From dcc9611aec8216b0e9cb6e632a42cc6899191fa1 Mon Sep 17 00:00:00 2001 From: Martin Brennan Date: Fri, 16 Dec 2022 10:28:22 +1000 Subject: [PATCH] FIX: Scroll autocomplete container on arrow press (#19478) The autocomplete container has not needed to be scrolled with arrow keys until we introduced the new hashtag autocomplete, which shows more options and allows scrolling. This commit scrolls the options up/down when selecting an item outside the scroll with arrow keys. --- .../discourse/app/lib/autocomplete.js | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/discourse/app/lib/autocomplete.js b/app/assets/javascripts/discourse/app/lib/autocomplete.js index 60a529e16c5..f0602ae2269 100644 --- a/app/assets/javascripts/discourse/app/lib/autocomplete.js +++ b/app/assets/javascripts/discourse/app/lib/autocomplete.js @@ -117,6 +117,33 @@ export default function (options) { discourseLater(() => me.trigger("keydown"), 50); } + function scrollAutocomplete() { + if (!div) { + return; + } + + const divElement = div[0]; + const selectedElement = getSelectedOptionElement(); + const selectedElementTop = selectedElement.offsetTop; + const selectedElementBottom = + selectedElementTop + selectedElement.clientHeight; + + // the top of the item is above the top of the div, so scroll UP + if (selectedElementTop <= divElement.scrollTop) { + divElement.scrollTo(0, selectedElementTop); + + // the bottom of the item is below the bottom of the div, so scroll DOWN + } else if ( + selectedElementBottom >= + divElement.scrollTop + divElement.clientHeight + ) { + divElement.scrollTo( + 0, + divElement.scrollTop + selectedElement.clientHeight + ); + } + } + function closeAutocomplete() { _autoCompletePopper?.destroy(); @@ -288,9 +315,16 @@ export default function (options) { } function markSelected() { - const links = div.find("li a"); - links.removeClass("selected"); - return $(links[selectedOption]).addClass("selected"); + getLinks().removeClass("selected"); + return $(getSelectedOptionElement()).addClass("selected"); + } + + function getSelectedOptionElement() { + return getLinks()[selectedOption]; + } + + function getLinks() { + return div.find("li a"); } // a sane spot below cursor @@ -641,6 +675,7 @@ export default function (options) { selectedOption = 0; } markSelected(); + scrollAutocomplete(); e.preventDefault(); return false; case keys.downArrow: @@ -653,6 +688,7 @@ export default function (options) { selectedOption = 0; } markSelected(); + scrollAutocomplete(); e.preventDefault(); return false; case keys.backSpace: