From fc0e7fe802304ccd3e0770e2bc27af346c41ff53 Mon Sep 17 00:00:00 2001 From: Osama Sayegh Date: Fri, 2 Jun 2023 19:55:00 +0300 Subject: [PATCH] FIX: Ensure mention autocomplete box doesn't go off-screen in RTL locales (#21905) Meta topic: https://meta.discourse.org/t/mention-suggestion-list-box-in-the-rtl-website-in-wrong-place/266763?u=osama. Our autocomplete box doesn't currently take into account the user's locale and places itself off-screen when using an RTL locale. This commit changes the placement logic for the autocomplete box when an RTL locale is used to make sure that: 1. the autocomplete box's right side is near and to the left of the caret 2. the autocomplete box doesn't go beyond the composer's left side. --- .../discourse/app/lib/autocomplete.js | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/discourse/app/lib/autocomplete.js b/app/assets/javascripts/discourse/app/lib/autocomplete.js index dbd999a65e2..7744844c322 100644 --- a/app/assets/javascripts/discourse/app/lib/autocomplete.js +++ b/app/assets/javascripts/discourse/app/lib/autocomplete.js @@ -6,6 +6,7 @@ import Site from "discourse/models/site"; import { createPopper } from "@popperjs/core"; import discourseDebounce from "discourse-common/lib/debounce"; import { iconHTML } from "discourse-common/lib/icon-library"; +import { isDocumentRTL } from "discourse/lib/text-direction"; /** This is a jQuery plugin to support autocompleting values in our text fields. @@ -420,20 +421,14 @@ export default function (options) { } let vOffset = 0; - let hOffset = 0; let pos = me.caretPosition({ pos: completeStart + 1, }); - hOffset = 10; if (options.treatAsTextarea) { vOffset = -32; } - div.css({ - left: "-1000px", - }); - if (!isInput && !options.treatAsTextarea) { vOffset = div.height(); @@ -446,34 +441,39 @@ export default function (options) { vOffset = BELOW; } + if (Site.currentProp("mobileView") && me.height() / 2 >= pos.top) { + vOffset = BELOW; + } + } + + const mePos = me.position(); + + let left; + if (isDocumentRTL()) { + left = mePos.left + pos.left - div.width(); + } else { + let hOffset = 10; if (Site.currentProp("mobileView")) { - if (me.height() / 2 >= pos.top) { - vOffset = BELOW; - } if (me.width() / 2 <= pos.left) { hOffset = -div.width(); } } + left = mePos.left + pos.left + hOffset; } - - let mePos = me.position(); - - let borderTop = parseInt(me.css("border-top-width"), 10) || 0; - - let left = mePos.left + pos.left + hOffset; if (left < 0) { left = 0; } const offsetTop = me.offset().top; + const borderTop = parseInt(me.css("border-top-width"), 10) || 0; if (mePos.top + pos.top + borderTop - vOffset + offsetTop < 30) { vOffset = BELOW; } div.css({ position: "absolute", - top: mePos.top + pos.top - vOffset + borderTop + "px", - left: left + "px", + top: `${mePos.top + pos.top - vOffset + borderTop}px`, + left: `${left}px`, }); }