Skip to content
44 changes: 42 additions & 2 deletions asset/js/widget/Completer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 });
}
}
Expand Down Expand Up @@ -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
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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 ' ':
Expand Down Expand Up @@ -676,7 +714,7 @@ define(["../notjQuery"], function ($) {
break;
case 'Escape':
if (this.hasSuggestions()) {
this.hideSuggestions()
this.hideSuggestions();
event.preventDefault();
}

Expand Down Expand Up @@ -712,7 +750,6 @@ define(["../notjQuery"], function ($) {

onInput(event) {
let input = event.target;

if (input.minLength > 0 && input.value.length < input.minLength) {
return;
}
Expand All @@ -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;
Expand Down
Loading