tags:

views:

72

answers:

5

Hi

<div id="WhateverHolder">

<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>

</div>

that i need to have converted into

<div id="WhateverHolder">

<div class="block">
<div class="item first"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item last"></div>
</div>

<div class="block">
<div class="item first"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item last"></div>
</div>

</div>

I have looked for a plugin that can do this but to no avail what is the easiest way to do this in jQuery

A: 
var MAX_CHILDREN_PER_BLOCK = 4;
var parent = $('#WhateverHolder');
var currentBlock;
parent.find('.item').each(function() {
   if (!currentBlock) {
       currentBlock = $('<div class="block"></div>');
       currentBlock.appendTo(parent);
   }
   $(this).appendTo(currentBlock);
   if (currentBlock.children().size() == MAX_CHILDREN_PER_BLOCK) {
       currentBlock = null;
   }
});
parent.find('.block').each(function() {
   $(this).find('.item:first').addClass('first');
   $(this).find('.item:last').addClass('last');
});

Edit: Tested and solved bug explained in the comments

gustavogb
Also tested this one, the block part works but when i try with a children per block of 3 , on the last block ( the one that only has 2 doesn't have the item first and item last )
nokiko
You are right, I have solved that problem and tested it in case you want to make use of the code
gustavogb
+1  A: 

You could use the jQuery function .slice(...):

http://api.jquery.com/slice/

var items = $("#WhateverHolder > div.item");

var blockCount = 4;

for (var i = 0; i < items.length; i+= blockCount) {
    var slice = items.slice(i,i + blockCount);      

    slice.first().addClass('first');
    slice.last().addClass('last');

    slice.wrapAll("<div class=\"block\"></div>");
}

It will make a new block on the nine'th element. And otherwise make it exactly as you want with first and last classes.

lasseespeholt
It's easier to with :lt and :gt selectors.
Dorian
@Dorian Also if it should scale to X elements?
lasseespeholt
I don't know, but yes, after 2 blocks, it's easier with slice.
Dorian
Why is my answer downvoted? It works perfect here. Please comment
lasseespeholt
Thanks this does the dividing up in blocks with 8 but also with 11 items and does the first and last class as well
nokiko
Yes, exactly as your described in your comment to your own question. Did you downvote it? really bad style when my answer actually works
lasseespeholt
No i did not downvote it so far this is the only one that works was waiting for someone to comment on this downvote as well
nokiko
Thanks, I apologies then :) Good luck with your site
lasseespeholt
A: 

You can use selectors (you can improve this) :

place = $('#WhateverHolder')
place.find('div:lt(4)').wrapAll('<div class="block" />')
place.find('div:gt(4)').wrapAll('<div class="block" />')
place.find('.block').each(function (i, e) {
  e = $(e)
  e.find('div:first').addClass('first')
  e.find('div:last').addClass('last')
});

Edit : It Works (with your example) ! (It's easy to made it more flexible (with .each() and .slice())

Dorian
A: 

Here're my 2 cents:

 var listItemsPerList = 10;
 var listItems = $("#WhateverHolder > div").length;

 for (var i = 0; i < Math.round(listItems / listItemsPerList); i++) {
     var startingItem = i * listItemsPerList;
     var endingItem = (i + 1) * listItemsPerList;
     if (endingItem > listItems) { endingItem = listItems };
     $("#WhateverHolder > div").slice(startingItem, endingItem).wrapAll("<div class="block"></div>");
 }

 $("#WhateverHolder").replaceWith($("#WhateverHolder").children());
zarko.susnjar
this one doesn't seem to work with if i do 4 then it puts the first 4 in a block then 3 normal ones and then it put the last one in a block again
nokiko
Aham, I guess you don't like to adjust and debug things? Just pure copy/paste? Nevermind...
zarko.susnjar
A: 

Use jQuerys .slice() and .wrapAll() method to accomplish that task.

$(function(){
   var $set = $('.item');

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

This would wrap each four div.item elements into one div.block.

See: .wrapAll(), .slice()

Example: http://jsbin.com/ahuvu3/edit

jAndy
ok thanks, this one works and creates the html needed
nokiko
It does not create the first and last class...
lasseespeholt