0





34

Advertisement

I use this to make a list of all <h1>. How would you also insert the <h2>, as a nested list?

Should I detect all <h2> inside a specific <h1>, i.e. use a double loop, or is there a more straightforward approach?

I'm a bit lost about which approach to use.

var toc = document.getElementById('toc'); 
var h1 = document.getElementsByTagName("h1");
for (var i = 0; i < h1.length; i++) {
     var li = document.createElement("li");
     li.appendChild(document.createTextNode(h1[i].textContent));
     toc.appendChild(li);
}
Table of contents:

<div>
  <ul id="toc">
  </ul>
</div>  

___

<h1>TitleA</h1>
<h1>TitleB</h1>
<h2>SubTitleB1</h2>
<h2>SubTitleB2</h2>
<h1>TitleC</h1>
<h1>TitleD</h1>
<h2>SubTitleD1</h2>
Question author Basj | Source

Advertisement


0


You can use querySelectorAll to get an ordered list of all h1 and h2 elements. Then you can process that list to create a nested table of contents with subheadings:

// parse the ToC content
var list = document.querySelectorAll("h1,h2"); // get all h1 & h2
var tocArr = [], cur; // holds the structure of the ToC
for (var i = 0; i < list.length; i++) {
  var e = list[i];
  if (e.tagName == "H1") {
    // for an h1, create a new heading entry (with a blank child list)
    tocArr.push({text:e.textContent, children:(cur=[])});
  } else {
    // for an h2, add it to the current h1's child list
    cur.push(e.textContent);
  }
}
console.log(tocArr);// build the DOM nodes
var toc = document.getElementById('toc');
for (var i in tocArr) {
  var li = document.createElement("li");
  li.textContent = tocArr[i].text;
  
  // NEW: add a sub-ul for any subheadings
  var ch = tocArr[i].children;
  if (ch.length > 0) {
    var ul = document.createElement("ul");
    for (var i2 in ch) {
      var li2 = document.createElement("li");
      li2.textContent = ch[i2];
      ul.appendChild(li2);
    }
    li.appendChild(ul);
  }
  
  toc.appendChild(li);
}
Table of contents:<div>
  <ul id="toc">
  </ul>
</div>  ___<h1>TitleA</h1>
<h1>TitleB</h1>
<h2>SubTitleB1</h2>
<h2>SubTitleB2</h2>
<h1>TitleC</h1>
<h1>TitleD</h1>
<h2>SubTitleD1</h2>
Answer author Qxz