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

后端 未结 12 1711
广开言路
广开言路 2020-12-12 17:21

I have headers in

through
tags. Is there a way that I can use JavaScript to generate a table of contents for the contents tha

相关标签:
12条回答
  • 2020-12-12 17:54

    Check out the component you are looking for on this page: Re-inventing XMLHttpRequest: Cross-browser implementation with sniffing capabilities

    It walks over entire document and creates a TOC with all h1-h6 elements reflected in an openable (upon hover) structure. The component is standalone and it doesn't use any library.

    0 讨论(0)
  • 2020-12-12 17:56

    JQuery comes to mind as a fast and easy solution. A quick google search for jquery table of contents yields two promising results:

    • jqTOC
    • Article on how to do this manually
    0 讨论(0)
  • 2020-12-12 18:00
     let headers = document.querySelectorAll('h1,h2,h3,h4,h5,h6');
      let list    = document.createElement('ol');
    
      let _el = list;
      for(i=0; i<headers.length; i++) {
        while(_el) {
          let li = document.createElement('li');
          li.innerText = headers[i].innerText;
          li.setAttribute('tagName', headers[i].tagName);
          if(_el.getAttribute('tagName') < headers[i].tagName) {
            let ol = _el.children.length > 0 ? ol = _el.querySelector('ol') : document.createElement('ol');
            ol.appendChild(li);
            _el.appendChild(ol);
            _el = li;
            break;
          } else {
            if(_el.tagName == 'OL') {
             _el.appendChild(li);
             _el = li;
             break;
            } else if (!_el.parentNode.parentNode) {
              _el.parentNode.appendChild(li);
              _el = li;
              break;
            }
            else {
              _el = _el.parentNode.parentNode;
            }
          }
        }
      }
      console.log(list);
    
    0 讨论(0)
  • 2020-12-12 18:02

    Are you looking for a prepackaged solution or are you asking how this can be implemented?

    For the latter, you could use getElementsByTagName() recursively on <h1> through <h6> XPath to iterate through all <h*> elements and construct the corresponding nested <ul> or <ol> lists. You'd also have to add the <a> tags to the headers.

    0 讨论(0)
  • 2020-12-12 18:02
      this.insert = (el, h) => {
        let li = document.createElement('li');
        li.innerText = h.innerText;
        li.setAttribute('tagName', h.tagName);
        if(el.tagName == 'OL') {
          el.appendChild(li);
          return li;
        } else if(el.getAttribute('tagName') < h.tagName) {
          let ol = el.children.length > 0 ? ol = el.querySelector('ol') : document.createElement('ol');
          ol.appendChild(li);
          el.appendChild(ol);
          return li;
        } else if(!el.parentNode.parentNode) {
          el.parentNode.appendChild(li);
          return li;
        } else {
          return this.insert(el.parentNode.parentNode, h);
        }
      }
    
      this.parse = (headers) => {
        let list = document.createElement('ol');
        let el = list;
        for(i=0; i<headers.length; i++) {
          el = this.insert(el, headers[i]);
        }
        return list;
      }
      let headers = document.querySelectorAll('h1,h2,h3,h4,h5,h6');
      let toc = this.parse(headers);
      console.log(toc);
    
    0 讨论(0)
  • 2020-12-12 18:03

    Here's a great script to do this:

    https://github.com/matthewkastor/html-table-of-contents/wiki

    To use it:

    1. Add this tag:

      <script src="./node_modules/html-table-of-contents/src/html-table-of-contents.js" type="text/javascript">
      
    2. Call the function, such as in your body's onload attribute:

      <body onload="htmlTableOfContents();"> 
      

    Here is the definition of the method that does the generation:

    /**
     * Generates a table of contents for your document based on the headings
     *  present. Anchors are injected into the document and the
     *  entries in the table of contents are linked to them. The table of
     *  contents will be generated inside of the first element with the id `toc`.
     * @param {HTMLDOMDocument} documentRef Optional A reference to the document
     *  object. Defaults to `document`.
     * @author Matthew Christopher Kastor-Inare III
     * @version 20130726
     * @example
     * // call this after the page has loaded
     * htmlTableOfContents();
     */
    function htmlTableOfContents (documentRef) {
        var documentRef = documentRef || document;
        var toc = documentRef.getElementById('toc');
        var headings = [].slice.call(documentRef.body.querySelectorAll('h1, h2, h3, h4, h5, h6'));
        headings.forEach(function (heading, index) {
            var anchor = documentRef.createElement('a');
            anchor.setAttribute('name', 'toc' + index);
            anchor.setAttribute('id', 'toc' + index);
    
            var link = documentRef.createElement('a');
            link.setAttribute('href', '#toc' + index);
            link.textContent = heading.textContent;
    
            var div = documentRef.createElement('div');
            div.setAttribute('class', heading.tagName.toLowerCase());
    
            div.appendChild(link);
            toc.appendChild(div);
            heading.parentNode.insertBefore(anchor, heading);
        });
    }
    
    try {
         module.exports = htmlTableOfContents;
    } catch (e) {
        // module.exports is not defined
    }
    
    0 讨论(0)
提交回复
热议问题