fix(nav): portal publish menu so chip cannot stretch
Move multi-type 发布 menu to document.body with fixed positioning; chip uses fit-content only and never inherits the 168px menu width.
This commit is contained in:
1 parent
57fa97bf9b
commit
b7ee5987f0
4 files changed
+306
-43
No files matched your search
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* Header multi-type publish menu: portal dropdown to document.body.
|
||||
*
|
||||
* Keeps the pink chip content-sized. The menu is position:fixed under the
|
||||
* toggle and never participates in the chip's layout width.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var openRoot = null;
|
||||
var openMenu = null;
|
||||
var openToggle = null;
|
||||
var closeTimer = null;
|
||||
|
||||
function clearCloseTimer() {
|
||||
if (closeTimer) {
|
||||
clearTimeout(closeTimer);
|
||||
closeTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function placeMenu(toggle, menu) {
|
||||
var rect = toggle.getBoundingClientRect();
|
||||
var menuWidth = 168;
|
||||
var left = rect.right - menuWidth;
|
||||
if (left < 8) left = 8;
|
||||
if (left + menuWidth > window.innerWidth - 8) {
|
||||
left = Math.max(8, window.innerWidth - menuWidth - 8);
|
||||
}
|
||||
menu.style.position = 'fixed';
|
||||
menu.style.top = Math.round(rect.bottom + 6) + 'px';
|
||||
menu.style.left = Math.round(left) + 'px';
|
||||
menu.style.right = 'auto';
|
||||
menu.style.width = menuWidth + 'px';
|
||||
menu.style.minWidth = menuWidth + 'px';
|
||||
menu.style.maxWidth = menuWidth + 'px';
|
||||
menu.style.zIndex = '2000';
|
||||
}
|
||||
|
||||
function closeMenu() {
|
||||
clearCloseTimer();
|
||||
if (!openMenu) return;
|
||||
openMenu.classList.remove('is-open');
|
||||
openMenu.setAttribute('hidden', '');
|
||||
openMenu.setAttribute('aria-hidden', 'true');
|
||||
if (openToggle) openToggle.setAttribute('aria-expanded', 'false');
|
||||
if (openRoot) openRoot.classList.remove('is-open');
|
||||
// Return menu to original root so SSR structure stays consistent.
|
||||
if (openRoot && openMenu.parentNode !== openRoot) {
|
||||
openRoot.appendChild(openMenu);
|
||||
}
|
||||
openRoot = null;
|
||||
openMenu = null;
|
||||
openToggle = null;
|
||||
}
|
||||
|
||||
function openMenuFor(root) {
|
||||
var toggle = root.querySelector('.newadd-btns__toggle');
|
||||
var menu = root.querySelector('.drop-newadd');
|
||||
if (!toggle || !menu) return;
|
||||
|
||||
if (openRoot && openRoot !== root) closeMenu();
|
||||
|
||||
clearCloseTimer();
|
||||
openRoot = root;
|
||||
openMenu = menu;
|
||||
openToggle = toggle;
|
||||
|
||||
if (menu.parentNode !== document.body) {
|
||||
document.body.appendChild(menu);
|
||||
}
|
||||
menu.removeAttribute('hidden');
|
||||
menu.setAttribute('aria-hidden', 'false');
|
||||
menu.classList.add('is-open');
|
||||
root.classList.add('is-open');
|
||||
toggle.setAttribute('aria-expanded', 'true');
|
||||
placeMenu(toggle, menu);
|
||||
}
|
||||
|
||||
function scheduleClose() {
|
||||
clearCloseTimer();
|
||||
closeTimer = setTimeout(closeMenu, 160);
|
||||
}
|
||||
|
||||
function onPointerEnterRoot(e) {
|
||||
var root = e.currentTarget;
|
||||
openMenuFor(root);
|
||||
}
|
||||
|
||||
function onPointerLeaveRoot() {
|
||||
scheduleClose();
|
||||
}
|
||||
|
||||
function onPointerEnterMenu() {
|
||||
clearCloseTimer();
|
||||
}
|
||||
|
||||
function onPointerLeaveMenu() {
|
||||
scheduleClose();
|
||||
}
|
||||
|
||||
function onToggleClick(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var root = e.currentTarget.closest('[data-aksrt-newadd="1"]');
|
||||
if (!root) return;
|
||||
if (openRoot === root) {
|
||||
closeMenu();
|
||||
} else {
|
||||
openMenuFor(root);
|
||||
}
|
||||
}
|
||||
|
||||
function onDocPointerDown(e) {
|
||||
if (!openRoot) return;
|
||||
if (openRoot.contains(e.target)) return;
|
||||
if (openMenu && openMenu.contains(e.target)) return;
|
||||
closeMenu();
|
||||
}
|
||||
|
||||
function onKey(e) {
|
||||
if (e.key === 'Escape') closeMenu();
|
||||
}
|
||||
|
||||
function onScrollOrResize() {
|
||||
if (!openToggle || !openMenu) return;
|
||||
placeMenu(openToggle, openMenu);
|
||||
}
|
||||
|
||||
function bindRoot(root) {
|
||||
if (root.getAttribute('data-aksrt-newadd-bound') === '1') return;
|
||||
root.setAttribute('data-aksrt-newadd-bound', '1');
|
||||
|
||||
var toggle = root.querySelector('.newadd-btns__toggle');
|
||||
var menu = root.querySelector('.drop-newadd');
|
||||
if (!toggle || !menu) return;
|
||||
|
||||
// CSS hover no longer drives this control.
|
||||
root.classList.add('is-js-portal');
|
||||
|
||||
root.addEventListener('mouseenter', onPointerEnterRoot);
|
||||
root.addEventListener('mouseleave', onPointerLeaveRoot);
|
||||
toggle.addEventListener('click', onToggleClick);
|
||||
toggle.addEventListener('focus', function () {
|
||||
openMenuFor(root);
|
||||
});
|
||||
|
||||
menu.addEventListener('mouseenter', onPointerEnterMenu);
|
||||
menu.addEventListener('mouseleave', onPointerLeaveMenu);
|
||||
}
|
||||
|
||||
function init() {
|
||||
document.querySelectorAll('[data-aksrt-newadd="1"]').forEach(bindRoot);
|
||||
document.addEventListener('pointerdown', onDocPointerDown, true);
|
||||
document.addEventListener('keydown', onKey);
|
||||
window.addEventListener('scroll', onScrollOrResize, true);
|
||||
window.addEventListener('resize', onScrollOrResize);
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user