求助:如何让带折叠功能的目录在页面加载时自动展开当前章节
目录折叠功能:页面加载自动展开当前章节的修复方案
我在网页中使用层级目录,通过CSS为标记了toc-current-section类的当前章节(该类可能出现在目录任意层级)添加边框。为实现目录折叠功能,编写了对应的JavaScript脚本和CSS样式,但遇到页面加载时当前章节无法自动展开的问题。
最初尝试新增脚本逻辑,给对应元素添加faq-clicked类——虽然类成功添加,但目录仍处于折叠状态。排查后发现:原折叠脚本是为子级li元素而非ol元素切换faq-clicked类,修改为给o[t].firstElementChild切换该类后,问题得以解决。
HTML片段
<ol> ... </ol> <ol> <li><a href="#">Public Host Server</a> <ol class="toc-collapse-level"> <li><a href="#">Host Server</a> <ol> <li class="toc-current-section"><a href="#">Hyper-V Configuration</a> <ol> <li><a href="#s1">Host Network Settings and Status</a></li> <li><a href="#s2">Disk and VM Configuration Locations</a></li> <li><a href="#s3">Virtual Switch Configuration</a></li> <li><a href="#s4">Installed Virtual Servers</a></li> <li><a href="#s5">Web Servers and Reverse Proxy Server VM Network Adapter Settings</a></li> </ol> </li> </ol> </li> <li> <ol> <li><a>...</a> <ol> <li><a>...</a></li> <li><a>...</a></li> <li><a>...</a></li> </ol> </li> </ol> </li> </ol> </li> </ol> <ol> ... </ol>
JavaScript脚本
(t => { const e = "faq-list", n = "faq-clicked"; function l(l, o) { const i = l.children; if (0 === i.length) return; for (let t of i) if (t.childElementCount < 2) return; let c = l.classList; if (c.length > 0 && !c.contains(e)) return; c.add(e); const s = t.createElement("span"); let a = !1; s.className = "faq-button", s.innerText = "⊕", s.onclick = function() { a = !a, this.innerText = a ? "⊖" : "⊕"; for (const t of l.children) t.classList.toggle(n, a) }, l.before(s); for (let t = 0; t < i.length; t++) { let e = i[t]; e.id = "faq-" + (o ? o + "-" : "") + (t + 1); let l = e.firstElementChild; l.insertAdjacentHTML("beforeend", ` <span class="anchor"><a href="#${e.id}">#</a></span>`), location.hash === "#" + e.id && (e.scrollIntoView(), e.classList.add(n)), l.onclick = function(t) { e.classList.toggle(n) } } } // 新增:判断元素是否在视口内 function isElementVisible(el) { var rect = el.getBoundingClientRect(), vWidth = window.innerWidth || document.documentElement.clientWidth, vHeight = window.innerHeight || document.documentElement.clientHeight, efp = function (x, y) { return document.elementFromPoint(x, y) }; // 元素完全不在视口内返回false if (rect.right < 0 || rect.bottom < 0 || rect.left > vWidth || rect.top > vHeight) return false; // 元素任意一个角在视口内则返回true return ( el.contains(efp(rect.left, rect.top)) || el.contains(efp(rect.right, rect.top)) || el.contains(efp(rect.right, rect.bottom)) || el.contains(efp(rect.left, rect.bottom)) ); } const o = t.querySelectorAll(["div", "main", "section", "article"].map((t => t + ":not(.footnotes) > ol")).join(",")); for (let t = 0; t < o.length; t++) { l(o[t], o.length > 1 ? t + 1 : 0) if(isElementVisible(o[t])){ // 获取一级ol元素 tocSectionL1_ol = o[t].firstElementChild.childNodes[2]; // 获取一级ol下的li元素 tocSectionL1_li = tocSectionL1_ol.firstElementChild; // 获取二级ol元素 tocSectionL2_ol = tocSectionL1_li.childNodes[2]; // 获取二级ol下的li元素 tocSectionL2_li = tocSectionL2_ol.firstElementChild; // 获取li元素的类名 tocSectionL1_li_class = tocSectionL1_li.className; tocSectionL2_li_class = tocSectionL2_li.className; // 检查是否有li包含当前章节类 if((tocSectionL1_li_class || tocSectionL2_li_class) == "toc-current-section") { // 关键修复:给正确的元素切换折叠类 o[t].firstElementChild.classList.toggle("faq-clicked"); } } } })(document);
CSS样式
.faq-button { cursor: pointer } .faq-list>li>:first-child { display: block; cursor: pointer; background: #fafafa; margin: -.5em; padding: .5em } .faq-list>:not(.faq-clicked)>* { display: none } .faq-button { float: right; margin-left: 1em } .faq-list .anchor { display: none } .faq-list>li:hover .anchor { display: inline } .faq-list>li { border: 1px solid #eee; padding: .5em }
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

