Ui调整
This commit is contained in:
@@ -1,160 +0,0 @@
|
||||
(function () {
|
||||
const DESKTOP_COLLAPSE_LIMIT = 10;
|
||||
const MOBILE_COLLAPSE_LIMIT = 8;
|
||||
|
||||
function initApplicationPage() {
|
||||
const page = document.querySelector(".application-page");
|
||||
if (!page) return;
|
||||
|
||||
const tabsNav = page.querySelector(".app-category-tabs");
|
||||
const tabs = page.querySelectorAll(".app-category-tab");
|
||||
const sections = page.querySelectorAll(".app-list-section[data-total]");
|
||||
if (!tabs.length || !sections.length) return;
|
||||
|
||||
let isProgrammaticScroll = false;
|
||||
let scrollTimer = null;
|
||||
|
||||
function isDesktop() {
|
||||
return window.matchMedia("(min-width: 768px)").matches;
|
||||
}
|
||||
|
||||
function getCollapseLimit() {
|
||||
return isDesktop() ? DESKTOP_COLLAPSE_LIMIT : MOBILE_COLLAPSE_LIMIT;
|
||||
}
|
||||
|
||||
function getScrollOffset() {
|
||||
const header = document.querySelector(".site-header");
|
||||
const barHeight = (header && header.getBoundingClientRect().height) || (isDesktop() ? 72 : 56);
|
||||
return barHeight + (isDesktop() ? 24 : 12);
|
||||
}
|
||||
|
||||
function getSectionAnchor(section) {
|
||||
return section.querySelector(".app-list-section__head") || section;
|
||||
}
|
||||
|
||||
function setActiveTab(activeTab) {
|
||||
tabs.forEach((tab) => {
|
||||
const isActive = tab === activeTab;
|
||||
tab.classList.toggle("app-category-tab--active", isActive);
|
||||
tab.setAttribute("aria-selected", isActive ? "true" : "false");
|
||||
});
|
||||
}
|
||||
|
||||
function updateActionButton(button, expanded, limit) {
|
||||
const label = button.querySelector(".app-list-section__more-label");
|
||||
const icon = button.querySelector(".app-list-section__more-icon");
|
||||
const total = Number(button.dataset.total) || 0;
|
||||
const hiddenCount = Math.max(total - limit, 0);
|
||||
|
||||
if (label) {
|
||||
label.textContent = expanded ? "收起" : `显示全部${hiddenCount}个站点`;
|
||||
}
|
||||
if (icon) {
|
||||
icon.classList.toggle("app-list-section__more-icon--up", expanded);
|
||||
}
|
||||
button.setAttribute("aria-expanded", expanded ? "true" : "false");
|
||||
}
|
||||
|
||||
function updateCollapseSections() {
|
||||
const limit = getCollapseLimit();
|
||||
|
||||
page.querySelectorAll(".app-list-section[data-total]").forEach((section) => {
|
||||
const total = Number(section.dataset.total) || 0;
|
||||
const button = section.querySelector(".app-list-section__more");
|
||||
const needsCollapse = total > limit;
|
||||
|
||||
section.classList.toggle("app-list-section--collapsible", needsCollapse);
|
||||
|
||||
if (!needsCollapse) {
|
||||
section.classList.remove("app-list-section--expanded");
|
||||
}
|
||||
|
||||
if (button) {
|
||||
button.hidden = !needsCollapse;
|
||||
if (needsCollapse) {
|
||||
updateActionButton(button, section.classList.contains("app-list-section--expanded"), limit);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function scrollTabIntoView(tab) {
|
||||
if (!tabsNav || !tab) return;
|
||||
const navRect = tabsNav.getBoundingClientRect();
|
||||
const tabRect = tab.getBoundingClientRect();
|
||||
const nextLeft = tabsNav.scrollLeft + (tabRect.left - navRect.left) - (navRect.width - tabRect.width) / 2;
|
||||
tabsNav.scrollTo({ left: Math.max(0, nextLeft), behavior: "smooth" });
|
||||
}
|
||||
|
||||
function scrollToSection(section) {
|
||||
if (!section) return;
|
||||
const anchor = getSectionAnchor(section);
|
||||
const top = anchor.getBoundingClientRect().top + window.scrollY - getScrollOffset();
|
||||
isProgrammaticScroll = true;
|
||||
clearTimeout(scrollTimer);
|
||||
window.scrollTo({ top: Math.max(0, top), behavior: "smooth" });
|
||||
scrollTimer = window.setTimeout(() => {
|
||||
isProgrammaticScroll = false;
|
||||
}, 800);
|
||||
}
|
||||
|
||||
tabs.forEach((tab, index) => {
|
||||
if (!tab.hasAttribute("aria-selected")) {
|
||||
tab.setAttribute("aria-selected", index === 0 ? "true" : "false");
|
||||
}
|
||||
|
||||
tab.addEventListener("click", () => {
|
||||
const targetId = tab.dataset.target;
|
||||
if (!targetId) return;
|
||||
|
||||
setActiveTab(tab);
|
||||
scrollTabIntoView(tab);
|
||||
scrollToSection(document.getElementById(targetId));
|
||||
});
|
||||
});
|
||||
|
||||
page.querySelectorAll(".app-list-section__more").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
const section = button.closest(".app-list-section");
|
||||
if (!section || button.hidden) return;
|
||||
|
||||
const expanded = section.classList.toggle("app-list-section--expanded");
|
||||
updateActionButton(button, expanded, getCollapseLimit());
|
||||
});
|
||||
});
|
||||
|
||||
updateCollapseSections();
|
||||
window.addEventListener("resize", updateCollapseSections);
|
||||
|
||||
if (!("IntersectionObserver" in window)) return;
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (isProgrammaticScroll) return;
|
||||
|
||||
const visible = entries
|
||||
.filter((entry) => entry.isIntersecting)
|
||||
.sort((a, b) => b.intersectionRatio - a.intersectionRatio);
|
||||
|
||||
if (!visible.length) return;
|
||||
|
||||
const activeTab = page.querySelector(`.app-category-tab[data-target="${visible[0].target.id}"]`);
|
||||
if (activeTab) {
|
||||
setActiveTab(activeTab);
|
||||
}
|
||||
},
|
||||
{
|
||||
rootMargin: `-${getScrollOffset()}px 0px -55% 0px`,
|
||||
threshold: [0, 0.25, 0.5, 0.75, 1],
|
||||
}
|
||||
);
|
||||
|
||||
sections.forEach((section) => observer.observe(section));
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initApplicationPage);
|
||||
} else {
|
||||
initApplicationPage();
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user