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>

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.


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


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.


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.


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.


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/

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.