diff --git a/asset/js/widget/Completer.js b/asset/js/widget/Completer.js index a11548a3..1596d331 100644 --- a/asset/js/widget/Completer.js +++ b/asset/js/widget/Completer.js @@ -6,6 +6,7 @@ define(["../notjQuery"], function ($) { constructor(input, instrumented = false) { this.input = input; this.instrumented = instrumented; + this.hasBeenManuallyChanged = false; // Flag to identify if the input has been manually changed. this.selectionStartInput = null; this.selectionActive = false; this.mouseSelectionActive = false; @@ -268,6 +269,8 @@ define(["../notjQuery"], function ($) { complete(input, value, data) { $(input).focus({ scripted: true }); + // Disable autosubmit for the input in non-instrumented mode if the input is completed. + this.hasBeenManuallyChanged = false; if (this.instrumented) { if (! Object.keys(data).length) { @@ -321,8 +324,12 @@ define(["../notjQuery"], function ($) { if (! stopAtEdge && this.completedValue !== null) { if (input === this.completedInput) { + // Re-enable autosubmit for the input in non-instrumented mode when the user moves from suggestions back to the input. + this.hasBeenManuallyChanged = true; this.suggest(this.completedInput, this.completedValue); } else { + // Disable the autosubmit for the input in non-instrumented mode while moving through suggestions. + this.hasBeenManuallyChanged = false; this.suggest(this.completedInput, input.value, { ...input.dataset }); } } @@ -476,6 +483,23 @@ define(["../notjQuery"], function ($) { } onFocusOut(event) { + if (! this.instrumented && this.shouldAutoSubmit()) { + setTimeout(() => { + // Autosubmit if the user leaves the input and the input has been manually changed. + // Only for non-instrumented mode — instrumented inputs (e.g. TermInput) handle + // autosubmit themselves via BaseInput.autoSubmit() with proper term data. + if ( + this.hasBeenManuallyChanged + && ! this.hasSuggestions() + ) { + // Reset this flag since the user has navigated away from the input and the submit event + // will be triggered by the input's form submit event handler. + this.hasBeenManuallyChanged = false; + $(this.input.form).trigger('submit', {submittedBy: this.input}); + } + }, 300); + } + if (this.completedInput === null) { // If there are multiple instances of Completer bound to the same suggestion container // all of them try to handle the event. Though, only one of them is responsible and @@ -495,6 +519,9 @@ define(["../notjQuery"], function ($) { if (input !== completedInput) { // Restore input if a suggestion lost focus this.suggest(completedInput, this.completedValue); + // This triggers the autosubmit if the user navigates away from the input for non-instrumented mode. + // as the input is reset to the manually changed value once suggestions are hidden. + this.hasBeenManuallyChanged = true; } this.hideSuggestions(); @@ -569,6 +596,8 @@ define(["../notjQuery"], function ($) { $(this.completedInput).focus({ scripted: true }); this.suggest(this.completedInput, this.completedValue); this.clearSelection(); + this.hasBeenManuallyChanged = true; + break; case 'Tab': event.preventDefault(); @@ -631,6 +660,15 @@ define(["../notjQuery"], function ($) { onKeyDown(event) { let suggestions; + const keys = ['Tab', 'ArrowDown', 'ArrowUp']; + if ( + ! this.instrumented + && keys.includes(event.key) + && this.hasSuggestions() + ) { + // Disable the autosubmit if the user navigates away from the input but is within the suggestions. + this.hasBeenManuallyChanged = false; + } switch (event.key) { case ' ': @@ -676,7 +714,7 @@ define(["../notjQuery"], function ($) { break; case 'Escape': if (this.hasSuggestions()) { - this.hideSuggestions() + this.hideSuggestions(); event.preventDefault(); } @@ -712,7 +750,6 @@ define(["../notjQuery"], function ($) { onInput(event) { let input = event.target; - if (input.minLength > 0 && input.value.length < input.minLength) { return; } @@ -730,6 +767,9 @@ define(["../notjQuery"], function ($) { dataElement.value = input.value; } + // This flag triggers the autosubmit if the user navigates away from the input for non-instrumented mode + // and the input has the manually changed value. + this.hasBeenManuallyChanged = true; let [value, data] = this.prepareCompletionData(input); this.completedInput = input; this.completedValue = value;