45 lines
1.2 KiB
JavaScript
45 lines
1.2 KiB
JavaScript
document.addEventListener("DOMContentLoaded", () => {
|
|
const toc = document.querySelector("article > nav#toc");
|
|
const content = document.querySelector("article > div#content");
|
|
|
|
if (!toc || !content) {
|
|
return;
|
|
}
|
|
|
|
const links = Array.from(toc.querySelectorAll('a[href^="#"]'));
|
|
const sections = Array.from(content.querySelectorAll("section[id]"));
|
|
|
|
if (!links.length || !sections.length) {
|
|
return;
|
|
}
|
|
|
|
const linksById = new Map(
|
|
links.map((link) => [decodeURIComponent(link.getAttribute("href").slice(1)), link]),
|
|
);
|
|
|
|
const setActive = (id) => {
|
|
links.forEach((link) => {
|
|
link.classList.toggle("active", linksById.get(id) === link);
|
|
});
|
|
};
|
|
|
|
const updateActive = () => {
|
|
const threshold = window.innerHeight * 0.25;
|
|
let current = sections[0];
|
|
|
|
sections.forEach((section) => {
|
|
if (section.getBoundingClientRect().top <= threshold) {
|
|
current = section;
|
|
}
|
|
});
|
|
|
|
if (current?.id) {
|
|
setActive(current.id);
|
|
}
|
|
};
|
|
|
|
updateActive();
|
|
window.addEventListener("scroll", updateActive, { passive: true });
|
|
window.addEventListener("resize", updateActive);
|
|
});
|