Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrap every 3 divs in a div

Is it possible to use nth-child selectors to wrap 3 divs using .wrapAll? I can't seem to work out the correct equation.

so...

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

becomes...

<div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
</div>
like image 649
csbourne Avatar asked Jul 29 '10 20:07

csbourne


4 Answers

You can do it with .slice(), like this:

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

You can try out a demo here, all we're doing here is getting the elements you want to wrap and looping through them, doing a .wrapAll() in batches of 3 then moving to the next 3, etc. It will wrap 3 at a time and however many are left at the end, e.g. 3, 3, 3, 2 if that's the case.

like image 183
Nick Craver Avatar answered Oct 20 '22 03:10

Nick Craver


I've written a generic chunk function that makes this quite easy to do:

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

$.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>');
div > div {
  width: 50px;
  height: 50px;
  background: blue;
  margin: 2px;
  float: left;
}

div.new {
  background: red;
  height: auto;
  width: auto;
  overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
</div>
like image 25
Ja͢ck Avatar answered Oct 20 '22 03:10

Ja͢ck


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

How to use it.

Call EveryWhat() on the element and put in a number for every element you would like to collect.

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

wrapinner's quotes should have a properly formatted <div class="new" /> with a class and closing tag. Stackoverflow prevents me from showing what that looks like but here is a link of a self closing div.

What it should look like

That will wrap every other number that you specified. I'm using jquery 1.8.2. so remember use selector call EveryWhat(3) and a number for every time. Of course putting it at the bottom of the page or wrapping it in a

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

You could use every nth and then .wrapInner('<div class="new" />') for the same results.

like image 8
Alex Williams Avatar answered Oct 20 '22 03:10

Alex Williams


Here is a more usable version of Nick's above:

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

You would use this like:

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

window should be replaced with your Handlers namespace, of course.

Updated: A slightly better version that leverages 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);

Use like:

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

The second parameter for the wrapper name is optional.

like image 7
Pat Avatar answered Oct 20 '22 04:10

Pat