lorkyborky
lorkyborky

Reputation: 31

JQuery wrap <li> elements to create nested lists

I have a list of li elements with classes representing their type (ordered or unordered) and their list level (2 is a sublist, 3 is a sublist of a sublist etc.)

I need to wrap them up in the / tags correctly but I haven't figured out how yet.

Example:

<li class="ordered O1">
<li class="ordered O1">
<li class="unordered O2">
<li class="ordered O1">

Should be:

<ol>
<li class="ordered O1">
<li class="ordered O1">
<ul>
<li class="unordered O2">
</ul>
<li class="ordered O1">
</ol>

Upvotes: 2

Views: 97

Answers (1)

epascarello
epascarello

Reputation: 207501

It can be done with creating some new element and replacing it. Since it is tagged with jQuery, I will use that since it makes it a bit easier.

function cleanUpListItems (list, type, level) {

  // find the first one that is 
  const unItem = $(list).find(`> li.${type}.${level}`).eq(0);

  // If we have unordered lets move it
  if (unItem.length) {
    // figure out where we are moving it
    const prevLi = unItem.prev("li");

    // find all the unordered elements in that group
    const groupedLis = unItem.nextUntil(`:not(.${level})`).addBack();

     
    // create the nested list and add it
    const ul = type === "unordered" ? $("<ul></ul>") : $("<ol></ol>");
    ul.append(groupedLis);
    prevLi.append(ul);
    
    cleanUpListItems (list, type, level)
  }
}

function cleanUpList(list) {

  // find what tha max ident level is so we know what we need to start with
  const maxIndent = Math.max(...list.find("> li").map(function (e) { 
    return +this.className.match(/O(\d+)/)[1] }
  )); 

  // start from the top to the bottom, moving items into the li before it
  for (var i = maxIndent; i > 1; i--) {
    cleanUpListItems(list, "ordered", `O${i}`);
    cleanUpListItems(list, "unordered", `O${i}`); 
  }

  // check if the list is the correct type, if not swap it
  if (list.find("li:eq(0)").is(".ordered")) {
    const newList = $("<ol></ol>");
    newList.append(list.children());
    list.replaceWith(newList);
  }
}

cleanUpList($(".myList"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="myList">
  <li class="ordered O1">1 o</li>
  <li class="ordered O1">2 o</li>
  <li class="unordered O2">2.1 u</li>
  <li class="ordered O1">3 o</li>
  <li class="ordered O1">4 o</li>
  <li class="unordered O2">4.1 u</li>
  <li class="unordered O2">4.2 u</li>
  <li class="ordered O3">4.2.1 o</li>
  <li class="ordered O3">4.2.2 o</li>
  <li class="ordered O3">4.2.3 o</li>
  <li class="unordered O2">4.3 u</li>
  <li class="unordered O3">4.3 u</li>
  <li class="unordered O3">4.3 u</li>
  <li class="unordered O3">4.3 u</li>
  <li class="ordered O1">5 o</li>
  <li class="ordered O2">5.1 o</li>
  <li class="ordered O2">5.2 o</li>
  <li class="ordered O3">5.2.1 o</li>
  <li class="ordered O3">5.2.1 o</li>
  <li class="ordered O1">6 o</li>
</ul>

Upvotes: 1

Related Questions