# table of contents

{% tabs %}
{% tab title="💾 程式" %}
* replit: [toc](https://replit.com/@pegasusroe/toc#script.js)
* ⬆️ 需要：[str.htmltoelement](../../../js/val/prim/str/method/str.htmltoelement "mention"), [elem.wrappedwithhtml](../type/element/+ext/elem.wrappedwithhtml "mention")

```javascript
// "DOMContentLoaded" event handler (on document)
// - automatically generates a table of contents for the document.
document.addEventListener("DOMContentLoaded", () => {

    // find the TOC container element.
    // if there isn't one, create one at the start of the document.
    let toc = document.querySelector("#toc") || (() => {
        let div = `<div id="toc"></div>`.htmlToElement();
        document.body.prepend(div);
        return div;
    })();

    // find all section headings, assuming: 
    // - title: <h1>
    // - sections: <h2> - <h6>
    let headings = document.querySelectorAll("h2,h3,h4,h5,h6");

    // keeps track of section numbers. 
    const sectionNumberManager = {
        
        _numbers: [0, 0, 0, 0, 0],    // h2, h3, h4, h5, h6
        
        // generate section number for current heading in for-of loop
        sectionNumberForHeading(heading){
            
            // h2 -> 0, h3 -> 1, ...
            let i = level(heading) - 2;
    
            // increment the section number for this heading level 
            this._numbers[i] += 1; 
            
            // reset all lower heading level numbers to zero. 
            for (let j = i + 1; j < this._numbers.length; j++) {
                this._numbers[j] = 0;
            }
    
            // combine section numbers for all heading levels 
            // to produce a section number like 2.3.1.
            return this._numbers.slice(0, i+1).join(".");
        },
    };

    // h2 -> 2, h3 -> 3, ...
    function level(heading){
        return parseInt(heading.tagName.charAt(1));
    }

    // loop through section headings. 
    for (let heading of headings) {

        // skip if it's inside the TOC container. 
        if (heading.parentNode === toc) continue;

        // generate section number for current `heading`
        let sectionNumber = sectionNumberManager.sectionNumberForHeading(heading);

        // add section number to `heading`. 
        heading.insertAdjacentHTML(
            'afterbegin', 
            `<span class="TOCSectNum">${sectionNumber}</span>`    // place in a <span> to make it styleable.
        );

        // wrap `heading` in "named anchor" <a> so we can link to it.
        let anchorID = `TOC${sectionNumber}`;
        heading.wrappedWithHTML(`<a id="${anchorID}"></a>`);
        
        // add link (to `heading`) to TOC container.
        toc.insertAdjacentHTML('beforeend', 
            `<div class="TOCEntry TOCLevel${level(heading)-1}">
               <a href="#${anchorID}">${heading.innerHTML}</a>
             </div>`
        );
    }

});
```
{% endtab %}

{% tab title="⬆️ 需要" %}
* [str.htmltoelement](../../../js/val/prim/str/method/str.htmltoelement "mention")
* [elem.wrappedwith](../type/element/+ext/elem.wrappedwith "mention")
{% endtab %}

{% tab title="⭐️ 重點" %}
{% hint style="warning" %}
<mark style="color:red;">**name**</mark> attribute is <mark style="color:yellow;">**obsolete**</mark>, use <mark style="color:blue;">**id**</mark> instead.
{% endhint %}
{% endtab %}

{% tab title="📘 手冊" %}
* [HTMLAnchorElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement)
* Document ⟩ [.createElement()](https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement)
{% endtab %}

{% tab title="📗 參考" %}
* [ ] JavaScript: The Definitive Guide (15.3 Scripting Document)
* [ ] [named anchor](https://www.computerhope.com/jargon/a/anchor.htm#named-anchor)
{% endtab %}

{% tab title="👥 相關" %}
* [client-side-javascript-timeline](../../event/client-side-javascript-timeline "mention")
{% endtab %}

{% tab title="🗣 討論" %}
* [Is using name attribute deprecated in HTML5?](https://stackoverflow.com/questions/40738589/is-using-name-attribute-deprecated-in-html5)
* [Why did they deprecate the 'name' attribute for HTML elements?](https://stackoverflow.com/questions/25633828/why-did-they-deprecate-the-name-attribute-for-html-a-elements)
* [Creating a new DOM element from an HTML string using built-in DOM methods or Prototype](https://stackoverflow.com/a/35385518/5409815) ⭐️
{% endtab %}
{% endtabs %}
