Refactor ToC generation and active link handling
The SVG HTML was moved into a constant for cleaner code.
This commit is contained in:
parent
65037e910f
commit
1fc42828b3
1 changed files with 43 additions and 42 deletions
|
@ -170,50 +170,20 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
|
|||
},
|
||||
});
|
||||
|
||||
// Function to create and add an item to the ToC list
|
||||
function addToC(heading: HTMLElement, tocList: HTMLElement | null) {
|
||||
const li = document.createElement("li");
|
||||
li.className = "toc-level-" + heading.tagName.toLowerCase();
|
||||
li.innerHTML =`
|
||||
<svg class="w-0 h-0" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="#fa5a15">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m12.75 15 3-3m0 0-3-3m3 3h-7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z">
|
||||
</path>
|
||||
</svg>
|
||||
<a href="#${heading.id}">${heading.textContent}</a>`;
|
||||
tocList?.appendChild(li);
|
||||
return li;
|
||||
}
|
||||
const SVG_HTML_STRING = '<svg class="w-0 h-0" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="#fa5a15"><path stroke-linecap="round" stroke-linejoin="round" d="m12.75 15 3-3m0 0-3-3m3 3h-7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"></svg>';
|
||||
|
||||
function setActiveLinkById(id: string | null) {
|
||||
const listItems = document.querySelectorAll("#toc li");
|
||||
listItems.forEach(item => item.classList.remove("selected"));
|
||||
|
||||
if (!id) return;
|
||||
|
||||
function setActiveLink(id: string) {
|
||||
document.querySelectorAll("#toc li").forEach((li) => {
|
||||
li.classList.remove("selected");
|
||||
});
|
||||
const activeLink = document.querySelector(`#toc a[href="#${id}"]`);
|
||||
if (activeLink) {
|
||||
const li: HTMLElement | null = activeLink.parentElement;
|
||||
li?.classList.add("selected");
|
||||
}
|
||||
}
|
||||
|
||||
function generateToC(article: HTMLElement | null, tocList: HTMLElement | null) {
|
||||
// Observe headings and add them to the ToC
|
||||
let headings: NodeListOf<HTMLElement> | [] = article
|
||||
? article.querySelectorAll("h1, h2, h3, h4, h5, h6")
|
||||
: [];
|
||||
headings.forEach((heading: Element, i: number) => {
|
||||
if (heading instanceof HTMLElement) {
|
||||
addToC(heading, tocList);
|
||||
gsap.timeline({
|
||||
scrollTrigger: {
|
||||
trigger: heading,
|
||||
start: "top 20%",
|
||||
end: () =>
|
||||
`bottom top+=${i === headings.length - 1 ? 0 : headings[i + 1].getBoundingClientRect().height}`,
|
||||
onEnter: () => setActiveLink(heading.id),
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
if (!activeLink) return;
|
||||
|
||||
const listItem = activeLink.parentElement;
|
||||
listItem?.classList.add("selected");
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
|
@ -221,6 +191,37 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
|
|||
const article: HTMLElement | null = document.querySelector("article");
|
||||
// The ToC container <ul> element
|
||||
const tocList: HTMLElement | null = document.querySelector("#toc ul");
|
||||
generateToC(article, tocList);
|
||||
|
||||
const headings: NodeListOf<HTMLElement> | [] = article ? article.querySelectorAll("h1, h2, h3, h4, h5, h6") : [];
|
||||
|
||||
headings.forEach((heading, i) => {
|
||||
if (heading instanceof HTMLElement) {
|
||||
const listItem = document.createElement("li");
|
||||
listItem.className = "toc-level-" + heading.tagName.toLowerCase();
|
||||
|
||||
const tempDiv = document.createElement("div");
|
||||
tempDiv.innerHTML = SVG_HTML_STRING;
|
||||
|
||||
const svg = tempDiv.firstChild;
|
||||
listItem.appendChild(svg as Node);
|
||||
|
||||
const link = document.createElement("a");
|
||||
link.href = "#" + heading.id;
|
||||
link.textContent = heading.textContent;
|
||||
listItem.appendChild(link);
|
||||
|
||||
tocList?.appendChild(listItem);
|
||||
|
||||
gsap.timeline({
|
||||
scrollTrigger: {
|
||||
trigger: heading,
|
||||
start: "top 20%",
|
||||
end: () => `bottom top+=${i === headings.length - 1 ? 0 : (headings[i + 1] as HTMLElement).getBoundingClientRect().height}`,
|
||||
onEnter: () => setActiveLinkById(heading.id),
|
||||
onLeaveBack: () => setActiveLinkById((headings[i - 1] as HTMLElement)?.id),
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
Loading…
Add table
Reference in a new issue