4

Possible Duplicate:
Wrap every 3 divs in a div

First thing, i know i should use a server side language to accomplish this not client side like jquery but that's not the point, i'm just trying to learn how to use it to manipulate html. Heres the html:

<div class="items">
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="1.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 1</span></div></div>
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="2.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 2</span></div></div>
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="3.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 3</span></div></div>
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="4.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 4</span></div></div>
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="5.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 5</span></div></div>
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="6.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 6</span></div></div>
</div>

I want to be able to wrap every 3 <divs> within the <div class="items"> with yet another div: <div class="row"></div>. So it end up like this:

<div class="items">
 <div class="row">  
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="1.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 1</span></div></div>
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="2.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 2</span></div></div>
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="3.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 3</span></div></div>
 </div>
 <div class="row">
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="4.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 4</span></div></div>
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="5.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 5</span></div></div>
  <div class="boxgrid"><span class="cushycms"><a href="#"><img src="6.jpg" alt=""/></a></span><div class="cover"><span class="film_title">Title 6</span></div></div>
 </div>
</div>  

How can i accomplish this with jquery's selectors? I thought i can use something like:

$("div.items:nth-child(3n)").wrap('<div class="row"></div>');

But that doesn't work. Any ideas please?

Community
  • 1
  • 1
Ritchie
  • 535
  • 3
  • 9
  • 21
  • I found this solution using wrapAll() to be very helpful and easy to follow: http://stackoverflow.com/questions/3366529/wrap-every-3-divs-in-a-div – willyp Sep 02 '11 at 19:24

4 Answers4

7

I think what you actually want is the range of divs between 1 and 3, not just wrapping the third div, yeah?

For getting a range you'll need to use jquery slice.

Steerpike
  • 17,163
  • 8
  • 39
  • 53
2

As a plugin:

jQuery.fn.wrapInChunks = function(html, chunkSize) {

    chunkSize = chunkSize || 1;

    var items = this.get(),
        rows = [],
        cur = rows[0] = $(html);

    while (items[0]) {

        if (rows[rows.length - 1].children().length === chunkSize) {
            cur = rows[rows.length] = $(html);
        }

        cur.append( items.shift() );

    }

    return this.pushStack(rows);

};

$('.boxgrid').wrapInChunks('<div class="row" />', 3).appendTo('.items');
James
  • 109,676
  • 31
  • 162
  • 175
1

Use map(), slice(), and wrapAll();

    $(document).ready( function(){
        var results =[];
        var elements = $(".items").children('.boxgrid');
        $.map( elements  , function(i, n){
            if( n%3 === 0 ){
                results.push(n);
            }
        });
        $.each( results , function(i,v){
            elements.slice(v, v+3).wrapAll('<div class="row"></div>');
        });
    });

This is tested and works.

Elzo Valugi
  • 27,240
  • 15
  • 95
  • 114
  • I may be being silly here, but aren't you using map as if it were each? - couldn't you do results = $.map(... and return n rather than pushing onto results? – Whisk Sep 16 '09 at 11:47
  • you are right and I could be further optimized, it just shows a way to do it. – Elzo Valugi Sep 16 '09 at 13:27
  • The 'v' variable will be 0 the first iteration, 1 the second, 2 the third etc. This variable needs to be incremented by 3 for every iteration in order for this example to work correctly am I not correct? Otherwise you will just be wrapping the same elements over and over with just one new element each iteration. This can be done with a for loop for example (v += 3). Don't know why to use a variable name like 'v' either. Isn't it much clearer to call it 'index' or 'i' since that's what it is? – Operator Sep 06 '17 at 05:52
0

You would have to slice the elements and make new div elements to contain the sliced elements. Below is a code example. I'm not aware of any more simpler method to do this.

$(".items").each(function()
{   
    var rowDiv = document.createElement("div");
    $(rowDiv).addClass("row");

    for(i=0; i< $(this).find("> .boxgrid").length ; i+= 3)
    {   
        $(rowDiv).append( $(this).find("> .boxgrid").slice(i, i+3).clone() );       
        $(this).append(rowDiv);
        rowDiv = document.createElement("div");
        $(rowDiv).addClass("row");
    }
    $(this).find("> .boxgrid").remove();//Remove all the immediate boxgrid child elements.  
});
Technowise
  • 1,182
  • 6
  • 11