From d62c32ba71c0d036269da0cef7effeba8398f91e Mon Sep 17 00:00:00 2001 From: Joffrey JAFFEUX Date: Mon, 26 Aug 2024 18:32:52 +0200 Subject: [PATCH] FIX: allows selectText to take a scroll position as opt (#28554) Prior to this fix using: - `replaceText(...)` - `selectText(..., ..., { scroll: true})` Wouldn't have the expected behaviour as the scroll from selectText will attempt to save the scroll position and restore it AFTER the replacement happened. This commit allows scroll to be a Boolean or a Number, when a number, it will be used to restore the scrollTop position. I tried to write tests for this specific behavior but couldn't reproduce the issue in tests. --- .../app/mixins/textarea-text-manipulation.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/discourse/app/mixins/textarea-text-manipulation.js b/app/assets/javascripts/discourse/app/mixins/textarea-text-manipulation.js index 84fcff21eb1..fe1122aa7f5 100644 --- a/app/assets/javascripts/discourse/app/mixins/textarea-text-manipulation.js +++ b/app/assets/javascripts/discourse/app/mixins/textarea-text-manipulation.js @@ -114,11 +114,13 @@ export default Mixin.create({ if (!this.element) { return; } - this._textarea.selectionStart = from; this._textarea.selectionEnd = from + length; - if (opts.scroll) { - const oldScrollPos = this._textarea.scrollTop; + if (opts.scroll === true || typeof opts.scroll === "number") { + const oldScrollPos = + typeof opts.scroll === "number" + ? opts.scroll + : this._textarea.scrollTop; if (!this.capabilities.isIOS) { this._textarea.focus(); } @@ -578,6 +580,7 @@ export default Mixin.create({ let autocompletePrefix = `${indentationLevel}${newPrefix}`; let autocompletePostfix = text.substring(offset); const autocompletePrefixLength = autocompletePrefix.length; + let scrollPosition; /* For numeric items, we have to also replace the rest of the @@ -598,6 +601,7 @@ export default Mixin.create({ numericBullet + 1 ); autocompletePrefix += autocompletePostfix; + scrollPosition = this._textarea.scrollTop; this.replaceText( text.substring(offset, offset + autocompletePrefix.length), @@ -610,7 +614,9 @@ export default Mixin.create({ this._insertAt(offset, offset, autocompletePrefix); } - this.selectText(offset + autocompletePrefixLength, 0); + this.selectText(offset + autocompletePrefixLength, 0, { + scroll: scrollPosition, + }); } else { // Clear the new autocompleted list item if there is no other text. const offsetWithoutPrefix = offset - `\n${listPrefix}`.length;