Skip to content

Commit ca6e64d

Browse files
authored
docs: Fix bug on table of contents (#43840)
We were previously always highlighting the last header in the table of contents as active even if you were at the top of the page. This is now fixed, where upon loading the page, no header is highlighted, and as you scroll, we highlight the top-most heading one by one. Release Notes: - N/A
1 parent 0079044 commit ca6e64d

File tree

1 file changed

+35
-23
lines changed

1 file changed

+35
-23
lines changed

docs/theme/page-toc.js

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,18 @@ let scrollTimeout;
33
const listenActive = () => {
44
const elems = document.querySelector(".pagetoc").children;
55
[...elems].forEach((el) => {
6-
el.addEventListener("click", (event) => {
6+
el.addEventListener("click", (_) => {
77
clearTimeout(scrollTimeout);
88
[...elems].forEach((el) => el.classList.remove("active"));
99
el.classList.add("active");
10-
// Prevent scroll updates for a short period
10+
1111
scrollTimeout = setTimeout(() => {
1212
scrollTimeout = null;
13-
}, 100); // Adjust timing as needed
13+
}, 100);
1414
});
1515
});
1616
};
1717

18-
const getPagetoc = () =>
19-
document.querySelector(".pagetoc") || autoCreatePagetoc();
20-
2118
const autoCreatePagetoc = () => {
2219
const main = document.querySelector("#content > main");
2320
const content = Object.assign(document.createElement("div"), {
@@ -27,30 +24,41 @@ const autoCreatePagetoc = () => {
2724
main.prepend(content);
2825
main.insertAdjacentHTML(
2926
"afterbegin",
30-
'<div class="sidetoc"><nav class="pagetoc"></nav></div>',
27+
'<div class="toc-container"><nav class="pagetoc"></nav></div>',
3128
);
3229
return document.querySelector(".pagetoc");
3330
};
31+
32+
const getPagetoc = () =>
33+
document.querySelector(".pagetoc") || autoCreatePagetoc();
34+
3435
const updateFunction = () => {
35-
if (scrollTimeout) return; // Skip updates if within the cooldown period from a click
36+
if (scrollTimeout) return;
37+
3638
const headers = [...document.getElementsByClassName("header")];
37-
const scrolledY = window.scrollY;
38-
let lastHeader = null;
39-
40-
// Find the last header that is above the current scroll position
41-
for (let i = headers.length - 1; i >= 0; i--) {
42-
if (scrolledY >= headers[i].offsetTop) {
43-
lastHeader = headers[i];
44-
break;
39+
if (headers.length === 0) return;
40+
41+
const threshold = 100;
42+
let activeHeader = null;
43+
44+
for (const header of headers) {
45+
const rect = header.getBoundingClientRect();
46+
47+
if (rect.top <= threshold) {
48+
activeHeader = header;
4549
}
4650
}
4751

52+
if (!activeHeader && headers.length > 0) {
53+
activeHeader = headers[0];
54+
}
55+
4856
const pagetocLinks = [...document.querySelector(".pagetoc").children];
4957
pagetocLinks.forEach((link) => link.classList.remove("active"));
5058

51-
if (lastHeader) {
59+
if (activeHeader) {
5260
const activeLink = pagetocLinks.find(
53-
(link) => lastHeader.href === link.href,
61+
(link) => activeHeader.href === link.href,
5462
);
5563
if (activeLink) activeLink.classList.add("active");
5664
}
@@ -63,13 +71,9 @@ document.addEventListener("DOMContentLoaded", () => {
6371
const nonH1Headers = headers.filter(
6472
(header) => !header.parentElement.tagName.toLowerCase().startsWith("h1"),
6573
);
66-
const sidetoc = document.querySelector(".sidetoc");
6774
const tocContainer = document.querySelector(".toc-container");
6875

6976
if (nonH1Headers.length === 0) {
70-
if (sidetoc) {
71-
sidetoc.style.display = "none";
72-
}
7377
if (tocContainer) {
7478
tocContainer.classList.add("no-toc");
7579
}
@@ -84,6 +88,7 @@ document.addEventListener("DOMContentLoaded", () => {
8488
className: "toc-title",
8589
textContent: "On This Page",
8690
});
91+
8792
pagetoc.appendChild(tocTitle);
8893

8994
headers.forEach((header) => {
@@ -94,7 +99,14 @@ document.addEventListener("DOMContentLoaded", () => {
9499
});
95100
pagetoc.appendChild(link);
96101
});
102+
97103
updateFunction();
98104
listenActive();
99-
window.addEventListener("scroll", updateFunction);
105+
106+
const pageElement = document.querySelector(".page");
107+
if (pageElement) {
108+
pageElement.addEventListener("scroll", updateFunction);
109+
} else {
110+
window.addEventListener("scroll", updateFunction);
111+
}
100112
});

0 commit comments

Comments
 (0)