fix(nav): stop dual overflow folders fighting on insertBefore
Remove legacy initNavOverflow from enhancements.js (core/nav.js owns zibll navFolding). Harden clearFolding against detached more nodes and skip counting existing .aksrt-nav-more during fold measurement.
This commit is contained in:
+39
-10
@@ -18,16 +18,42 @@
|
||||
}
|
||||
|
||||
function clearFolding() {
|
||||
var more = document.querySelector(".navbar-nav > li.aksrt-nav-more");
|
||||
if (!more) return;
|
||||
var sub = more.querySelector(".sub-menu");
|
||||
var nav = more.parentNode;
|
||||
if (sub && nav) {
|
||||
while (sub.firstChild) {
|
||||
nav.insertBefore(sub.firstChild, more);
|
||||
// Support both zibll-style more and any legacy .aksrt-nav-more nodes.
|
||||
var mores = document.querySelectorAll(".navbar-nav > li.aksrt-nav-more");
|
||||
Array.prototype.forEach.call(mores, function (more) {
|
||||
var nav = more.parentNode;
|
||||
if (!nav) {
|
||||
more.remove();
|
||||
return;
|
||||
}
|
||||
}
|
||||
more.remove();
|
||||
// Prefer direct child .sub-menu (zibll contract); fall back to first matching submenu.
|
||||
var sub = null;
|
||||
for (var i = 0; i < more.children.length; i++) {
|
||||
var child = more.children[i];
|
||||
if (
|
||||
child.tagName === "UL" &&
|
||||
(child.classList.contains("sub-menu") ||
|
||||
child.classList.contains("aksrt-nav-more__dropdown"))
|
||||
) {
|
||||
sub = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sub) {
|
||||
sub = more.querySelector(".sub-menu, .aksrt-nav-more__dropdown");
|
||||
}
|
||||
if (sub) {
|
||||
while (sub.firstChild) {
|
||||
// Guard: only insertBefore when more is still a child of nav.
|
||||
if (more.parentNode === nav) {
|
||||
nav.insertBefore(sub.firstChild, more);
|
||||
} else {
|
||||
nav.appendChild(sub.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
more.remove();
|
||||
});
|
||||
}
|
||||
|
||||
function navFolding() {
|
||||
@@ -53,6 +79,7 @@
|
||||
var navsWidth = 66;
|
||||
var foldItems = [];
|
||||
Array.prototype.forEach.call(nav.children, function (li) {
|
||||
if (li.classList.contains("aksrt-nav-more")) return;
|
||||
navsWidth += li.offsetWidth || 0;
|
||||
if (navsWidth > surplus) foldItems.push(li);
|
||||
});
|
||||
@@ -63,7 +90,9 @@
|
||||
more.innerHTML =
|
||||
'<a href="javascript:void(0);"><i class="fas fa-bars" aria-hidden="true"></i></a><ul class="sub-menu"></ul>';
|
||||
var sub = more.querySelector(".sub-menu");
|
||||
foldItems.forEach(function (li) { sub.appendChild(li); });
|
||||
foldItems.forEach(function (li) {
|
||||
if (li && li.parentNode) sub.appendChild(li);
|
||||
});
|
||||
nav.appendChild(more);
|
||||
appendChevrons(more);
|
||||
}
|
||||
|
||||
@@ -521,83 +521,11 @@
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 4. 导航溢出自动折叠
|
||||
* 菜单项超出容器宽度时折叠进「更多」下拉
|
||||
* 4. 导航溢出折叠
|
||||
* 由 assets/js/core/nav.js(zibll 1:1 navFolding)负责。
|
||||
* 此处不再重复实现,避免两套逻辑争抢 .aksrt-nav-more 节点
|
||||
* 触发 NotFoundError: insertBefore (moreLi 已被对方 remove)。
|
||||
* ============================================================ */
|
||||
function initNavOverflow() {
|
||||
var nav = document.querySelector('.navbar-top .nav.navbar-nav');
|
||||
if (!nav) return;
|
||||
|
||||
// 创建「更多」按钮
|
||||
var moreLi = document.createElement('li');
|
||||
moreLi.className = 'nav-item aksrt-nav-more';
|
||||
moreLi.style.display = 'none';
|
||||
moreLi.innerHTML =
|
||||
'<button type="button" class="aksrt-nav-more__btn" aria-haspopup="true" aria-expanded="false">更多 <i class="fas fa-caret-down"></i></button>' +
|
||||
'<ul class="aksrt-nav-more__dropdown"></ul>';
|
||||
nav.appendChild(moreLi);
|
||||
|
||||
var moreBtn = moreLi.querySelector('.aksrt-nav-more__btn');
|
||||
var dropdown = moreLi.querySelector('.aksrt-nav-more__dropdown');
|
||||
|
||||
moreBtn.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
var open = dropdown.classList.toggle('is-open');
|
||||
moreBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
|
||||
});
|
||||
|
||||
document.addEventListener('click', function () {
|
||||
dropdown.classList.remove('is-open');
|
||||
moreBtn.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
function checkOverflow() {
|
||||
var items = Array.from(nav.children).filter(function (el) {
|
||||
return !el.classList.contains('aksrt-nav-more');
|
||||
});
|
||||
|
||||
// 重置:把所有项移回原位
|
||||
while (dropdown.firstChild) {
|
||||
var li = dropdown.firstChild;
|
||||
nav.insertBefore(li, moreLi);
|
||||
}
|
||||
moreLi.style.display = 'none';
|
||||
|
||||
var navWidth = nav.clientWidth;
|
||||
var moreWidth = 80; // 预留「更多」按钮宽度
|
||||
var usedWidth = 0;
|
||||
var overflowItems = [];
|
||||
|
||||
items.forEach(function (item) {
|
||||
usedWidth += item.offsetWidth;
|
||||
if (usedWidth + moreWidth > navWidth) {
|
||||
overflowItems.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
if (overflowItems.length > 0) {
|
||||
moreLi.style.display = '';
|
||||
overflowItems.forEach(function (item) {
|
||||
dropdown.appendChild(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ResizeObserver 监听(避免 resize 抖动)
|
||||
if ('ResizeObserver' in window) {
|
||||
var timer = null;
|
||||
var ro = new ResizeObserver(function () {
|
||||
if (timer) clearTimeout(timer);
|
||||
timer = setTimeout(checkOverflow, 100);
|
||||
});
|
||||
ro.observe(nav);
|
||||
} else {
|
||||
window.addEventListener('resize', checkOverflow, { passive: true });
|
||||
}
|
||||
|
||||
// 初始检测
|
||||
checkOverflow();
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 初始化入口
|
||||
@@ -605,7 +533,6 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
initLightbox();
|
||||
initScrollDirection();
|
||||
initNavOverflow();
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user