From be91be52b1111b00917602dafe407fcc37f3fb94 Mon Sep 17 00:00:00 2001 From: ilhan Date: Thu, 1 Oct 2020 18:44:13 +0300 Subject: [PATCH 1/2] fix(ui5-input): cancel suggestion selection with ESC --- packages/main/src/Input.js | 48 ++++++++++++++++++++++---- packages/main/test/pages/Input.html | 9 +++++ packages/main/test/specs/Input.spec.js | 20 +++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index 14c104087838..92969c03f4f9 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -11,6 +11,7 @@ import { isSpace, isEnter, isBackSpace, + isEscape, } from "@ui5/webcomponents-base/dist/Keys.js"; import Integer from "@ui5/webcomponents-base/dist/types/Integer.js"; import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; @@ -494,11 +495,20 @@ class Input extends UI5Element { // Indicates if there is selected suggestionItem. this.hasSuggestionItemSelected = false; - // Represents the value before user moves selection between the suggestion items. - // Used to register and fire "input" event upon [SPACE] or [ENTER]. - // Note: the property "value" is updated upon selection move and can`t be used. + // Represents the value before user moves selection from suggestion item to another + // and its value is updated after each move. + // Note: Used to register and fire "input" event upon [SPACE] or [ENTER]. + // Note: The property "value" is updated upon selection move and can`t be used. this.valueBeforeItemSelection = ""; + // Represents the value before user moves selection between the suggestion items + // and its value remains the same when the user navigates up or down the list. + // Note: Used to cancel selection upon [ESC]. + this.valueBeforeItemPreview = ""; + + // Indicates if the user selection has been canceled with [ESC]. + this.suggestionSelectionCanceled = false; + // tracks the value between focus in and focus out to detect that change event should be fired. this.previousValue = undefined; @@ -591,6 +601,10 @@ class Input extends UI5Element { return this._handleEnter(event); } + if (isEscape(event)) { + return this._handleEscape(event); + } + this._keyDown = true; } @@ -624,6 +638,20 @@ class Input extends UI5Element { } } + _handleEscape() { + if (this.Suggestions && this.Suggestions._isItemOnTarget()) { + // Restore the value. + this.value = this.valueBeforeItemPreview; + + // Mark that the selection has been canceled, so the popover can close + // and not reopen, due to receiving focus. + this.suggestionSelectionCanceled = true; + + // Close suggestion popover + this._closeRespPopover(true); + } + } + async _onfocusin(event) { const inputDomRef = await this.getInputDOMRef(); @@ -633,6 +661,7 @@ class Input extends UI5Element { this.focused = true; // invalidating property this.previousValue = this.value; + this.valueBeforeItemPreview = this.value; this._inputIconFocused = event.target && event.target === this.querySelector("[ui5-icon]"); } @@ -682,6 +711,8 @@ class Input extends UI5Element { async _handleInput(event) { const inputDomRef = await this.getInputDOMRef(); + this.suggestionSelectionCanceled = false; + if (this.value && this.type === InputType.Number && !isBackSpace(event) && !inputDomRef.value) { // For input with type="Number", if the delimiter is entered second time, the inner input is firing event with empty value return; @@ -711,8 +742,8 @@ class Input extends UI5Element { this._inputWidth = this.offsetWidth; } - _closeRespPopover() { - this.Suggestions.close(); + _closeRespPopover(preventFocusRestore) { + this.Suggestions.close(preventFocusRestore); } async _afterOpenPopover() { @@ -786,7 +817,8 @@ class Input extends UI5Element { return !!(this.suggestionItems.length && this.focused && this.showSuggestions - && !this.hasSuggestionItemSelected); + && !this.hasSuggestionItemSelected + && !this.suggestionSelectionCanceled); } selectSuggestion(item, keyboardUsed) { @@ -807,6 +839,9 @@ class Input extends UI5Element { this.fireEvent(this.EVENT_CHANGE); } + this.valueBeforeItemPreview = ""; + this.suggestionSelectionCanceled = false; + this.fireEvent(this.EVENT_SUGGESTION_ITEM_SELECT, { item }); } @@ -857,6 +892,7 @@ class Input extends UI5Element { this.value = inputValue; this.highlightValue = inputValue; + this.valueBeforeItemPreview = inputValue; if (isSafari()) { // When setting the value by hand, Safari moves the cursor when typing in the middle of the text (See #1761) diff --git a/packages/main/test/pages/Input.html b/packages/main/test/pages/Input.html index 2fc6cb900cfa..a3e5541fdcda 100644 --- a/packages/main/test/pages/Input.html +++ b/packages/main/test/pages/Input.html @@ -134,6 +134,15 @@

Input test change

Input test change result

+

Input test ESC

+ + + + + + + +

Input readonly

diff --git a/packages/main/test/specs/Input.spec.js b/packages/main/test/specs/Input.spec.js index c1455e201373..d11f89ab87ae 100644 --- a/packages/main/test/specs/Input.spec.js +++ b/packages/main/test/specs/Input.spec.js @@ -215,6 +215,26 @@ describe("Input general interaction", () => { assert.strictEqual(inputResult.getValue(), "1", "suggestionItemSelect is not fired as item is 'Inactive'"); }); + it("handles suggestions selection cancel with ESC", () => { + const suggestionsInput = $("#myInputEsc").shadow$("input"); + + // act + suggestionsInput.click(); + suggestionsInput.keys("ch"); + suggestionsInput.keys("ArrowDown"); + + // assert + assert.strictEqual(suggestionsInput.getValue(), "Chromium", + "The value is updated as the item has been previewed."); + + // act + suggestionsInput.keys("Escape"); + + // assert + assert.strictEqual(suggestionsInput.getValue(), "ch", + "The value is restored as ESC has been pressed."); + }); + it("handles group suggestion item via keyboard", () => { const suggestionsInput = $("#myInputGrouping").shadow$("input"); const inputResult = $("#inputResultGrouping").shadow$("input"); From 681bf8676784b4f08292a3bf52ad6c9da8249356 Mon Sep 17 00:00:00 2001 From: ilhan Date: Mon, 5 Oct 2020 13:57:09 +0300 Subject: [PATCH 2/2] add additional check for showSuggestions --- packages/main/src/Input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index 92969c03f4f9..b583edd3b73e 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -639,7 +639,7 @@ class Input extends UI5Element { } _handleEscape() { - if (this.Suggestions && this.Suggestions._isItemOnTarget()) { + if (this.showSuggestions && this.Suggestions && this.Suggestions._isItemOnTarget()) { // Restore the value. this.value = this.valueBeforeItemPreview;