Ah, I think I know now.
The code is assuming that you are strictly setting headers in the correct structure.
See the Headings are important section here:
<h1>
headings should be used for main headings, followed by<h2>
headings, then the less important<h3>
, and so on.
Problems occur, if the previous heading was an h2
and you add an h4
. Problems also occur, if the first heading isn’t an h1
and you add an h1
somewhere.
The code in populateSideBar
that does currentList = currentList.parentElement.parentElement
is the problem. It’s going up two levels in the <ul>
structure and ending up outside the sidebar when the heading structure is improper.
Updated populateSideBar
with some error checking
- In case the heading structure does not follow the proper order, this should at least stop it from adding stuff outside the sidebar
<script>
// Populate the sidebar with <li> elements
function populateSidebar() {
const sidebarList = document.getElementById("sidebar-list");
const headers = document.querySelectorAll("h1, h2, h3, h4, h5, h6");
// Duplicate the header structure in the sidebar as a nested <ul> list
let currentList = sidebarList;
let previousLevel = 1;
function addHeader(header) {
if (!currentList) {
return;
}
const level = parseInt(header.tagName[1]);
const listItem = document.createElement("li");
const link = document.createElement("a");
link.textContent = header.textContent;
// If the header doesn't have an id, assign it the text content
if (!header.id) {
header.id = header.textContent;
}
link.href = "#" + header.id;
listItem.appendChild(link);
if (level > previousLevel) {
const newList = document.createElement("ul");
currentList.appendChild(newList);
currentList = newList;
} else if (level < previousLevel) {
for (let i = 0; i < previousLevel - level; i++) {
// We want to get currentList.parentElement.parentElement but not go beyond the top level
// which is sideBarList
currentList = currentList.parentElement
if (currentList.id !== "sidebar-list") {
currentList = currentList.parentElement
}
}
}
currentList?.appendChild(listItem);
previousLevel = level;
}
headers.forEach(addHeader);
}
populateSidebar();
</script>