diff --git a/front/src/Phaser/Components/TextInput.ts b/front/src/Phaser/Components/TextInput.ts index 1e01029b..9dbe5d6c 100644 --- a/front/src/Phaser/Components/TextInput.ts +++ b/front/src/Phaser/Components/TextInput.ts @@ -1,7 +1,9 @@ +import {HtmlUtils} from "../../WebRtc/HtmlUtils"; export class TextInput extends Phaser.GameObjects.BitmapText { private minUnderLineLength = 4; private underLine: Phaser.GameObjects.Text; + private onChange: (text: string) => void; constructor(scene: Phaser.Scene, x: number, y: number, maxLength: number, text: string, onChange: (text: string) => void) { super(scene, x, y, 'main_font', text, 32); @@ -10,19 +12,30 @@ export class TextInput extends Phaser.GameObjects.BitmapText { this.underLine = this.scene.add.text(x, y+1, this.getUnderLineBody(text.length), { fontFamily: 'Arial', fontSize: "32px", color: '#ffffff'}) this.underLine.setOrigin(0.5) + this.onChange = onChange; + // Use a hidden input field so that on mobile browsers the virtual + // keyboard will be displayed + const mainContainer = HtmlUtils.getElementByIdOrFail('main-container'); + const inputElement = document.createElement('input'); + inputElement.id = 'playerName'; + inputElement.maxLength = maxLength + // Make sure that now scolling is needed and that the input field is + // not visible + inputElement.setAttribute('style', 'opacity:0;position:absolute;top:0'); + mainContainer.appendChild(inputElement); - this.scene.input.keyboard.on('keydown', (event: KeyboardEvent) => { - if (event.keyCode === 8 && this.text.length > 0) { - this.deleteLetter(); - } else if ((event.keyCode === 32 || (event.keyCode >= 48 && event.keyCode <= 90)) && this.text.length < maxLength) { - this.addLetter(event.key); - } - this.underLine.text = this.getUnderLineBody(this.text.length); - onChange(this.text); - }); + inputElement.addEventListener('input', this.onInput.bind(this) as EventListener); } - + + private onInput(event: InputEvent) { + const inputElement = event.target; + // Truncate the text to the maximum length, this is needed for mobile + // browsers that don't support the input field `maxLength` attribute + this.text = inputElement.value.substr(0, inputElement.maxLength) + this.onChange(this.text); + } + private getUnderLineBody(textLength:number): string { if (textLength < this.minUnderLineLength) textLength = this.minUnderLineLength; let text = '_______'; @@ -32,15 +45,6 @@ export class TextInput extends Phaser.GameObjects.BitmapText { return text; } - private deleteLetter() { - this.text = this.text.substr(0, this.text.length - 1); - } - - - private addLetter(letter: string) { - this.text += letter; - } - getText(): string { return this.text; } diff --git a/front/src/Phaser/Login/LoginScene.ts b/front/src/Phaser/Login/LoginScene.ts index 9ca6dcd2..a57eac5f 100644 --- a/front/src/Phaser/Login/LoginScene.ts +++ b/front/src/Phaser/Login/LoginScene.ts @@ -1,3 +1,4 @@ +import {HtmlUtils} from "../../WebRtc/HtmlUtils"; import {gameManager} from "../Game/GameManager"; import {TextField} from "../Components/TextField"; import {TextInput} from "../Components/TextInput"; @@ -41,6 +42,22 @@ export class LoginScene extends ResizableScene { this.name = text; }); + // Mobile Browsers need an input field, so that a virtual keyboard + // gets shown + const nameInputElement = HtmlUtils.getElementByIdOrFail('playerName'); + // As we need an input field for mobile browsers, use it also for + // the desktop. Therefore make sure that is has the focus when the page + // is loaded, so that all keyboard events are handled by that input + // field. + nameInputElement.focus() + // Mobile browsers won't show the virtual keyboard on page load, hence + // re-focus to make it pop up. On desktop browsers it doesn't do any + // harm. + this.input.on('pointerdown', () => { + nameInputElement.blur(); + nameInputElement.focus(); + }); + this.pressReturnField = new TextField(this, this.game.renderer.width / 2, 130, 'Press enter to start'); this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon); @@ -55,6 +72,11 @@ export class LoginScene extends ResizableScene { } this.login(this.name); }); + + this.events.on('destroy', () => { + // Make sure the virtual keyboard isn't visible in the next scene + nameInputElement.blur() + }) } update(time: number, delta: number): void {