Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I wrap contiguous sibling divs under a parent div?

I have some HTML that looks like this:

<p>Some Text</p>
<div class="listBullet">Item 1</div>
<div class="listBullet">Item 2</div>
<div class="listBullet">Item 3</div>
<p>Some More Text</p>
<div class="listBullet">Item 1</div>
<div class="listBullet">Item 2</div>
<div class="listBullet">Item 3</div>
<p>Some Other Text</p>

I want to end up with the following output:

<p>Some Text</p>
<div class="wrapperDiv">
   <div class="listBullet">Item 1</div>
   <div class="listBullet">Item 2</div>
   <div class="listBullet">Item 3</div>
</div>
<p>Some More Text</p>
<div class="wrapperDiv">
   <div class="listBullet">Item 1</div>
   <div class="listBullet">Item 2</div>
   <div class="listBullet">Item 3</div>
</div>
<p>Some Other Text</p>

I tried $(".listBullet").wrapAll("<div class='wrapperDiv' />"), but that ended up moving the two blocks to be contiguous with each other. It seems like what I need is a selector that separates the contiguous blocks into separate elements, which I would then call wrapAll on separately.

like image 295
Chris B. Behrens Avatar asked May 04 '15 22:05

Chris B. Behrens


2 Answers

This does the job:

$('p + .listBullet').each(function() {
  $(this).nextUntil('p')
         .addBack()
         .wrapAll("<div class='wrapperDiv' />");
});

Fiddle 1


If your XHTML has a mix of elements, you can do this (assuming container is the class of the parent div):
$('.container > :not(.listBullet) + .listBullet').each(function() {
  $(this).nextUntil('.container > :not(.listBullet)')
         .addBack()
         .wrapAll("<div class='wrapperDiv' />");
});

Fiddle 2


Here's a more brute force approach:
var lb= [];
$('.container > *').each(function() {
  if($(this).hasClass('listBullet')) {
    lb.push(this);
  }
  else {
    $(lb).wrapAll("<div class='wrapperDiv'/>");
    lb= [];
  }
});
$(lb).wrapAll("<div class='wrapperDiv'/>");

Fiddle 3

like image 160
Rick Hitchcock Avatar answered Oct 05 '22 05:10

Rick Hitchcock


As a general approach you could:

Loop through all the elements on the page using .next(), while the next element you find is has the correct class, (use .attr("class")) add an extra class of currentList (or simular) class wrapAll on currentList then select all the items with the currentList class and remove that class and then keep looping!

like image 35
saml Avatar answered Oct 05 '22 06:10

saml