Zawijaj co 3 elementy div w element div

85

Czy można użyć nth-childselektorów do zawijania 3 elementów div .wrapAll? Nie mogę znaleźć prawidłowego równania.

więc...

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

staje się...

<div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
</div>
csbourne
źródło
2
gist.github.com/3181731 Ładna wtyczka jQuery, która właśnie to robi. Mam nadzieję, że okażą się przydatne.
iMoses

Odpowiedzi:

179

Możesz to zrobić w .slice()ten sposób:

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

Możesz wypróbować tutaj demo , wszystko, co tutaj robimy, to pobieranie elementów, które chcesz zawinąć i przeglądanie ich w pętli, robiąc .wrapAll()partie po 3, a następnie przechodząc do następnych 3 itd. Owijamy 3 na raz i jakkolwiek wiele zostało na końcu, np. 3, 3, 3, 2, jeśli tak jest.

Nick Craver
źródło
Uczyniłbym to funkcją i uczyniłbym liczbę opakowanych elementów div jako argument. Coś w rodzaju applyDivGrouping (divs, divsPerGroup);
Stefan Kendall
Łał! Dzięki za szybką odpowiedź. Parę rzeczy ... Tak więc dla wyjaśnienia - nie jest to możliwe przy użyciu n-tego dziecka? & .. Jako kompletny nowicjusz w jQuery - jak sprawić, by to działało? Czy zawijam to w jQuery (function ($) ...? Wielkie dzięki
csbourne
@csbourne - Nie :nth-child(), nie nadaje się do tego dobrze, jak nazywanie tego, po prostu zapakuj to, $(function() { });jeśli chcesz to uruchomić document.ready, w przeciwnym razie nazwij to, gdy chcesz to uruchomić :)
Nick Craver
Dzięki Nick za fantastyczną pomoc i wskazówki - działa idealnie.
csbourne
3
@Fahad, zgodnie z logiką NickCraver, możesz po prostu edytować mały kawałek kodu var divs = $("div > .classname");LUB var divs = $("div .classname");Dzięki
23

Napisałem ogólną funkcję porcji, która sprawia, że ​​jest to dość łatwe:

$.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>');

Jacek
źródło
8

Wtyczka

$(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", "");
    }
});

Jak tego użyć.

Przywołaj EveryWhat()element i podaj numer dla każdego elementu, który chcesz zebrać.

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

cudzysłowy opakowujące powinny mieć odpowiednio sformatowane <div class="new" />z klasą i tagiem zamykającym. Stackoverflow uniemożliwia mi pokazanie, jak to wygląda, ale tutaj jest łącze do samozamykającego się elementu div.

Jak to powinno wyglądać

Spowoduje to zawinięcie każdej innej określonej liczby. Używam jquery 1.8.2. pamiętaj więc, aby EveryWhat(3)za każdym razem używać wywołania selektora i numeru. Oczywiście umieszczając go na dole strony lub pakując w plik

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

Możesz użyć każdego n-tego, a następnie .wrapInner('<div class="new" />')dla tych samych wyników.

Alex Williams
źródło
1
Możesz to już zrobić z $('div > div:nth-child(3n)')dwiema grupami po trzy elementy, a tak naprawdę nie daje to rezultatu.
Ja͢ck
7

Oto bardziej użyteczna wersja powyższego Nicka:

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

Używałbyś tego tak:

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

okno powinno zostać oczywiście zastąpione przestrzenią nazw Handlerów.

Zaktualizowano: Nieco lepsza wersja, która wykorzystuje 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);

Użyj jak:

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

Drugi parametr nazwy opakowania jest opcjonalny.

Poklepać
źródło
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 = []
                }
            });
        }
    }
});

Wziąłem pomysł wtyczki Kyle'a i rozszerzyłem go, aby zawijał się automatycznie i przyjmował dwa argumenty. Na początku nie działało, ale uruchomiłem go z kilkoma edycjami i dodatkami do kodu.

Aby wywołać funkcję, po prostu użyj elementu nadrzędnego tego, co chcesz opakować, a następnie ustaw argumenty w następujący sposób.

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

Pierwszy argument to liczba elementów, które chcesz zawinąć, a drugi to typ elementu, który chcesz owinąć.

Możesz zmienić klasę elementu opakowującego w funkcji głównej pod zmienną wrapClass.

PixelPrecision
źródło
0

Przygotowałem tę odpowiedź na inne pytanie, które było duplikatem tego. Więc może mój wariant przyda się komuś:

Myślę, że rozwiązaniem do owinięcia wszystkich trzech elementów jest:

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)

Napisałem ten sam kod na jsbin z pewnymi ulepszeniami http://jsbin.com/necozu/17/ lub http://jsbin.com/necozu/16/

Chekit
źródło