Reputation: 27
I have a problem with Javascript, my HTML list has five items with .item
class, I want it to wrapAll
by ul
element but, when I use the wrapAll
method of jQuery, so it wraps all .item
elements with one ul
, I want it to be a different ul
separated by other li
elements like the code below:
<ul>
<li>Item 1</li>
<li class='item'>Item 2</li>
<li class='item'>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li class='item'>Item 6</li>
<li class='item'>Item 7</li>
<li class='item'>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
</ul>
And I want to wrapAll
the .item
class like this:
<ul>
<li>Item 1</li>
<ul class='wrap'>
<li class='item'>Item 2</li>
<li class='item'>Item 3</li>
</ul>
<li>Item 4</li>
<li>Item 5</li>
<ul class='wrap'>
<li class='item'>Item 6</li>
<li class='item'>Item 7</li>
<li class='item'>Item 8</li>
</ul>
<li>Item 9</li>
<li>Item 10</li>
</ul>
I've tried this:
$('.item').wrapAll($('<ul/>',{class:'wrap'}));
but it goes like this:
<ul>
<li>Item 1</li>
<ul class='wrap'>
<li class='item'>Item 2</li>
<li class='item'>Item 3</li>
<li class='item'>Item 6</li>
<li class='item'>Item 7</li>
<li class='item'>Item 8</li>
</ul>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 9</li>
<li>Item 10</li>
</ul>
Thanks for reading.
Upvotes: 2
Views: 105
Reputation: 901
Here, I made a pure JavaScript solution:
var item = document.querySelectorAll("ul")[0].children;
var arr = [];
for (var i=0; i<item.length; i++) {
if (item[i].className == "item") {
arr.push(item[i]);
var nextEle = item[i].nextElementSibling;
if (nextEle.className !== "item") {
var newGroup = document.createElement("UL");
newGroup.setAttribute("class", "wrap");
for (var x=0; x<arr.length; x++) {
console.log(arr[x]);
newGroup.appendChild(arr[x]);
}
nextEle.parentNode.insertBefore(newGroup, nextEle);
arr = [];
}
}
}
<ul>
<li>Item 1</li>
<li class='item'>Item 2</li>
<li class='item'>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li class='item'>Item 6</li>
<li class='item'>Item 7</li>
<li class='item'>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
</ul>
This took me a while, but does exactly what you need.
Upvotes: 1
Reputation: 50974
One idea could be to select all li
elements which do not have an item
class which have an adjacent li
item with an .item
class. This essentially will give you all the li
elements at the start of a group of items. You can then use .nextUntil(':not(.item)')
on each starting li to get each li
element after your first .item
which has the .item
class. This gives you all elements but your original starting element, so you need to use .addBack()
to add the initial starting element to the collection. You can then wrap this using wrapAll()
:
$('li:not(.item) + li.item').each(function() {
$(this).nextUntil(':not(.item)').addBack().wrapAll($('<ul/>',{class:'wrap'}));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>Item 1</li>
<li class='item'>Item 2</li>
<li class='item'>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li class='item'>Item 6</li>
<li class='item'>Item 7</li>
<li class='item'>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
</ul>
Upvotes: 1