feat(widgets): wire PostsNavs TOC shell to page-template scrollspy
Match built-in single sidebar .posts-nav-box.toc-widget/.toc-list so the sidebar widget is filled (≥3 headings), supports multiple TOC shells, and removes empty chrome.
This commit is contained in:
1 parent
5ab935f015
commit
c0b7cb504b
3 files changed
+108
-25
No files matched your search
@@ -364,6 +364,10 @@ html.dark .article-end-separator span {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.toc-list .toc-h1 a {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.toc-list .toc-h3 a {
|
||||
padding-left: 12px;
|
||||
}
|
||||
@@ -372,6 +376,30 @@ html.dark .article-end-separator span {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
/* WidgetPostsNavs + built-in shell share .posts-nav-box.toc-widget */
|
||||
.widget .posts-nav-box.toc-widget,
|
||||
.widget_aksrt_posts_navs .posts-nav-box.toc-widget {
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.widget .posts-nav-box.toc-widget > h3,
|
||||
.widget .posts-nav-box.toc-widget .toc-widget__title,
|
||||
.widget_aksrt_posts_navs .posts-nav-box.toc-widget > h3 {
|
||||
margin: 0 0 10px;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
body.single .sidebar .posts-nav-box.toc-widget.is-affix,
|
||||
body.single .sidebar .posts-nav-box.toc-widget[data-affix="true"] {
|
||||
position: sticky;
|
||||
top: calc(var(--nav-height, 60px) + 16px);
|
||||
}
|
||||
|
||||
.toc-float-btn {
|
||||
position: fixed;
|
||||
right: 18px;
|
||||
|
||||
+59
-17
@@ -19,9 +19,31 @@
|
||||
}
|
||||
|
||||
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;
|
||||
// Accept either explicit data-aksrt-toc="1" or any [data-nav] article body.
|
||||
var content =
|
||||
document.querySelector('.wp-posts-content[data-nav="posts"][data-aksrt-toc="1"]') ||
|
||||
document.querySelector('.wp-posts-content[data-nav]') ||
|
||||
document.querySelector('[data-nav="posts"]') ||
|
||||
document.querySelector('[data-nav]');
|
||||
|
||||
// Support multiple TOC shells (built-in single sidebar + WidgetPostsNavs).
|
||||
var tocWidgets = Array.prototype.slice.call(
|
||||
document.querySelectorAll('.posts-nav-box.toc-widget, .posts-nav-box[data-title]')
|
||||
);
|
||||
var tocLists = [];
|
||||
tocWidgets.forEach(function (box) {
|
||||
if (!box.classList.contains('toc-widget')) {
|
||||
box.classList.add('toc-widget');
|
||||
}
|
||||
var list = box.querySelector('.toc-list');
|
||||
if (!list) {
|
||||
list = document.createElement('ol');
|
||||
list.className = 'toc-list';
|
||||
box.appendChild(list);
|
||||
}
|
||||
tocLists.push(list);
|
||||
});
|
||||
|
||||
var mobileToggle = document.querySelector('.toc-float-btn');
|
||||
var drawer = document.querySelector('.toc-drawer');
|
||||
var overlay = document.querySelector('.toc-drawer-overlay');
|
||||
@@ -29,16 +51,25 @@
|
||||
var closeBtn = drawer ? drawer.querySelector('.toc-drawer__close') : null;
|
||||
|
||||
if (!content || content.dataset.aksrtTocBound === '1') return;
|
||||
if (!tocList && !drawerList && !mobileToggle) return;
|
||||
if (!tocLists.length && !drawerList && !mobileToggle) return;
|
||||
|
||||
content.dataset.aksrtTocBound = '1';
|
||||
|
||||
var maxDepth = parseInt(content.dataset.aksrtTocDepth || '3', 10) || 3;
|
||||
// zibll section-navs: only fill when heading count > 2 (≥3).
|
||||
var MIN_HEADINGS = 3;
|
||||
|
||||
function getHeadings() {
|
||||
return Array.prototype.slice.call(content.querySelectorAll('h2, h3, h4')).filter(function (heading) {
|
||||
// zibll scans h1–h4 inside [data-nav]; depth setting still caps lower levels.
|
||||
return Array.prototype.slice.call(content.querySelectorAll('h1, h2, h3, h4')).filter(function (heading) {
|
||||
if (heading.closest('.no-nav') || heading.classList.contains('item-heading')) {
|
||||
return false;
|
||||
}
|
||||
var level = parseInt((heading.tagName || 'H2').replace('H', ''), 10) || 2;
|
||||
return level <= maxDepth;
|
||||
// toc_depth is typically 2–4 meaning deepest heading level from h2 baseline;
|
||||
// allow h1 always, then h2..h(1+maxDepth) capped at h4.
|
||||
if (level === 1) return true;
|
||||
return level <= Math.min(4, maxDepth + 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -46,7 +77,7 @@
|
||||
if (!container) return false;
|
||||
|
||||
var headings = getHeadings();
|
||||
if (!headings.length) return false;
|
||||
if (headings.length < MIN_HEADINGS) return false;
|
||||
|
||||
var html = '';
|
||||
headings.forEach(function (heading) {
|
||||
@@ -55,7 +86,9 @@
|
||||
}
|
||||
|
||||
var levelClass = '';
|
||||
if (heading.tagName === 'H3') {
|
||||
if (heading.tagName === 'H1') {
|
||||
levelClass = 'toc-h1';
|
||||
} else if (heading.tagName === 'H3') {
|
||||
levelClass = 'toc-h3';
|
||||
} else if (heading.tagName === 'H4') {
|
||||
levelClass = 'toc-h4';
|
||||
@@ -68,13 +101,24 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
var hasToc = buildToc(tocList);
|
||||
if (drawerList && drawerList !== tocList) {
|
||||
buildToc(drawerList);
|
||||
var hasToc = false;
|
||||
tocLists.forEach(function (list) {
|
||||
if (buildToc(list)) hasToc = true;
|
||||
});
|
||||
if (drawerList && tocLists.indexOf(drawerList) === -1) {
|
||||
if (buildToc(drawerList)) hasToc = true;
|
||||
}
|
||||
|
||||
if (!hasToc) {
|
||||
if (tocWidget) tocWidget.remove();
|
||||
tocWidgets.forEach(function (box) {
|
||||
var host = box.closest('.widget') || box.parentElement;
|
||||
// Prefer removing the whole widget chrome when empty.
|
||||
if (host && host !== document.body && host.querySelectorAll('.posts-nav-box').length <= 1) {
|
||||
host.remove();
|
||||
} else {
|
||||
box.remove();
|
||||
}
|
||||
});
|
||||
if (mobileToggle) mobileToggle.remove();
|
||||
if (drawer) drawer.remove();
|
||||
if (overlay) overlay.remove();
|
||||
@@ -94,7 +138,7 @@
|
||||
}
|
||||
|
||||
function trackActiveHeading() {
|
||||
var headings = content.querySelectorAll('h2[id], h3[id], h4[id]');
|
||||
var headings = content.querySelectorAll('h1[id], h2[id], h3[id], h4[id]');
|
||||
if (!headings.length) return;
|
||||
|
||||
var activeId = '';
|
||||
@@ -117,10 +161,8 @@
|
||||
if (!target) return;
|
||||
|
||||
event.preventDefault();
|
||||
target.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
var top = target.getBoundingClientRect().top + window.pageYOffset - 105;
|
||||
window.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
|
||||
closeDrawer();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user