Automatic Table of Contents Generation
Here’s a JavaScript snippet for automatically generating a table of contents based on headings in a document. It will traverse all <h1>, <h2>, <h3>, etc. elements, add anchors (<a>) to them and generate nested unordered lists (<ul>, <li>) with links to the now anchored headings. The nesting honors the hierarchy of the headings.
For example, for a document that has the following headings:
<h1>Main Section 1</h1> Some text <h2>Sub-section</h2> Some text <h3>Sub-sub-section</h3> Some text <h1>Main Section 2</h1>
The generated HTML will be:
<ul>
<li>
Main Section 1
<ul>
<li>
Sub-section
<ul>
<li>Sub-sub-section</li>
</ul>
</li>
</ul>
</li>
<li>
Main Section 2
</li>
</ul>
The code can be placed anywhere on an HTML page. It will locate all heading under the element with id “contents” and generate the table of contents inside the element with id “toc”:
window.onload = function () {
var toc = "";
var level = 0;
document.getElementById("contents").innerHTML =
document.getElementById("contents").innerHTML.replace(
/<h([\d])>([^<]+)<\/h([\d])>/gi,
function (str, openLevel, titleText, closeLevel) {
if (openLevel != closeLevel) {
return str;
}
if (openLevel > level) {
toc += (new Array(openLevel - level + 1))
.join("<ul>");
} else if (openLevel < level) {
toc += (new Array(level - openLevel + 1))
.join("</ul>");
}
level = parseInt(openLevel);
var anchor = titleText.replace(/ /g, "_");
toc += "<li><a href=\"#" + anchor + "\">"
+ titleText + "</a></li>";
return "<h" + openLevel + "><a name=\"" + anchor
+ "\">" + titleText + "</a></h" + closeLevel
+ ">";
}
);
if (level) {
toc += (new Array(level + 1)).join("</ul>");
}
document.getElementById("toc").innerHTML += toc;
};
The HTML should be structured similar to this:
<body> <div id="toc"> <h3>Table of Contents</h3> </div> <hr/> <div id="contents"> <h1>Fruits</h1> <h2>Red Fruits</h2> <h3>Apple</h3> <h3>Raspberry</h3> <h2>Orange Fruits</h2> <h3>Orange</h3> <h3>Tangerine</h3> <h1>Vegetables</h1> <h2>Vegetables Which Are Actually Fruits</h2> <h3>Tomato</h3> <h3>Eggplant</h3> </div> </body>