0

I have the below html structure:

<div class="thumbnail"></div>
<div class="thumbnail"></div>
<div class="thumbnail"></div>
<div class="thumbnail"></div>
<div class="thumbnail"></div>
<div class="thumbnail"></div>
<div class="thumbnail"></div>
<div class="thumbnail"></div>

Now to group/wrap each 4 items in a separate div I did as below:

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

My question - Is there any way to convert this specific loop into $.each or is for loop only the way to do this?

UPDATE

This ain't duplicate because the answer mentioned there using jquery $.each doesn't work as expected and that has been specific to wrapping divs may be on any technique and my question is specific to wrap with $.each. I don't see it as duplicate!!

A Pen to show how the $.each answer over there works!

Guruprasad J Rao
  • 29,410
  • 14
  • 101
  • 200

2 Answers2

5

A jQuery only way would be to iterate over the nth-child(4n)

$('.thumbnail:nth-child(4n)').each(function(){
    $(this)
      .prevAll('.thumbnail').andSelf()
      .wrapAll($('<div/>',{class:"new"})) 
});

Demo

Considering the complexity, not sure whether the prevAll() performs better than the plain for loop.

Referring one of my similar answer here

Community
  • 1
  • 1
Shaunak D
  • 20,588
  • 10
  • 46
  • 79
  • Simply superb!! Thanks for enlightening!! :) – Guruprasad J Rao Jun 22 '15 at 04:41
  • 1
    Thank you. Glad to help. – Shaunak D Jun 22 '15 at 04:43
  • On a small document you probably won't see much difference, but introducing this complexity to eliminate a humble for-loop doesn't seem worth it; also, what if the elements are wrapped with elements that share the same class name, it would not work in the same way all of a sudden. – Ja͢ck Jun 22 '15 at 05:38
  • Yes, you are right. The above solution is case-specific. *if the elements are wrapped with elements that share the same class name*: This can still be handled jQuery-selector way (`('.thumbnail:not('.thumbnail > .thumbnail')`). But again as you said, jQuery might increase the complexity compared to a plain for loop. – Shaunak D Jun 22 '15 at 05:45
1

Nothing really beats a direct for loop like that, but it would be handy to keep this in a small extension:

$.fn.wrapEvery = function(n, html) {
    for(var i = 0; i < this.length; i+=n) {
        this.slice(i, i+n).wrapAll(html);
    }
});

Then, called like:

$('.thumbnail').wrapEvery(4, "<div class='new'></div>");

Or, a more generic chunk function from an earlier answer.

$.fn.every = function(n) {
    var arr = [];
    for (var i = 0; i < this.length; i+=n) {
        arr.push(this.slice(i, i+n));
    }
    return this.pushStack(arr, "every", n);
}

Called like:

$('.thumbnail').every(4).wrap('<div class="new"></div>');
Community
  • 1
  • 1
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309