TOC Heading not working if heading not clear

Issue

I got TOC function like this
but this only work if the heading tag is clear
I mean like this

<h1>this will work</h1>

but when I add some class or Id or everyting inside <h1> the list wont appear
example <h1 class="test">This list wont be appear cz I have class</h1>

Can we ignore the class so heading will be appear on list??

document.addEventListener('DOMContentLoaded', function() {
  TableOfContents();
}
);                        


function TableOfContents() {
var toc = "";
var level = 0;
var container = document.querySelector(container) || document.querySelector('#contents');
var output = output || '#toc';

container.innerHTML =
    container.innerHTML.replace(
        /<h([\d])>([^<]+)<\/h([\d])>/gi,
        function (str, openLevel, titleText, closeLevel) {
            if (openLevel != closeLevel) {
                return str;
            }

            if (openLevel > level) {
                toc += (new Array(openLevel - level + 1)).join('<ul>');
            } else if (openLevel < level) {
                toc += (new Array(level - openLevel + 1)).join('</li></ul>');
            } else {
                toc += (new Array(level+ 1)).join('</li>');
            }

            level = parseInt(openLevel);

            var anchor = titleText.replace(/ /g, "_");
            toc += '<li><a href="#' + anchor + '">' + titleText
                + '</a>';

            return '<h' + openLevel + '><a href="#' + anchor + '" id="' + anchor + '">'
                + titleText + '</a></h' + closeLevel + '>';
        }
    );

if (level) {
    toc += (new Array(level + 1)).join('</ul>');
}
document.querySelector(output).innerHTML += toc;
};
<div id="toc">
  Table of Contents
</div>

<div id="contents" class="blog-contents">
  <h1>this is h1</h1>
  <h2>this is h2</h2>
  <h1 class="test" id="myid">why this section dont appear?</h1>
</div>

please check the example
I have 3 heading
two working fine, but one is not workig cz I’ve add class and Id

Solution

Using regular expressions to parse HTML is never a good idea. Below I created a little snippet, demonstrating how the job can be done by using document.querySelector() and Element.prototype.querySelectorAll(). A single Array.prototype.reduce() then equips the headings with a suitable id attribute and also assembles the html for the table of contents:

document.querySelector('#toc').insertAdjacentHTML("beforeend","<ul>"
+[...document.querySelector('#contents')
.querySelectorAll("H1,H2,H3,H4,H5,H6")]
.reduce((a,h)=>{
  h.id=h.textContent.replaceAll(" ","_");
  a.push(`<li class="l${h.tagName[1]}"><a href="#${h.id}">${h.textContent}</a></li>`);
  return a;}, [] ).join("\n")
+"</ul>");
.l2 {margin-left:20px}
.l3 {margin-left:40px}
.l4 {margin-left:60px}
.l5 {margin-left:80px}
.l6 {margin-left:100px}
#toc { border: 1px solid grey;
       padding: 6px }
H1,H2 { margin-bottom:400px }
<div id="toc">
  Table of Contents
</div>

<div id="contents" class="blog-contents">
  <h1>this is h1</h1>
  <h2>this is h2</h2>
  <h1 class="test" id="myid">Why won't this section appear?</h1>
</div>

Answered By – Carsten Massmann

Answer Checked By – Robin (AngularFixing Admin)

Leave a Reply

Your email address will not be published.