diff --git a/extensions/embed/js/src/forum/index.js b/extensions/embed/js/src/forum/index.js index f858688120..75a6290897 100644 --- a/extensions/embed/js/src/forum/index.js +++ b/extensions/embed/js/src/forum/index.js @@ -36,7 +36,7 @@ app.pageInfo = Stream({}); const reposition = function () { const info = app.pageInfo(); - this.$().css('top', Math.max(0, info.scrollTop - info.offsetTop)); + this.element.style.top = Math.max(0, info.scrollTop - info.offsetTop) + 'px'; }; extend(ModalManager.prototype, 'show', reposition); @@ -50,7 +50,7 @@ window.iFrameResizer = { extend('flarum/forum/components/PostStream', 'goToNumber', function (promise, number) { if (number === 'reply' && 'parentIFrame' in window && app.composer.isFullScreen()) { - const itemTop = this.$('.PostStream-item:last').offset().top; + const itemTop = this.element.getBoundingClientRect().top + document.documentElement.scrollTop; window.parentIFrame.scrollToOffset(0, itemTop); } }); diff --git a/extensions/emoji/js/src/forum/addComposerAutocomplete.js b/extensions/emoji/js/src/forum/addComposerAutocomplete.js index 7d6df93903..120341bd74 100644 --- a/extensions/emoji/js/src/forum/addComposerAutocomplete.js +++ b/extensions/emoji/js/src/forum/addComposerAutocomplete.js @@ -24,7 +24,8 @@ export default function addComposerAutocomplete() { extend('flarum/common/components/TextEditor', 'onbuild', function () { this.emojiDropdown = new AutocompleteDropdown(); - const $editor = this.$('.TextEditor-editor').wrap('
'); + const editor = this.element.querySelector('.TextEditor-editor'); + editor.outerHTML = `
${editor.outerHTML}
`; this.navigator = new KeyboardNavigatable(); this.navigator @@ -33,9 +34,9 @@ export default function addComposerAutocomplete() { .onDown(() => this.emojiDropdown.navigate(1)) .onSelect(this.emojiDropdown.complete.bind(this.emojiDropdown)) .onCancel(this.emojiDropdown.hide.bind(this.emojiDropdown)) - .bindTo($editor); + .bindTo(editor); - $editor.after($('
')); + editor.outerHTML = editor.outerHTML + '
'; }); extend('flarum/common/components/TextEditor', 'buildEditorParams', function (params) { @@ -134,27 +135,28 @@ export default function addComposerAutocomplete() { if (suggestions.length) { this.emojiDropdown.items = suggestions; - m.render(this.$('.ComposerBody-emojiDropdownContainer')[0], this.emojiDropdown.render()); + m.render(this.element.querySelector('.ComposerBody-emojiDropdownContainer'), this.emojiDropdown.render()); this.emojiDropdown.show(); const coordinates = this.attrs.composer.editor.getCaretCoordinates(autocompleting.absoluteStart); - const width = this.emojiDropdown.$().outerWidth(); - const height = this.emojiDropdown.$().outerHeight(); - const parent = this.emojiDropdown.$().offsetParent(); + const rect = this.emojiDropdown.element.getBoundingClientRect(); + const width = rect.width; + const height = rect.height; + const parent = this.emojiDropdown.element.offsetParent; let left = coordinates.left; let top = coordinates.top + 15; // Keep the dropdown inside the editor. - if (top + height > parent.height()) { + if (top + height > parent.clientHeight) { top = coordinates.top - height - 15; } - if (left + width > parent.width()) { - left = parent.width() - width; + if (left + width > parent.clientWidth) { + left = parent.clientWidth - width; } // Prevent the dropdown from going off screen on mobile - top = Math.max(-(parent.offset().top - $(document).scrollTop()), top); - left = Math.max(-parent.offset().left, left); + top = Math.max(-(parent.getBoundingClientRect().top), top); + left = Math.max(-parent.getBoundingClientRect().left + document.documentElement.scrollLeft, left); this.emojiDropdown.show(left, top); } @@ -163,7 +165,7 @@ export default function addComposerAutocomplete() { buildSuggestions(); this.emojiDropdown.setIndex(0); - this.emojiDropdown.$().scrollTop(0); + this.emojiDropdown.element.scrollTo({ top: 0 }); this.emojiDropdown.active = true; } }); diff --git a/extensions/emoji/js/src/forum/fragments/AutocompleteDropdown.js b/extensions/emoji/js/src/forum/fragments/AutocompleteDropdown.js index e4f27921e3..086b56821d 100644 --- a/extensions/emoji/js/src/forum/fragments/AutocompleteDropdown.js +++ b/extensions/emoji/js/src/forum/fragments/AutocompleteDropdown.js @@ -18,17 +18,15 @@ export default class AutocompleteDropdown extends Fragment { } show(left, top) { - this.$() - .show() - .css({ - left: left + 'px', - top: top + 'px', - }); + const style = this.element.style; + style.display = 'block'; + style.left = left + 'px'; + style.top = top + 'px'; this.active = true; } hide() { - this.$().hide(); + this.element.style.display = 'none'; this.active = false; } @@ -40,42 +38,51 @@ export default class AutocompleteDropdown extends Fragment { } complete() { - this.$('li:not(.Dropdown-header)').eq(this.index).find('button').click(); + this.element.querySelectorAll('li:not(.Dropdown-header)')[this.index].querySelector('button').click(); } + // todo: check if copied implementation matches the original behavior setIndex(index, scrollToItem) { if (this.keyWasJustPressed && !scrollToItem) return; - const $dropdown = this.$(); - const $items = $dropdown.find('li:not(.Dropdown-header)'); + const dropdown = this.element; + const items = dropdown.querySelectorAll('li:not(.Dropdown-header)'); let rangedIndex = index; if (rangedIndex < 0) { - rangedIndex = $items.length - 1; - } else if (rangedIndex >= $items.length) { + rangedIndex = items.length - 1; + } else if (rangedIndex >= items.length) { rangedIndex = 0; } this.index = rangedIndex; - const $item = $items.removeClass('active').eq(rangedIndex).addClass('active'); + items.forEach((el) => el.classList.remove('active')); + const item = items[rangedIndex]; + item.classList.add('active'); if (scrollToItem) { - const dropdownScroll = $dropdown.scrollTop(); - const dropdownTop = $dropdown.offset().top; - const dropdownBottom = dropdownTop + $dropdown.outerHeight(); - const itemTop = $item.offset().top; - const itemBottom = itemTop + $item.outerHeight(); + const documentScrollTop = document.documentElement.scrollTop; + const dropdownScroll = dropdown.scrollTop; + const dropdownRect = dropdown.getBoundingClientRect(); + const dropdownTop = dropdownRect.top + documentScrollTop; + const dropdownBottom = dropdownTop + dropdownRect.height; + const itemRect = item.getBoundingClientRect(); + const itemTop = itemRect.top + documentScrollTop; + const itemBottom = itemTop + itemRect.height; let scrollTop; if (itemTop < dropdownTop) { - scrollTop = dropdownScroll - dropdownTop + itemTop - parseInt($dropdown.css('padding-top'), 10); + scrollTop = dropdownScroll - dropdownTop + itemTop - parseInt(getComputedStyle(dropdown).paddingTop, 10); } else if (itemBottom > dropdownBottom) { - scrollTop = dropdownScroll - dropdownBottom + itemBottom + parseInt($dropdown.css('padding-bottom'), 10); + scrollTop = dropdownScroll - dropdownBottom + itemBottom + parseInt(getComputedStyle(dropdown).paddingBottom, 10); } if (typeof scrollTop !== 'undefined') { - $dropdown.stop(true).animate({ scrollTop }, 100); + dropdown.scrollTo({ + top: scrollTop, + behavior: 'smooth', + }); } } }