Как я могу обернуть смежные div div-sibling в родительском div?

У меня есть HTML, который выглядит так:

<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>

Я хочу получить следующий результат:

<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>

Я попробовал $(".listBullet").wrapAll("<div class='wrapperDiv' />"), но это привело к тому, что два блока были смежными друг с другом. Кажется, что мне нужен селектор, который разделяет смежные блоки на отдельные элементы, которые я бы потом вызывал wrapAll отдельно.

Ответ 1

Это задание:

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

Fiddle 1


Если ваш XHTML содержит множество элементов, вы можете сделать это (если container - класс родительского div ):
$('.container > :not(.listBullet) + .listBullet').each(function() {
  $(this).nextUntil('.container > :not(.listBullet)')
         .addBack()
         .wrapAll("<div class='wrapperDiv' />");
});

Fiddle 2


Здесь применяется более грубая сила:
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

Ответ 2

В качестве общего подхода вы можете:

Прокрутите все элементы на странице с помощью .next(), в то время как следующий элемент, который вы найдете, имеет правильный класс (используйте .attr("class")), добавьте дополнительный класс класса currentList (или simular) wrapAll в currentList затем выберите все элементы класса currentList и удалите этот класс, а затем продолжайте цикл!

Ответ 3

Ну, вы также можете сделать что-то подобное, хотя, возможно, просто использование методов jQuery является более простым (и немного более гибким):

http://jsfiddle.net/ewj44a2L/1/

var listBullets = $('.listBullet'),
    n = 3, // Number of bullets per group. All groups must be equal.
    len = listBullets.length / n; // Number of groups to be encapsulated
for(var i = 0; i < len; i++) {
    listBullets.slice( n * i, n * (i + 1) )
    .wrapAll('<div class="wrapperDiv"></div>');
}
.wrapperDiv {
    background: #000;
    color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<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>
<div class="listBullet">Item 1</div>
<div class="listBullet">Item 2</div>
<div class="listBullet">Item 3</div>

Ответ 4

Try

$("p").map(function(i, el) {
  var el = $(el), list = ".listBullet";
  if (el.next().is(list)) {
    var wrap = el.after("<div class=wrapperDiv />").next();
    do { wrap.next().appendTo(wrap); } 
    while (wrap.next().is(list));
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<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>