feat(nav): complete remaining zibll parity (search, i18n, senior menus, CSS)

- Remove obsolete dual-path nav CSS; add utilities + language dropdown styles
- Wire header/mobile translate switcher from i18n config
- Layout-2 inline search hot keywords panel; nav_folding on resize
- NavMenuOptions JSON editors for graphic_card / multi_column_links
- Section-navs zibll posts-nav-lists; page-navs enqueue; mobile article TOC box
- SPA/PHP user-card publish type; rebuild admin assets
This commit is contained in:
kate522 committed 2026-07-22 11:40:17 +08:00
1 parent 259dbdbe04
commit fc50e57bc9
22 files changed
+580 -1994

No files matched your search

+51 -24
View File
@@ -1,13 +1,15 @@
/**
* AKSRT nav chrome — zibll contract (body.mobile-navbar-show, folding, chevron).
* Drawer open/close is handled by aksrt-runtime [data-toggle-class].
* AKSRT nav chrome — zibll contract (folding, chevron, language, drawer a11y).
* Drawer open/close via aksrt-runtime [data-toggle-class] → body.mobile-navbar-show.
*/
(function () {
"use strict";
function appendChevrons() {
document.querySelectorAll(".navbar-top li.menu-item-has-children > a").forEach(function (a) {
if (a.querySelector(".fa-angle-down")) return;
var foldTimer = null;
function appendChevrons(root) {
(root || document).querySelectorAll(".navbar-top li.menu-item-has-children > a").forEach(function (a) {
if (a.querySelector(".fa-angle-down, .fas.fa-angle-down")) return;
var i = document.createElement("i");
i.className = "fa fa-angle-down ml6";
i.setAttribute("aria-hidden", "true");
@@ -15,18 +17,30 @@
});
}
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);
}
}
more.remove();
}
function navFolding() {
var collapse = document.querySelector(".navbar-collapse");
var nav = document.querySelector(".navbar-nav");
if (!collapse || !nav) return;
if (window.innerWidth <= 996) return;
clearFolding();
if (window.innerWidth <= 996) return;
var header = document.querySelector(".header");
if (header && header.offsetHeight <= 81) return;
// Already folded?
if (nav.querySelector("li.aksrt-nav-more")) return;
var surplus = collapse.clientWidth;
Array.prototype.forEach.call(collapse.children, function (child) {
if (!child.classList.contains("navbar-nav")) {
@@ -40,9 +54,7 @@
var foldItems = [];
Array.prototype.forEach.call(nav.children, function (li) {
navsWidth += li.offsetWidth || 0;
if (navsWidth > surplus) {
foldItems.push(li);
}
if (navsWidth > surplus) foldItems.push(li);
});
if (!foldItems.length) return;
@@ -51,14 +63,33 @@
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) { sub.appendChild(li); });
nav.appendChild(more);
appendChevrons(more);
}
function scheduleFold() {
if (foldTimer) clearTimeout(foldTimer);
foldTimer = setTimeout(function () {
try { navFolding(); } catch (e) {}
}, 80);
}
function bindLanguage() {
document.addEventListener("click", function (e) {
var btn = e.target && e.target.closest ? e.target.closest(".translate-button[data-language]") : null;
if (!btn) return;
e.preventDefault();
var lang = btn.getAttribute("data-language");
if (!lang) return;
try { localStorage.setItem("aksrt_lang", lang); } catch (err) {}
var url = new URL(window.location.href);
url.searchParams.set("lang", lang);
window.location.href = url.toString();
});
}
function bindDrawerA11y() {
// Esc closes mobile nav via body class.
document.addEventListener("keydown", function (e) {
if (e.key === "Escape" && document.body.classList.contains("mobile-navbar-show")) {
document.body.classList.remove("mobile-navbar-show");
@@ -68,18 +99,14 @@
function init() {
appendChevrons();
try {
navFolding();
} catch (err) {
// ignore fold failures
}
scheduleFold();
bindLanguage();
bindDrawerA11y();
window.addEventListener("resize", scheduleFold, { passive: true });
}
if (window.AksrtFrontend && typeof window.AksrtFrontend.register === "function") {
window.AksrtFrontend.register("aksrt-nav-chrome", function () {
init();
});
window.AksrtFrontend.register("aksrt-nav-chrome", function () { init(); });
} else if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {