diff options
Diffstat (limited to 'web_src/js/features/common-page.ts')
-rw-r--r-- | web_src/js/features/common-page.ts | 105 |
1 files changed, 67 insertions, 38 deletions
diff --git a/web_src/js/features/common-page.ts b/web_src/js/features/common-page.ts index 56c5915b6d..5a02ee7a6a 100644 --- a/web_src/js/features/common-page.ts +++ b/web_src/js/features/common-page.ts @@ -2,6 +2,8 @@ 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 {registerGlobalInitFunc, registerGlobalSelectorFunc} from '../modules/observer.ts'; +import {initAvatarUploaderWithCropper} from './comp/Cropper.ts'; const {appUrl} = window.config; @@ -28,51 +30,78 @@ 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'}); + registerGlobalSelectorFunc('.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. - $uiDropdowns.filter('.upward').dropdown('setting', 'direction', 'upward'); - $uiDropdowns.filter('.downward').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. + if (el.classList.contains('upward')) $dropdown.dropdown('setting', 'direction', 'upward'); + if (el.classList.contains('downward')) $dropdown.dropdown('setting', 'direction', 'downward'); + }); } export function initGlobalTabularMenu() { - fomanticQuery('.ui.menu.tabular:not(.custom) .item').tab({autoTabActivation: false}); + fomanticQuery('.ui.menu.tabular:not(.custom) .item').tab(); +} + +export function initGlobalAvatarUploader() { + registerGlobalInitFunc('initAvatarUploader', initAvatarUploaderWithCropper); +} + +// for performance considerations, it only uses performant syntax +function attachInputDirAuto(el: Partial<HTMLInputElement | HTMLTextAreaElement>) { + if (el.type !== 'hidden' && + el.type !== 'checkbox' && + el.type !== 'radio' && + el.type !== 'range' && + el.type !== 'color') { + el.dir = 'auto'; + } +} + +export function initGlobalInput() { + registerGlobalSelectorFunc('input, textarea', attachInputDirAuto); + registerGlobalInitFunc('initInputAutoFocusEnd', (el: HTMLInputElement) => { + el.focus(); // expects only one such element on one page. If there are many, then the last one gets the focus. + el.setSelectionRange(el.value.length, el.value.length); + }); } /** |