mirror of
https://github.com/go-gitea/gitea
synced 2025-07-05 18:17:19 +00:00
Fix dynamic content loading init problem (#33748)
1. Rewrite `dirauto.ts` to `observer.ts`. * We have been using MutationObserver for long time, it's proven that it is quite performant. * Now we extend its ability to handle more "init" works. 2. Use `observeAddedElement` to init all non-custom "dropdown". 3. Use `data-global-click` to handle click events from dynamically loaded elements. * By this new approach, the old fragile selector-based (`.comment-reaction-button`) mechanism is removed. 4. By the way, remove unused `.diff-box` selector, it was abused and never really used. A lot of FIXMEs in "repo-diff.ts" are completely fixed, newly loaded contents could work as expected.
This commit is contained in:
@ -2,6 +2,7 @@ import {GET} from '../modules/fetch.ts';
|
||||
import {showGlobalErrorMessage} from '../bootstrap.ts';
|
||||
import {fomanticQuery} from '../modules/fomantic/base.ts';
|
||||
import {queryElems} from '../utils/dom.ts';
|
||||
import {observeAddedElement} from '../modules/observer.ts';
|
||||
|
||||
const {appUrl} = window.config;
|
||||
|
||||
@ -28,47 +29,51 @@ export function initFootLanguageMenu() {
|
||||
}
|
||||
|
||||
export function initGlobalDropdown() {
|
||||
// Semantic UI modules.
|
||||
const $uiDropdowns = fomanticQuery('.ui.dropdown');
|
||||
|
||||
// do not init "custom" dropdowns, "custom" dropdowns are managed by their own code.
|
||||
$uiDropdowns.filter(':not(.custom)').dropdown({hideDividers: 'empty'});
|
||||
observeAddedElement('.ui.dropdown:not(.custom)', (el) => {
|
||||
const $dropdown = fomanticQuery(el);
|
||||
if ($dropdown.data('module-dropdown')) return; // do not re-init if other code has already initialized it.
|
||||
|
||||
// The "jump" means this dropdown is mainly used for "menu" purpose,
|
||||
// clicking an item will jump to somewhere else or trigger an action/function.
|
||||
// When a dropdown is used for non-refresh actions with tippy,
|
||||
// it must have this "jump" class to hide the tippy when dropdown is closed.
|
||||
$uiDropdowns.filter('.jump').dropdown('setting', {
|
||||
action: 'hide',
|
||||
onShow() {
|
||||
// hide associated tooltip while dropdown is open
|
||||
this._tippy?.hide();
|
||||
this._tippy?.disable();
|
||||
},
|
||||
onHide() {
|
||||
this._tippy?.enable();
|
||||
// eslint-disable-next-line unicorn/no-this-assignment
|
||||
const elDropdown = this;
|
||||
$dropdown.dropdown('setting', {hideDividers: 'empty'});
|
||||
|
||||
// hide all tippy elements of items after a while. eg: use Enter to click "Copy Link" in the Issue Context Menu
|
||||
setTimeout(() => {
|
||||
const $dropdown = fomanticQuery(elDropdown);
|
||||
if ($dropdown.dropdown('is hidden')) {
|
||||
queryElems(elDropdown, '.menu > .item', (el) => el._tippy?.hide());
|
||||
}
|
||||
}, 2000);
|
||||
},
|
||||
if (el.classList.contains('jump')) {
|
||||
// The "jump" means this dropdown is mainly used for "menu" purpose,
|
||||
// clicking an item will jump to somewhere else or trigger an action/function.
|
||||
// When a dropdown is used for non-refresh actions with tippy,
|
||||
// it must have this "jump" class to hide the tippy when dropdown is closed.
|
||||
$dropdown.dropdown('setting', {
|
||||
action: 'hide',
|
||||
onShow() {
|
||||
// hide associated tooltip while dropdown is open
|
||||
this._tippy?.hide();
|
||||
this._tippy?.disable();
|
||||
},
|
||||
onHide() {
|
||||
this._tippy?.enable();
|
||||
// eslint-disable-next-line unicorn/no-this-assignment
|
||||
const elDropdown = this;
|
||||
|
||||
// hide all tippy elements of items after a while. eg: use Enter to click "Copy Link" in the Issue Context Menu
|
||||
setTimeout(() => {
|
||||
const $dropdown = fomanticQuery(elDropdown);
|
||||
if ($dropdown.dropdown('is hidden')) {
|
||||
queryElems(elDropdown, '.menu > .item', (el) => el._tippy?.hide());
|
||||
}
|
||||
}, 2000);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Special popup-directions, prevent Fomantic from guessing the popup direction.
|
||||
// With default "direction: auto", if the viewport height is small, Fomantic would show the popup upward,
|
||||
// if the dropdown is at the beginning of the page, then the top part would be clipped by the window view.
|
||||
// eg: Issue List "Sort" dropdown
|
||||
// But we can not set "direction: downward" for all dropdowns, because there is a bug in dropdown menu positioning when calculating the "left" position,
|
||||
// which would make some dropdown popups slightly shift out of the right viewport edge in some cases.
|
||||
// eg: the "Create New Repo" menu on the navbar.
|
||||
if (el.classList.contains('upward')) $dropdown.dropdown('setting', 'direction', 'upward');
|
||||
if (el.classList.contains('downward')) $dropdown.dropdown('setting', 'direction', 'downward');
|
||||
});
|
||||
|
||||
// Special popup-directions, prevent Fomantic from guessing the popup direction.
|
||||
// With default "direction: auto", if the viewport height is small, Fomantic would show the popup upward,
|
||||
// if the dropdown is at the beginning of the page, then the top part would be clipped by the window view.
|
||||
// eg: Issue List "Sort" dropdown
|
||||
// But we can not set "direction: downward" for all dropdowns, because there is a bug in dropdown menu positioning when calculating the "left" position,
|
||||
// which would make some dropdown popups slightly shift out of the right viewport edge in some cases.
|
||||
// eg: the "Create New Repo" menu on the navbar.
|
||||
$uiDropdowns.filter('.upward').dropdown('setting', 'direction', 'upward');
|
||||
$uiDropdowns.filter('.downward').dropdown('setting', 'direction', 'downward');
|
||||
}
|
||||
|
||||
export function initGlobalTabularMenu() {
|
||||
|
Reference in New Issue
Block a user