【发布时间】:2020-06-14 23:26:36
【问题描述】:
问题
您好,我正在创建一个简单的导航站点,并且想知道如何更改/添加一个类到右侧的内联 toc 的 li 元素之一,以使用 css 对其进行样式化
到目前为止我的页面。
https://startech-enterprises.github.io/docs/data-integration-and-etl/branches-and-loops-local.html
我想要实现的页面行为: https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/intro-to-csharp/branches-and-loops-local
(如果你在主页面上下滚动,你会看到右侧toc元素的样式发生了变化)
在这里可以看到相同的行为: https://startech-enterprises.github.io/minimal-mistakes/docs/quick-start-guide/ (上下滚动页面时,请参阅右侧目录更改)
我尝试研究这些页面背后的 JavaScript,但很难理解,而且脚本看起来过于复杂。
有什么想法吗?
谢谢,
萨钦
注意 - 问题已得到解答,上面链接中的代码已更新,基于下面给出的答案
使用的代码
我目前拥有的 CSS:
.doc-outline ul li a {
text-decoration: none;
}
.doc-outline ul li a:hover {
text-decoration: underline;
}
.doc-outline li.selected {
font-weight: 600;
border-color: #0065b3;
}
.doc-outline a:visited {
color: #0065b3;
}
HTML 的相关部分
<div class="primary-holder column is-two-thirds-tablet is-three-quarters-desktop">
<div class="columns has-large-gaps is-gapless-mobile">
<!-- MAIN CONTENT GOES HERE --!>
<div id="main-column" class="column is-full is-four-fifths-desktop">
<main id="main" class ="content" lang="eng-us">
<h1 id="learn-conditional-logic-with-branch-and-loop-statements">Learn conditional logic with branch and loop statements</h1>.....etc.
</main>
</div>
<!-- RHS TOC GOES HERE --!>
<div class="right-sidebar column is-one-quarter is-one-fifth-desktop is-hidden-mobile is-hidden-tablet-only">
<nav class="doc-outline is-fixed is-vertically-scrollable", id="affixed-right-sidebar">
<nav id="side-doc-outline">
<ul class="section-nav">
<li class="toc-entry toc-h2"><a href="#make-decisions-using-the-if-statement">Make decisions using the if statement</a></li>
<li class="toc-entry toc-h2"><a href="#make-if-and-else-work-together">Make if and else work together</a></li>
<li class="toc-entry toc-h2"><a href="#use-loops-to-repeat-operations">Use loops to repeat operations</a></li>
<li class="toc-entry toc-h2"><a href="#work-with-the-for-loop">Work with the for loop</a></li>
<li class="toc-entry toc-h2"><a href="#created-nested-loops">Created nested loops</a>
<ul>
<li class="toc-entry toc-h3"><a href="#test">Test</a></li>
</ul>
</li>
<li class="toc-entry toc-h2"><a href="#combine-branches-and-loops">Combine branches and loops</a></li>
</ul>
</nav>
</nav>
</div>
</div>
</div>
JavaScript
编辑(上面链接中使用的最终 JS,结合了下面答案中的想法/cmets)- 可能简化一些代码块的范围..
突出显示正确的 RHS TOC 菜单项
(function rhsToc() {
// initialise global variables outside functions
let observer = new IntersectionObserver(handler, { threshold: [0] });
let selection;
let headings = [...document.querySelectorAll("#main h2, #main h3")];
let rhsToc = [...document.querySelectorAll("ul.section-nav a")];
let a = null;
let lastScroll = 0;
let headingMenuMap = headings.reduce((acc, h) => {
let id = h.id;
acc[id] = rhsToc.find(a => a.getAttribute("href") === "#" + id);
return acc;
}, {})
headings.forEach(elem => observer.observe(elem));
// detect scroll direction
scrollDetect();
let scrollDirection = [];
function scrollDetect(){
var lastScroll = 0;
window.onscroll = function() {
let currentScroll = document.documentElement.scrollTop || document.body.scrollTop; // Get Current Scroll Value
if (currentScroll > 0 && lastScroll <= currentScroll){
lastScroll = currentScroll;
scrollDirection = "down";
}else{
lastScroll = currentScroll;
scrollDirection = "up"
}
};
}
function handler(entries) {
// Update selection with current entries.
selection = (selection || entries).map( s => entries.find(e => e.target.id === s.target.id) || s);
// keep only true values
filteredArr = selection.filter(x => x.isIntersecting == true );
// Find last visible/intersecting (use a copied array for that, since reverse is an in place method)
let firstVisibleId = [...selection].find(x => x.isIntersecting) ? [...selection].find(x => x.isIntersecting).target.id : null;
// Is a firstVisibleId returned? If not, then follow the below steps
if (firstVisibleId === null){
// were you scrolling down? - then do nothing
if (scrollDirection == "down"){
// do nothing!
} else {
// scrolling up - so remove 'selected' from current menu item, and add it to the menu item above it
const current = document.querySelector(`#side-doc-outline > ul li.selected`);
if (current) {
current.classList.remove('selected');
}
// if there is no previous sibling with a class of 'toc-entry', you're at top of branch, so go up a level, provided you don't get to section-nav
if(previousByClass(a.parentElement, "toc-entry") == null){
parent_by_selector(a.parentElement, "ul:not(.section-nav)") ? parent_by_selector(a.parentElement, "ul:not(.section-nav)").parentElement.classList.add("selected") : null;
} else {
previousByClass(a.parentElement, "toc-entry") ? previousByClass(a.parentElement, "toc-entry").classList.add("selected") : null;
}
}
return;
}
// otherwise, remove 'selected' from the active item in the RHS toc
const current = document.querySelector(`#side-doc-outline > ul li.selected`);
if (current) {
current.classList.remove('selected');
}
// add 'selected' to the target item in the RHS toc
for (s of selection) {
let targetId = s.target.id;
// get the entry from the generated map.
a = headingMenuMap[targetId];
if (firstVisibleId === targetId) {
a.parentElement.classList.add("selected");
return;
}
};
}
})();
// WAIT TILL DOCUMENT HAS LOADED BEFORE INITIATING FUNCTIONS
document.addEventListener('DOMContentLoaded', tree);
【问题讨论】:
-
试试 jQuery toggleClass 或 addClass
-
问题解决了一半。除了我的页面,与docs.microsoft.com/en-us/dotnet/csharp/tutorials/… 的行为不太一样(例如,当视口中有两个 h2/h3 时,或者对于较长的部分,h2/h3 标签从视口中消失)
-
问题完全基于 cmets 解决,来自 Paul 下面
标签: javascript html css