Avvolgi ogni 3 div in una div


86

È possibile utilizzare i nth-childselettori per avvolgere 3 div utilizzando .wrapAll? Non riesco a trovare l'equazione corretta.

così...

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

diventa ...

<div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
</div>

2
gist.github.com/3181731 Un bel plugin jQuery per fare esattamente questo. Spero che lo troverai utile.
iMoses

Risposte:


181

Puoi farlo con .slice(), in questo modo:

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

Puoi provare una demo qui , tutto ciò che stiamo facendo qui è ottenere gli elementi che vuoi racchiudere e scorrerli in un ciclo, eseguendo un gruppo .wrapAll()di 3 quindi passare ai 3 successivi, ecc. Avvolgerà 3 alla volta e tuttavia molti sono lasciati alla fine, ad esempio 3, 3, 3, 2 se è così.


Lo farei una funzione e renderei il numero di div avvolti un argomento. Qualcosa come applyDivGrouping (divs, divsPerGroup);
Stefan Kendall

Wow! Grazie per la pronta risposta. Un paio di cose ... Quindi, solo per chiarimenti, questo non è possibile usando l'ennesimo figlio? & .. Come un principiante completo di jQuery, come faccio a farlo funzionare? Lo inserisco in una jQuery (function ($) ...? Molte grazie
csbourne

@csbourne - No, :nth-child()non si presta bene a questo, poiché per chiamarlo, basta avvolgerlo in un $(function() { });se vuoi eseguirlo document.ready, altrimenti chiamalo quando vuoi eseguirlo :)
Nick Craver

Grazie Nick per il fantastico aiuto e guida - funziona perfettamente.
csbourne

3
@ Fahad, secondo la logica di NickCraver, puoi semplicemente modificare un piccolo pezzo di codice var divs = $("div > .classname");OPPURE var divs = $("div .classname");Grazie

23

Ho scritto una funzione chunk generica che lo rende abbastanza facile da fare:

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

Il plugin

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

Come usarlo.

Chiama EveryWhat()l'elemento e inserisci un numero per ogni elemento che desideri raccogliere.

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

Le virgolette di wrapinner dovrebbero avere un formato corretto <div class="new" />con una classe e un tag di chiusura. Stackoverflow mi impedisce di mostrare come appare, ma ecco un link di un div a chiusura automatica.

Come dovrebbe essere

Questo avvolgerà ogni altro numero che hai specificato. Sto usando jquery 1.8.2. quindi ricorda di utilizzare il selettore di chiamata EveryWhat(3)e un numero per ogni volta. Ovviamente mettendolo in fondo alla pagina o avvolgendolo in un file

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

Puoi usare ogni ennesimo e poi .wrapInner('<div class="new" />')per gli stessi risultati.


1
Puoi già farlo con $('div > div:nth-child(3n)')e in realtà non risulta in due gruppi di tre elementi.
Ja͢ck

7

Ecco una versione più utilizzabile di quella di Nick sopra:

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

Lo useresti come:

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

La finestra dovrebbe essere sostituita con lo spazio dei nomi dei gestori, ovviamente.

Aggiornato: una versione leggermente migliore che sfrutta 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);

Usa come:

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

Il secondo parametro per il nome del wrapper è facoltativo.


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 = []
                }
            });
        }
    }
});

Ho preso l'idea del plugin di Kyle e l'ho estesa per avvolgere automaticamente e prendere due argomenti. All'inizio non funzionava per me, ma l'ho fatto funzionare con alcune modifiche e aggiunte al codice.

Per richiamare la funzione basta usare l'elemento genitore di ciò che si desidera racchiudere e quindi impostare gli argomenti come segue.

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

Il primo argomento è il numero di elementi che vuoi racchiudere insieme e il secondo argomento è il tipo di elemento che desideri racchiudere.

È possibile modificare la classe dell'elemento di avvolgimento nella funzione principale sotto la variabile wrapClass.


0

Ho preparato questa risposta per un'altra domanda che era un duplicato di questa. Quindi forse la mia variante sarà utile per qualcuno:

Penso che la soluzione per racchiudere tutti e tre gli elementi sia:

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)

Ho scritto lo stesso codice su jsbin con alcuni miglioramenti http://jsbin.com/necozu/17/ o http://jsbin.com/necozu/16/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.