diff --git a/app/assets/javascripts/discourse/app/lib/autocomplete.js b/app/assets/javascripts/discourse/app/lib/autocomplete.js index f08ac17ee9d..202d8d4385e 100644 --- a/app/assets/javascripts/discourse/app/lib/autocomplete.js +++ b/app/assets/javascripts/discourse/app/lib/autocomplete.js @@ -94,6 +94,19 @@ export default function (options) { let div = null; let prevTerm = null; + // By default, when the autcomplete popup is rendered it has the + // first suggestion 'selected', and pressing enter key inserts + // the first suggestion into the input box. + // If you want to stop that behavior, i.e. have the popup renders + // with no suggestions selected, set the `autoSelectFirstSuggestion` + // option to false. + // With this option set to false, users will have to select + // a suggestion via the up/down arrow keys and then press enter + // to insert it. + if (!("autoSelectFirstSuggestion" in options)) { + options.autoSelectFirstSuggestion = true; + } + // input is handled differently const isInput = me[0].tagName === "INPUT" && !options.treatAsTextarea; let inputSelectedItems = []; @@ -187,7 +200,11 @@ export default function (options) { " " + text.substring(completeEnd + 1, text.length); me.val(text); - setCaretPosition(me[0], completeStart + 1 + term.length); + let newCaretPos = completeStart + 1 + term.length; + if (options.key) { + newCaretPos++; + } + setCaretPosition(me[0], newCaretPos); if (options && options.afterComplete) { options.afterComplete(text); @@ -276,8 +293,12 @@ export default function (options) { div = $(options.template({ options: autocompleteOptions })); let ul = div.find("ul"); - selectedOption = 0; - markSelected(); + if (options.autoSelectFirstSuggestion) { + selectedOption = 0; + markSelected(); + } else { + selectedOption = -1; + } ul.find("li").click(function () { selectedOption = ul.find("li").index(this); completeTerm(autocompleteOptions[selectedOption]); @@ -549,8 +570,8 @@ export default function (options) { // Keyboard codes! So 80's. switch (e.which) { case keys.enter: - case keys.tab: if (!autocompleteOptions) { + closeAutocomplete(); return true; } if ( @@ -583,6 +604,7 @@ export default function (options) { markSelected(); return false; case keys.backSpace: + autocompleteOptions = null; completeEnd = cp; cp--; @@ -606,6 +628,7 @@ export default function (options) { updateAutoComplete(dataSource(term, options)); return true; default: + autocompleteOptions = null; completeEnd = cp; return true; } diff --git a/app/assets/javascripts/discourse/app/lib/search.js b/app/assets/javascripts/discourse/app/lib/search.js index 0b0f9ecb2f6..e5b2002f0b9 100644 --- a/app/assets/javascripts/discourse/app/lib/search.js +++ b/app/assets/javascripts/discourse/app/lib/search.js @@ -220,6 +220,7 @@ export function applySearchAutocomplete( key: "#", width: "100%", treatAsTextarea: true, + autoSelectFirstSuggestion: false, transformComplete(obj) { return obj.text; }, @@ -240,6 +241,7 @@ export function applySearchAutocomplete( key: "@", width: "100%", treatAsTextarea: true, + autoSelectFirstSuggestion: false, transformComplete: (v) => v.username || v.name, dataSource: (term) => userSearch({ term, includeGroups: true }), afterComplete,