js/toc.js (44 lines of code) (raw):

/** * Inspired by https://github.com/matthewkastor/html-table-of-contents * by Matthew Christopher Kastor-Inare III */ function createTOC() { var toc = document.getElementById('toc'); var content = document.getElementById('content'); var baseLevel = 0; var currentLevel = 0; var currentTarget = document.createElement('ul'); toc.appendChild(currentTarget); var headings = [].slice.call(content.querySelectorAll('h1, h2, h3')); headings.forEach(function (heading, index) { // The type of the heading will determine the nesting level in the TOC var level = parseInt(heading.tagName.substring(1)) // The first heading doesn't show nested in the TOC. It will determine // the root level. There shouldn't be bigger headings int he page. If // that is the case, they will reamin in the same level than this // base heading. if (baseLevel == 0) { baseLevel = level; } else { // Check if we have to nest or "un-nest" the element var nestDiff = level - currentLevel; if (nestDiff > 0) { // Create the nested lists to reflect the heading hierarchy for (var i = 0; i < nestDiff; i++) { var ul = document.createElement('ul'); currentTarget.appendChild(ul); currentTarget = ul; } } else if (nestDiff < 0) { // Go to the right parent according to the heading nesting level, but // stop "un-nesting" when reaching the baseLevel var toBaseLevelDiff = currentLevel - baseLevel; var unNestDiff = Math.min(toBaseLevelDiff, -nestDiff); for (var i = 0; i < unNestDiff; i++) { currentTarget = currentTarget.parentNode; } } } // Update the current level currentLevel = level; // After nesting/un-nesting, if we are below the base level, update it so // upcoming nestings/un-nestings are properly handled if (level < baseLevel) { baseLevel = level; } // Add an anchor to the heading to we can link to it var anchor = document.createElement('a'); anchor.setAttribute('name', 'toc' + index); anchor.setAttribute('id', 'toc' + index); // Build the link to pointing to the anchor var link = document.createElement('a'); link.setAttribute('href', '#toc' + index); link.textContent = heading.textContent; // Append the element to the TOC, with the right nesting level var li = document.createElement('li'); li.appendChild(link); currentTarget.appendChild(li); heading.parentNode.insertBefore(anchor, heading); }); }