diff --git a/src/lib/components/Keyboard.ts b/src/lib/components/Keyboard.ts index fcfa45d2..eec3c3b6 100644 --- a/src/lib/components/Keyboard.ts +++ b/src/lib/components/Keyboard.ts @@ -45,6 +45,7 @@ class SimpleKeyboard { candidateBox!: CandidateBox | null; keyboardRowsDOM!: KeyboardElement; defaultName = "default"; + activeInputElement: HTMLInputElement | HTMLTextAreaElement | null = null; /** * Creates an instance of SimpleKeyboard @@ -404,6 +405,27 @@ class SimpleKeyboard { this.caretPositionEnd ); + /** + * EDGE CASE: Check for whole input selection changes that will yield same updatedInput + */ + if(this.utilities.isStandardButton(button) && this.activeInputElement){ + const isEntireInputSelection = ( + this.input[inputName] && + this.input[inputName] === updatedInput && + this.caretPosition === 0 && + this.caretPositionEnd === updatedInput.length + ); + + if(isEntireInputSelection){ + this.setInput("", this.options.inputName, true); + this.setCaretPosition(0); + this.activeInputElement.value = ""; + this.activeInputElement.setSelectionRange(0, 0); + this.handleButtonClicked(button, e); + return; + } + } + /** * Calling onKeyPress */ @@ -1090,6 +1112,11 @@ class SimpleKeyboard { event.target.selectionEnd ); + /** + * Tracking current input in order to handle caret positioning edge cases + */ + this.activeInputElement = event.target; + if (instance.options.debug) { console.log( "Caret at: ", @@ -1105,6 +1132,11 @@ class SimpleKeyboard { */ instance.setCaretPosition(null); + /** + * Resetting activeInputElement + */ + this.activeInputElement = null; + if (instance.options.debug) { console.log( `Caret position reset due to "${event?.type}" event`, @@ -1190,6 +1222,11 @@ class SimpleKeyboard { this.candidateBox = null; } + /** + * Clearing activeInputElement + */ + this.activeInputElement = null; + /** * Clearing keyboardDOM */ diff --git a/src/lib/components/tests/Keyboard.test.js b/src/lib/components/tests/Keyboard.test.js index f6e741d9..505ca9f9 100644 --- a/src/lib/components/tests/Keyboard.test.js +++ b/src/lib/components/tests/Keyboard.test.js @@ -1330,4 +1330,25 @@ it('Keyboard excludeFromLayout will work', () => { it('Keyboard onSetOptions can be called without changedOptions param', () => { const keyboard = new Keyboard(); expect(keyboard.onSetOptions()).toBeUndefined(); +}); + +it('Keyboard will handle selected input with unchanged updatedInput edge case', () => { + const inputElem = document.createElement("input"); + const onChange = jest.fn(); + const keyboard = new Keyboard({ onChange }); + + const initialValue = "3"; + inputElem.value = initialValue; + inputElem.select(); + keyboard.setInput(initialValue); + keyboard.activeInputElement = inputElem; + keyboard.setCaretPosition(0, 1); + + keyboard.getButtonElement("3").onpointerdown(); + keyboard.getButtonElement("3").onpointerdown(); + + expect(onChange).toBeCalledTimes(2); + expect(keyboard.getInput()).toBe("33"); + expect(keyboard.getCaretPosition()).toBe(2); + expect(keyboard.getCaretPositionEnd()).toBe(2); }); \ No newline at end of file diff --git a/src/lib/services/Utilities.ts b/src/lib/services/Utilities.ts index dac3feac..a9d96d61 100644 --- a/src/lib/services/Utilities.ts +++ b/src/lib/services/Utilities.ts @@ -299,6 +299,11 @@ class Utilities { return output; } + /** + * Check whether the button is a standard button + */ + isStandardButton = (button: string) => button && !(button[0] === "{" && button[button.length - 1] === "}"); + /** * Removes an amount of characters before a given position *