Enveloppez toutes les 3 divs dans un div

85

Est-il possible d'utiliser des nth-childsélecteurs pour envelopper 3 divs en utilisant .wrapAll? Je n'arrive pas à trouver la bonne équation.

donc...

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

devient...

<div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
</div>
csbourne
la source
2
gist.github.com/3181731 Un joli plugin jQuery pour faire exactement cela. J'espère que vous le trouverez utile.
iMoses du

Réponses:

179

Vous pouvez le faire avec .slice(), comme ceci:

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

Vous pouvez essayer une démo ici , tout ce que nous faisons ici est d'obtenir les éléments que vous voulez envelopper et de les parcourir en boucle, de faire un .wrapAll()par lots de 3 puis de passer aux 3 suivants, etc. cependant il en reste beaucoup à la fin, par exemple 3, 3, 3, 2 si c'est le cas.

Nick Craver
la source
J'en ferais une fonction et ferais du nombre de div enveloppés un argument. Quelque chose comme applyDivGrouping (divs, divsPerGroup);
Stefan Kendall
Hou la la! Merci pour la réponse rapide. Quelques choses ... Donc, juste pour clarifier - ce n'est pas possible avec nth-child? & .. En tant que novice complet de jQuery - comment faire fonctionner cela? Dois-je l'envelopper dans un jQuery (function ($) ...? Merci beaucoup
csbourne
@csbourne - Non, :nth-child()ça ne se prête pas bien à ça, comme pour l'appeler, enveloppez-le simplement dans un $(function() { });si vous voulez l'exécuter document.ready, sinon appelez-le quand vous voulez l'exécuter :)
Nick Craver
Merci Nick pour l'aide et les conseils fantastiques - fonctionne parfaitement.
csbourne
3
@Fahad, selon la logique de NickCraver, vous pouvez simplement modifier un petit morceau de code var divs = $("div > .classname");OU var divs = $("div .classname");Merci
23

J'ai écrit une fonction de bloc générique qui rend cela assez facile à faire:

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

Jack
la source
8

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

Comment l'utiliser.

Appelez EveryWhat()l'élément et entrez un numéro pour chaque élément que vous souhaitez collecter.

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

Les citations de wrapinner doivent avoir un format correctement <div class="new" />avec une classe et une balise de fermeture. Stackoverflow m'empêche de montrer à quoi cela ressemble, mais voici un lien d'un div à fermeture automatique.

À quoi ça devrait ressembler

Cela englobera tous les autres nombres que vous avez spécifiés. J'utilise jquery 1.8.2. alors rappelez-vous d'utiliser l'appel sélecteur EveryWhat(3)et un numéro à chaque fois. Bien sûr, le mettre au bas de la page ou l'envelopper dans un

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

Vous pouvez utiliser tous les nièmes, puis .wrapInner('<div class="new" />')pour les mêmes résultats.

Alex Williams
la source
1
Vous pouvez déjà le faire avec $('div > div:nth-child(3n)')et ne donne pas réellement deux groupes de trois éléments.
Ja͢ck
7

Voici une version plus utilisable de Nick ci-dessus:

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

Vous utiliseriez ceci comme:

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

window doit être remplacée par votre espace de noms Handlers, bien sûr.

Mise à jour: une version légèrement meilleure qui exploite 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);

Utilisez comme:

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

Le deuxième paramètre du nom du wrapper est facultatif.

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

J'ai pris l'idée de plugin de Kyle et l'ai étendue pour qu'elle s'enroule automatiquement et prenne deux arguments. Cela n'a pas fonctionné pour moi au début, mais je l'ai fait fonctionner avec quelques modifications et ajouts au code.

Pour appeler la fonction, utilisez simplement l'élément parent de ce que vous souhaitez encapsuler, puis définissez vos arguments comme suit.

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

Le premier argument est le nombre d'éléments que vous souhaitez encapsuler et le deuxième argument est le type d'élément que vous souhaitez encapsuler.

Vous pouvez changer la classe de l'élément d'habillage dans la fonction principale sous la variable wrapClass.

PixelPrecision
la source
0

J'ai préparé cette réponse pour une autre question qui faisait double emploi avec celle-ci. Alors peut-être que ma variante sera utile pour quelqu'un:

Je pense que la solution pour envelopper les trois éléments est:

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)

J'ai écrit le même code à jsbin avec quelques améliorations http://jsbin.com/necozu/17/ ou http://jsbin.com/necozu/16/

Chekit
la source