开发者

Use Jquery to convert single UL LI list into a hierarchal nested list based on a class

开发者 https://www.devze.com 2023-03-11 09:14 出处:网络
I have an unordered list that needs to be spilit into a hierachal list, depending on the class that has been pre-assigned to each . Specifically, if the original list is like this:

I have an unordered list that needs to be spilit into a hierachal list, depending on the class that has been pre-assigned to each

  • . Specifically, if the original list is like this:

    <ul>
      <li class="level-1"><a href="#">First Level Item</a></li>
      <li class="level-2"><a href="#">Second Level item</a></li>
      <li class="level-3"><a href="#">Third Level item</a></li>
      <li class="level-3"><a href="#">Third Level item</a></li>
      <li class="level-2"><a href="#">Second Level item</a></li>
      <li class="level-3"><a href="#">Third Level item</a></li>
      <li class="level-3"><a href="#">Third Level item</a></li>
      <li class="level-3"><a href="#">Third Level item</a></li>
      <li class="level-2"><a href="#">Second Level item</a></li>
      <li class="level-2"><a href="#">Second Level item</a></li>
      <li class="level-1"><a href="#">Next First Level Item</a></li>
      <li class="level-2"><a href="#">Second Level item</a></li>
      <li class="level-2"><a href="#">Second Level item</a></li>
      <li class="level-3"><a href="#">Third Level item</a></li>
      <li class="level-3"><a href="#">Third Level item</a></li>
    </ul>
    

    I need it to become a nested list based on the class of each li so the final list is renedered as:

    <ul>
      <li class="level-1"><a href="#">First Level Item</a>
        <ul>
          <li class="level-2"><a href="#">Second Level item</a>
            <ul>
              <li class="level-3"><a href="#">Third Level item</a></li>
              <li class="level-3"><a href="#">Third Level item</a></li>
            </ul>
          </li>
          <li class="level-2"><a href="#">Second Level item</a>
            <ul>
              <li class="level-3"><a href="#">Third Level item</a></li>
              <li class="level-3"><a href="#">Third Level item</a></li>
              <li class="level-3"><a href="#">Third Level item</a></li>
            </ul>
          </li>
          <li class="level-2"><a href="#">Second Level item</a></li>
          <li class="level-2"><a href="#">Second Level item</a></li>
        </ul>
      </li>
      <li class="level-1"><a href="#">Next First Level Item</a>
        <ul>
          <li class="level-2"><a href="#">Second Level item</a></li>
          <li class="level-2"><a href="#">Second Level item</a>
            <ul>
              <li class="level-3"><a href="#">Third Level item</a></li>
              <li class="level-3"><a href="#">Third Level item</a></li>
            </ul>
          </li>
        </ul>
    </ul>
    

    Because I can't run server-side code on the CMS that is outputting this list, I must reorganize this HTML list client side.

    I've spent many hours without luck trying to write my own jQuery to create the new hierachy. My first attempt was trying to use a jQuery .before to add the additional </ul></li> tags before a class, and then append a new <ul> after the tag, but I wasn't able to get any <ul> <li> tags inserted -- seems jquery will add a <p> etc. but not a </ul></li>?

    I then tried using a .wrap to put a new <ul></ul> where needed but I haven't been clever enough to figure out how to just select and group all the children or grandchildren to wrap.

    Anyone have any hints on what I should be trying to开发者_开发知识库 do?


    What I believe is it would be difficult to manipulate the elements of the existing list. Rather it would be easier to generate new markup and replace the existing markup with it.

    I could come up with something like this:

        var prevlevel = 1;    
        var currentlevel;
        var newlisthtml = "";
    
        $("#idoful li").each(function(){
            currentlevel = parseInt($(this).attr("class").split("-")[1]);
    
            if(currentlevel > prevlevel) {
                newlisthtml += "<ul>";
            } else if(currentlevel < prevlevel) {
                newlisthtml += "</ul></li>";
            } else if(currentlevel == prevlevel) {
                        newlisthtml += "</li>";
                }
    
            newlisthtml += '<li class="level-' + currentlevel + '">' + $(this).html();
            prevlevel = currentlevel; 
        });
    
        $("#idoful").html(newlisthtml);
    

    Its been a long time I have used jQuery. I have not tested the above code. Refer to it as an algorithm rather than code. You will have to do something like this.


    I would start from the end and go backwards so that the trees move together.

    function nest_list(num) 
    {
        if (num <= 1) { 
            return; 
        } else {
           var item_selector = ".level-" + num.toString();
           var parent_item_selector = ".level-" + (num - 1).toString();
    
           $(item_selector).each(function() {
               $parent_item = $(this).prev(parent_item_selector);
    
               if ($parent_item.length > 0) {
                   // verify the ul
                   var $ul = $parent_item.find('ul');
                   if ($ul.length == 0) {
                      $ul = $('<ul></ul>').appendTo($parent_item);
                   } 
    
                   $ul.append($(this)); // moves the li
               }
           });
    
           nest_list(num - 1);
        }
    );
    
    nest_list(3); // number is the highest level that you want to nest from
    
  • 0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号