3

I have a page that returns a dynamic list of items

<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
<li>item6</li>
</ul>

I need a way to insert tags around every grouping of 3 list elements. Basically transform the code above into this

<ul>
 <div>
  <li>item1</li>
  <li>item2</li>
  <li>item3</li>
 </div>
 <div> 
  <li>item4</li>
  <li>item5</li>
  <li>item6</li>
 </div>
</ul>

I have been playing around with the Jquery Wrap(),WrapAll(), WrapInner()... but with no success so far. Greatly appreciate any solutions or ideas on this.

2
  • Are you sure that's valid markup? I would think ul-li-li-li ul-li-li-li would make more sense (semantically too) Commented Jul 14, 2009 at 19:03
  • yes I guess inserting a </ul><ul> pair after each 3 li elements would do what i need it to do and be valid. Good point Commented Jul 14, 2009 at 19:09

4 Answers 4

4

Here's another method that generates the HTML dynamically and follows correct semantics allowing only <li> elements directly inside of <ul> elements:

$(function(){
    const GROUP_COUNT = 3;
    var liElements = $('ul > li');
    var count = liElements.length;
    var html = '';

    for (var i = 0; i < count; i += GROUP_COUNT) {
        html += '<li><ul>';
        liElements.slice(i, i + GROUP_COUNT).each(function(){
            html += '<li>' + $(this).html() + '</li>';
        });
        html += '</ul></li>';
    }

    $('ul').html(html);
});

You can change GROUP_COUNT to group by a different number of elements.

This code will transform:

<ul>
  <li>item1</li>
  <li>item2</li>
  <li>item3</li>
  <li>item4</li>
  <li>item5</li>
  <li>item6</li>
  <li>item7</li>
</ul>

Into:

<ul>
  <li>
    <ul>
      <li>item1</li>
      <li>item2</li>
      <li>item3</li>
    </ul>
  </li>
  <li>
    <ul>
      <li>item4</li>
      <li>item5</li>
      <li>item6</li>
    </ul>
  </li>
  <li>
    <ul>
      <li>item7</li>
    </ul>
  </li>
</ul>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks everyone. This seem to be the most valid and at same time accomplished what I needed.
1

This is solution is for the suggested in comments to insert new ul instead of div.

jQuery:

var numbGroups = ($('ul li').length - 3)/3;
for(var index = 0; index < numbGroups ; index++) {
$('#ul'+index).after("<ul id='ul"+(index+1)+"'></ul>");
$('#ul' + (index+1)).append($('ul#ul0 li:gt(2):lt(3)'));
}

Inserting a Id in the ul

<ul id='ul0'>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
<li>item6</li>
<li>item7</li>
<li>item8</li>
</ul>

EDIT: The old solution was wrong for longer lists. Corrected that.

Comments

0

How about this:

var originalList = $("ul");
var listsToAdd = originalList.children("li").length / 3 - 1;
for(var index = 0; index < listsToAdd; index++)
{
    originalList.before("<ul></ul>");
}
while (originalList.children("li").length > 3)
{
    originalList.children("li:lt(3)").appendTo("ul:empty:first");
}

It worked in my tests with larger lists and no id needs to be added (assuming there is only one list to start. Otherwise, just set originalList to the list to be divided.)

Comments

0

I would, like suggested before, advice not to include some div elements inside ul. Anyhow, here is my proposal for this:

for(var i = 2; i < $('ul li').length - 1; i += 3)
{    $('ul li').eq(i).after('</div><div>');    }
$('ul').wrapInner('<div></div>');

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.