Thomas Owens Thomas Owens - 6 months ago 40
Javascript Question

Is there a JavaScript solution to generating a "table of contents" for a page?

I have headers in

<h1>
through
<h6>
tags. Is there a way that I can use JavaScript to generate a table of contents for the contents that serves as anchor tags as well?

I would like the output to be something like:

<ol>
<li>Header 1</li>
<li>Header 1</li>
<li>Header 2</li>
<li>Header 3</li>
</ol>


I am not currently using a JavaScript framework, but I don't see why I couldn't use one.

I am also looking for something done, since I'm guessing this is a common problem, but if not, a starting point to roll my own would be good.

Answer

I couldn't resist putting together a quick implementation.

Add the following script anywhere on your page:

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;
};

Your page should be structured something like 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>

You can see it in action at http://magnetiq.com/exports/toc.htm (Works in IE, FF, Safari, Opera)

Comments