2023-09-22 23:57:17 -04:00
|
|
|
/**
|
2023-09-29 01:43:39 -04:00
|
|
|
* The ToC is now generated in the page template so
|
|
|
|
|
* it even exists for users without client-side js
|
|
|
|
|
* and that means it loads with the page so it avoids
|
|
|
|
|
* all potential reshuffling or layout recalculations.
|
2025-10-30 08:49:48 +02:00
|
|
|
*
|
2023-09-29 01:43:39 -04:00
|
|
|
* So, all this function needs to do is make the links
|
|
|
|
|
* perform smooth animation, and adjust the "active"
|
|
|
|
|
* entry as the user scrolls.
|
2023-09-22 23:57:17 -04:00
|
|
|
*/
|
2023-09-28 00:24:52 -04:00
|
|
|
export default function setupToC() {
|
2025-10-30 08:49:48 +02:00
|
|
|
const container = document.getElementById("right-pane");
|
2023-09-29 01:43:39 -04:00
|
|
|
const toc = document.getElementById("toc");
|
2025-10-30 08:49:48 +02:00
|
|
|
if (!toc || !container) return;
|
2023-09-22 23:57:17 -04:00
|
|
|
|
2023-09-29 01:43:39 -04:00
|
|
|
// Get all relevant elements
|
|
|
|
|
const sections = document.getElementById("content")!.querySelectorAll("h2, h3, h4, h5, h6");
|
|
|
|
|
const links = toc.querySelectorAll("a");
|
2023-09-22 23:57:17 -04:00
|
|
|
|
2023-09-29 01:43:39 -04:00
|
|
|
// Setup smooth scroll on click
|
|
|
|
|
for (const link of links) {
|
|
|
|
|
link.addEventListener("click", e => {
|
|
|
|
|
const target = document.querySelector(link.getAttribute("href")!);
|
|
|
|
|
if (!target) return;
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
e.stopPropagation();
|
2025-10-30 08:49:48 +02:00
|
|
|
|
2023-09-29 01:43:39 -04:00
|
|
|
target.scrollIntoView({behavior: "smooth"});
|
|
|
|
|
});
|
2023-09-22 23:57:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Setup a moving "active" in the ToC that adjusts with the scroll state
|
|
|
|
|
function changeLinkState() {
|
|
|
|
|
let index = sections.length;
|
|
|
|
|
|
2025-10-30 08:49:48 +02:00
|
|
|
// Work backwards to find the first matching section
|
|
|
|
|
while (--index && container!.scrollTop + 50 < (sections[index] as HTMLElement).offsetTop) {} // eslint-disable-line no-empty
|
2023-09-22 23:57:17 -04:00
|
|
|
|
|
|
|
|
// Update the "active" item in ToC
|
|
|
|
|
links.forEach((link) => link.classList.remove("active"));
|
|
|
|
|
links[index].classList.add("active");
|
|
|
|
|
}
|
2025-10-30 08:49:48 +02:00
|
|
|
|
2023-09-22 23:57:17 -04:00
|
|
|
// Initial render
|
|
|
|
|
changeLinkState();
|
2025-10-30 08:49:48 +02:00
|
|
|
container.addEventListener("scroll", changeLinkState);
|
|
|
|
|
}
|