Ir para o conteúdo

Gerador de Índice

(function() {
    /* Esta função devolve o //levels//ésimo ancestral de um determinado
       objecto //start// do DOM. */
    function goBack(start, levels) {
        if (levels > 0) {
            return (goBack(start.parentNode, levels - 1));
        }
        else {
            return start;
        }
    }

    function incCounter(counter, level) {
        counter[level - 2]++;
    }

    function printCounter(counter, level) {
        s = '';
        for (i = 0; i < level - 1; i++) {
            s = s + counter[i] + '.';
        }
        return s;
    }

    function counterToID(counter, level) {
        s = printCounter(counter, level);
        s = s.replace(/.(d)/g, "-$1").replace(/.$/, "");
        return s;
    }

    function maketoc() {

        function recurseheaders(start, previous, counter) {
            if (start == null) return;
            if ((start.nodeType == 1) && (start.tagName.match(/hd/i))) {
                incCounter(counter, start.tagName.charAt(1));
                li = document.createElement("li");
                a = document.createElement("a");
                // Este span contém o número da entrada do índice (ex.: 1.1., 1.4.2., etc...)
                span = document.createElement("span");
                span.appendChild(document.createTextNode(printCounter(counter, start.tagName.charAt(1)) + " "));
                li.appendChild(span);
                a.appendChild(document.createTextNode((start.textContent ? start.textContent : start.innerText)));
                a.setAttribute("href", "#sec-" + counterToID(counter, start.tagName.charAt(1)));
                li.appendChild(a);
                // Damos um ID ao <h[1-6]> para que o click na respectiva entrada do índice faça scroll para lá
                start.setAttribute("id", "sec-" + counterToID(counter, start.tagName.charAt(1)));

                if (previous) {
                    if (previous.level < parseInt(start.tagName.charAt(1))) {
                        previous.appendChild(li);
                    }
                    else {
                        goBack(previous, (previous.level - start.tagName.charAt(1)) + 1).appendChild(li);
                    }
                }
                else {
                    document.getElementById("toc").appendChild(li);
                }
                previous = li;
                previous.level = parseInt(start.tagName.charAt(1));
            }
            recurseheaders(start.nextSibling, previous, counter);
        }

        toc = document.createElement("ul");
        toc.setAttribute("id", "toc");

        // Aqui, inserimos o índice num elemento de ID #content, antes de tudo o que ele contém
        document.getElementById("content").insertBefore(toc, document.getElementById("content").firstChild);

        recurseheaders(document.getElementById("content").firstChild, undefined, new Array(0, 0, 0, 0, 0, 0));
    }

    if (window.addEventListener) {
        window.addEventListener("load", maketoc, false);
    }
    else {
        window.attachEvent("onload", maketoc);
    }
})();