Add a ToC that is always visible on desktop

This commit is contained in:
2025-01-05 02:02:52 +01:00
parent 46c6f9037e
commit af3694f0ef
4 changed files with 195 additions and 8 deletions
+55 -1
View File
@@ -1,3 +1,14 @@
const throttle = (func, timeFrame) => {
let lastTime = 0;
return () => {
let now = new Date();
if (now - lastTime >= timeFrame) {
func();
lastTime = now;
}
};
};
window.addEventListener("load", () => {
// Enlarged floating figures
for (let figure of document.getElementsByTagName("figure")) {
@@ -51,6 +62,50 @@ window.addEventListener("load", () => {
}
}
// set active toc heading
const toc = document.getElementById("toc");
const tocNav = toc.getElementsByTagName("nav")[0];
const headingsForToc = [
...document.getElementsByTagName("article"),
].flatMap((article) =>
[...article.querySelectorAll("h1, h2, h3, h4")]
.filter((heading) => heading.offsetParent.tagName === "MAIN")
.reverse()
);
const onTocScroll = () => {
for (const heading of headingsForToc) {
if (window.scrollY + window.innerHeight / 3 > heading.offsetTop) {
const headingAnchor = heading.getElementsByTagName("a")[0];
for (const tocAnchor of toc.getElementsByTagName("a")) {
tocAnchor.classList.remove("current-toc");
if (tocAnchor.href !== headingAnchor.href) continue;
tocAnchor.classList.add("current-toc");
// Scroll toc element into view
const tocNavRect = tocNav.getBoundingClientRect();
const tocAnchorRect = tocAnchor.getBoundingClientRect();
const offset =
tocAnchorRect.top -
tocNavRect.top -
tocNav.clientHeight / 2;
const direction = offset / Math.abs(offset);
const limit = (tocNav.clientHeight / 2) * 0.5;
if (Math.abs(offset) > limit)
tocNav.scrollTop += offset - direction * limit;
}
return;
}
}
};
window.addEventListener("scroll", throttle(onTocScroll, 50));
onTocScroll();
// Code copy button
for (let codeblock of document.querySelectorAll(".highlight pre")) {
if (codeblock.querySelector(".lnt")) continue; // skip line numbers
@@ -70,6 +125,5 @@ window.addEventListener("load", () => {
button.classList.add("current-code");
});
console.log(codeblock);
}
});