(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(); } })();