3

My html looks like this:

<h1 id="header1">H1</h1> <p>Lorem ipsum</p> <h2 id="header2">H2</h2> <p>lorem ipsum</p> <h2 id="header3">H2</h2> <p>lorem upsum</p> <h3 id="subHeader1">H3</h3> <p>Lorem Ipsum</p>

I am using the following jquery selector to get all the headings that have an id.

var headings = $( ":header[id]" );

I want to build an nested list of all the headings so that I come up with this:

<ul><li>H1
     <ul><li>H2<li>
         <li>H2
           <ul><li>H3</li></ul>
         </li>
      </ul>
 </li></ul>

I was hoping there was an easy way of accomplishing this. Searched stackoverflow but was not able to find anything. I am able to build a flat list but having trouble building the nested list.

Any help would be extremely appreciated. Thank you!

1 Answer 1

3

I would like to say that this is not really easy. It does not just require some algorithm but also some knowledge about jQuery, it's a combination of the two, so it affects how we code it.

The idea here is you need to initialize a root ul, in each ul we should save some reference to the collection of the child headers, then we need to loop through this collection to turn each header to a ul. The newly converted ul should be added to some collection (some kind of stack) and we have a while loop running until this stack becomes empty.

It's hard to explain it better because as I said, this is fairly complicated especially to newbies who are new to both algorithm and jQuery. Here is the code:

//Initialize the root UL
var ul = $('<ul>');
for(var i = 1; i < 8; i++){
  var hs = $('h' + i);
  if(hs.length){
    ul[0].childHeaders = hs
    ul[0].childHeaderLevel = i;
    break;
  }
}

var rootUl = ul;
//main loop
while(ul.length){    
  var nextUl = $();
  //loop through each ul
  ul.each(function(){
     var innerUl = this;
     var n = this.childHeaderLevel;
     //turn each childHeader into the corresponding ul
     innerUl.childHeaders.each(function(i,elem){
        var childUl = $('<ul>').append('<li>' + $(elem).html() + '</li>')
                               .appendTo(innerUl);
        childUl[0].childHeaders = $(this).nextUntil('h' + n)
                                         .filter('h' + (n+1));
        childUl[0].childHeaderLevel = n + 1;            
        nextUl = nextUl.add(childUl);
     });                            
  });
  ul = nextUl;   
}
//append the root UL to the body after emptying
$('body').empty().append(rootUl);

Demo.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.