Обернуть каждые 3 div в div

85

Можно ли использовать nth-childселекторы для обертывания 3 div .wrapAll? Кажется, я не могу решить правильное уравнение.

так...

<div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
</div>

становится ...

<div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
</div>
csbourne
источник
2
gist.github.com/3181731 Хороший плагин jQuery для этого. Надеюсь, вы найдете это полезным.
iMoses

Ответы:

179

Вы можете сделать это .slice()вот так:

var divs = $("div > div");
for(var i = 0; i < divs.length; i+=3) {
  divs.slice(i, i+3).wrapAll("<div class='new'></div>");
}

Здесь вы можете опробовать демонстрацию , все, что мы здесь делаем, это получаем элементы, которые вы хотите обернуть, и перебираем их в цикле, выполняя их .wrapAll()партиями по 3, затем переходя к следующим 3 и т. Д. Он будет переносить 3 за раз и однако многие из них остаются в конце, например 3, 3, 3, 2, если это так.

Ник Крейвер
источник
Я бы сделал это функцией и сделал количество завернутых div в качестве аргумента. Что-то вроде applyDivGrouping (divs, divsPerGroup);
Стефан Кендалл
Вот это да! Спасибо за быстрый ответ. Пара вещей ... Итак, просто для пояснения - это невозможно с помощью nth-child? & .. Как полный новичок в jQuery - как мне заставить это работать?
Обернуть
@csbourne - Нет, :nth-child()это не очень хорошо для этого, что касается вызова этого, просто оберните его в, $(function() { });если вы хотите запустить его document.ready, в противном случае вызывайте его, когда хотите его запустить :)
Ник Крейвер
Спасибо Нику за фантастическую помощь и руководство - работает отлично.
csbourne
3
@Fahad, согласно логике NickCraver, вы можете просто отредактировать небольшой фрагмент кода var divs = $("div > .classname");ИЛИ var divs = $("div .classname");Спасибо
23

Я написал универсальную функцию фрагмента, которая упрощает это:

$.fn.chunk = function(size) {
    var arr = [];
    for (var i = 0; i < this.length; i += size) {
        arr.push(this.slice(i, i + size));
    }
    return this.pushStack(arr, "chunk", size);
}

$("div > div").chunk(3).wrap('<div class="new"></div>');

Джек
источник
8

Плагин

$(function() {
    $.fn.EveryWhat = function(arg1) {
        var arr = [];
        if($.isNumeric(arg1)) {
            $.each(this, function(idx, item) {
                var newNum = idx + 1;
                if(newNum%arg1 == 0)
                arr.push(item);
            });
        }
        return this.pushStack(arr, "EveryWhat", "");
    }
});

Как это использовать.

Вызовите EveryWhat()элемент и введите номер для каждого элемента, который вы хотите собрать.

$("div").EveryWhat(2).wrapInner('<div class="new" />');

Цитаты wrapinner должны иметь правильно отформатированный <div class="new" />класс и закрывающий тег. Stackoverflow не позволяет мне показать, как это выглядит, но вот ссылка на самозакрывающийся div.

Как это должно выглядеть

Это будет переносить все остальные указанные вами числа. Я использую jquery 1.8.2. так что не забывайте использовать селекторный вызов EveryWhat(3)и номер каждый раз. Конечно, поместив его внизу страницы или завернув в

$(document).ready(function() {  
    //place above code here
});

Вы можете использовать каждое n-е, а затем .wrapInner('<div class="new" />')для тех же результатов.

Алекс Уильямс
источник
1
Вы уже можете сделать это с помощью $('div > div:nth-child(3n)')и фактически не приводит к двум группам из трех элементов.
Jack
7

Вот более удобная версия Ника выше:

window.WrapMatch = function(sel, count, className){
  for(var i = 0; i < sel.length; i+=count) {
    sel.slice(i, i+count).wrapAll('<div class="'+className+'" />');
  }
}

Вы бы использовали это так:

var ele = $('#menu > ul > li'); 
window.WrapMatch(ele, 5, 'new-class-name');

window, конечно же, следует заменить на ваше пространство имен Handlers.

Обновлено: немного лучшая версия, использующая jQuery.

(function($){
  $.fn.wrapMatch = function(count, className) {
    var length = this.length;
    for(var i = 0; i < length ; i+=count) {
      this.slice(i, i+count).wrapAll('<div '+((typeof className == 'string')?'class="'+className+'"':'')+'/>');
    }
    return this;
  }; 
})(jQuery);

Используйте как:

$('.list-parent li').wrapMatch(5,'newclass');

Второй параметр для имени оболочки не обязателен.

Пэт
источник
1
$(function() {
    $.fn.WrapThis = function(arg1, arg2) { /*=Takes 2 arguments, arg1 is how many elements to wrap together, arg2 is the element to wrap*/

        var wrapClass = "column"; //=Set class name for wrapping element

        var itemLength = $(this).find(arg2).length; //=Get the total length of elements
        var remainder = itemLength%arg1; //=Calculate the remainder for the last array
        var lastArray = itemLength - remainder; //=Calculate where the last array should begin

        var arr = [];

        if($.isNumeric(arg1))
        {
            $(this).find(arg2).each(function(idx, item) {
                var newNum = idx + 1;

                if(newNum%arg1 !== 0 && newNum <= lastArray){
                    arr.push(item);
                }
                else if(newNum%arg1 == 0 && newNum <= lastArray) {
                    arr.push(item);
                    var column = $(this).pushStack(arr);
                    column.wrapAll('<div class="' + wrapClass + '"/>'); //=If the array reaches arg1 setting then wrap the array in a column
                    arr = [];
                }
                else if(newNum > lastArray && newNum !== itemLength){ //=If newNum is greater than the lastArray setting then start new array of elements
                    arr.push(item);
                }
                else { //=If newNum is greater than the length of all the elements then wrap the remainder of elements in a column
                    arr.push(item);
                    var column = $(this).pushStack(arr);
                    column.wrapAll('<div class="' + wrapClass + '"/>');
                    arr = []
                }
            });
        }
    }
});

Я взял идею плагина Кайла и расширил ее, чтобы автоматически переносить и принимать два аргумента. Для меня это не сработало с самого начала, но я запустил его с несколькими правками и дополнениями в код.

Чтобы вызвать функцию, просто используйте родительский элемент того, что вы хотите обернуть, а затем установите свои аргументы следующим образом.

$('#container').WrapThis(5, 'li');

Первый аргумент - это количество элементов, которые вы хотите объединить вместе, а второй аргумент - это тип элемента, который вы хотите объединить.

Вы можете изменить класс элемента оболочки в основной функции под переменной wrapClass.

PixelPrecision
источник
0

Я подготовил этот ответ на другой вопрос, который дублировал этот. Так что, может быть, мой вариант кому-то будет полезен:

Я думаю, что решение обернуть все три элемента:

var $lines = $('.w-col'), // All Dom elelements with class .w-col
     holder = []; //Collect DOM elelements

$lines.each(function (i, item) {
  holder.push(item);

  if (holder.length === 3) {
    $(holder).wrapAll('<div class="w-row" />');
    holder.length  = 0;
  }
});

$(holder).wrapAll('<div class="w-row" />'); //Wrap last elements with div(class=w-row)

Я написал тот же код на jsbin с некоторыми улучшениями http://jsbin.com/necozu/17/ или http://jsbin.com/necozu/16/

Chekit
источник