/** * AKSRT Page Template * * Handles template-scoped content interactions: TOC, lightbox, * expandable article bodies, and one-shot query cleanup banners. * * @package AKSRT */ (function () { 'use strict'; function slugifyHeading(text) { return 'heading-' + String(text || '') .trim() .toLowerCase() .replace(/\s+/g, '-') .replace(/[^\w\u4e00-\u9fff-]/g, ''); } function initPostToc() { var content = document.querySelector('.wp-posts-content[data-nav="posts"][data-aksrt-toc="1"]'); var tocWidget = document.querySelector('.posts-nav-box.toc-widget'); var tocList = tocWidget ? tocWidget.querySelector('.toc-list') : null; var mobileToggle = document.querySelector('.toc-float-btn'); var drawer = document.querySelector('.toc-drawer'); var overlay = document.querySelector('.toc-drawer-overlay'); var drawerList = drawer ? drawer.querySelector('.toc-list') : null; var closeBtn = drawer ? drawer.querySelector('.toc-drawer__close') : null; if (!content || content.dataset.aksrtTocBound === '1') return; if (!tocList && !drawerList && !mobileToggle) return; content.dataset.aksrtTocBound = '1'; var maxDepth = parseInt(content.dataset.aksrtTocDepth || '3', 10) || 3; function getHeadings() { return Array.prototype.slice.call(content.querySelectorAll('h2, h3, h4')).filter(function (heading) { var level = parseInt((heading.tagName || 'H2').replace('H', ''), 10) || 2; return level <= maxDepth; }); } function buildToc(container) { if (!container) return false; var headings = getHeadings(); if (!headings.length) return false; var html = ''; headings.forEach(function (heading) { if (!heading.id) { heading.id = slugifyHeading(heading.textContent); } var levelClass = ''; if (heading.tagName === 'H3') { levelClass = 'toc-h3'; } else if (heading.tagName === 'H4') { levelClass = 'toc-h4'; } html += '' + heading.textContent.trim() + ''; }); container.innerHTML = html; return true; } var hasToc = buildToc(tocList); if (drawerList && drawerList !== tocList) { buildToc(drawerList); } if (!hasToc) { if (tocWidget) tocWidget.remove(); if (mobileToggle) mobileToggle.remove(); if (drawer) drawer.remove(); if (overlay) overlay.remove(); return; } function closeDrawer() { if (drawer) drawer.classList.remove('is-open'); if (overlay) overlay.classList.remove('is-open'); document.body.style.overflow = ''; } function openDrawer() { if (drawer) drawer.classList.add('is-open'); if (overlay) overlay.classList.add('is-open'); document.body.style.overflow = 'hidden'; } function trackActiveHeading() { var headings = content.querySelectorAll('h2[id], h3[id], h4[id]'); if (!headings.length) return; var activeId = ''; var fromTop = window.scrollY + 120; for (var i = headings.length - 1; i >= 0; i -= 1) { if (headings[i].offsetTop <= fromTop) { activeId = headings[i].id; break; } } document.querySelectorAll('.toc-list a').forEach(function (link) { link.classList.toggle('is-active', link.getAttribute('href') === '#' + activeId); }); } document.querySelectorAll('.toc-list a').forEach(function (link) { link.addEventListener('click', function (event) { var target = document.querySelector(link.getAttribute('href')); if (!target) return; event.preventDefault(); target.scrollIntoView({ behavior: 'smooth', block: 'start' }); closeDrawer(); }); }); if (mobileToggle) mobileToggle.addEventListener('click', openDrawer); if (overlay) overlay.addEventListener('click', closeDrawer); if (closeBtn) closeBtn.addEventListener('click', closeDrawer); window.addEventListener('scroll', trackActiveHeading, { passive: true }); trackActiveHeading(); } function initLightbox() { var overlay = document.getElementById('lightbox-overlay'); var content = document.querySelector(".entry-content[data-aksrt-lightbox='1']"); if (!overlay || !content || overlay.dataset.aksrtLightboxBound === '1') return; overlay.dataset.aksrtLightboxBound = '1'; var image = overlay.querySelector('.lightbox-img'); var caption = overlay.querySelector('.lightbox-caption'); var closeBtn = overlay.querySelector('.lightbox-close'); function close() { overlay.classList.remove('is-open'); document.body.style.overflow = ''; if (image) { image.src = ''; image.alt = ''; } } content.querySelectorAll('img').forEach(function (img) { img.style.cursor = 'zoom-in'; img.addEventListener('click', function () { if (!image) return; image.src = img.src; image.alt = img.alt || ''; if (caption) { var figure = img.closest('figure'); var figureCaption = figure ? figure.querySelector('figcaption') : null; caption.textContent = img.alt || (figureCaption ? figureCaption.textContent : '') || ''; } overlay.classList.add('is-open'); document.body.style.overflow = 'hidden'; }); }); overlay.addEventListener('click', function (event) { if (event.target === overlay || event.target === closeBtn) { close(); } }); if (closeBtn) { closeBtn.addEventListener('click', close); } document.addEventListener('keydown', function (event) { if (event.key === 'Escape' && overlay.classList.contains('is-open')) { close(); } }); } function initContentExpand() { document.querySelectorAll('.entry-content[data-nav]').forEach(function (content) { if (content.dataset.aksrtExpandBound === '1') return; content.dataset.aksrtExpandBound = '1'; // Only expand when server enabled maxheight (data-maxheight > 0). var customMax = parseInt(content.getAttribute('data-maxheight') || content.dataset.maxheight || '0', 10); if (!(customMax > 0)) return; var limit = customMax; if (content.scrollHeight <= limit) { content.classList.remove('limit-height'); content.style.maxHeight = ''; return; } content.classList.add('limit-height'); content.style.maxHeight = limit + 'px'; var existingBtn = content.nextElementSibling; if (existingBtn && existingBtn.classList && existingBtn.classList.contains('content-expand-btn')) { return; } var button = document.createElement('button'); button.type = 'button'; button.className = 'content-expand-btn'; button.innerHTML = ' 展开阅读全文'; content.parentNode.insertBefore(button, content.nextSibling); button.addEventListener('click', function () { var expanded = content.classList.contains('is-expanded'); if (expanded) { content.classList.remove('is-expanded'); content.style.maxHeight = limit + 'px'; button.classList.remove('is-expanded'); button.querySelector('span').textContent = '展开阅读全文'; content.scrollIntoView({ behavior: 'smooth', block: 'start' }); return; } content.classList.add('is-expanded'); content.style.maxHeight = content.scrollHeight + 'px'; button.classList.add('is-expanded'); button.querySelector('span').textContent = '收起'; }); }); } function initFlashQueryCleanup() { document.querySelectorAll('[data-aksrt-flash-query]').forEach(function (node) { var queryKey = node.getAttribute('data-aksrt-flash-query'); if (!queryKey || !window.history || typeof window.history.replaceState !== 'function') return; var url = new URL(window.location.href); if (!url.searchParams.has(queryKey)) return; url.searchParams.delete(queryKey); window.history.replaceState({}, '', url.toString()); }); } function init() { initPostToc(); initLightbox(); initContentExpand(); initFlashQueryCleanup(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();