A while ago, I answered a Stack Overflow question about how to wrap child elements matching some selector into groups of a specified size. I had a need for this again recently so I went back to the code, tidied it up and have come up with a slightly more refined plugin.
// Copyright (c) 2011 Russ Cam // ------------------------------------------------------- // Dual licensed under the MIT and GPL licenses. // - http://www.opensource.org/licenses/mit-license // - http://www.opensource.org/licenses/gpl-3.0 (function($){ $.fn.wrapChildren = function(options) { options = $.extend({ childElem : undefined, groupSize : 1, wrapper : '<div>' }, options || {}); if (options.childElem === undefined) return this; return this.each(function() { var elems = $(this).children(), len = pos = 0; elems.each(function(i,value) { len += $(value).is(options.childElem)? 1 : 0; if (len > 0 && (len % options.groupSize === 0) || (i === elems.length - 1)) { elems.slice(pos,i + 1).wrapAll(options.wrapper); len = 0; pos = i + 1; } }); }); } })(jQuery);
You call the plugin on a matched set and pass it a selector for the child element you wish to group along with a number for how many of the matching child elements should be in a group and a string representing the element in which you wish to group them. Child elements that do not match the passed child element selector will be ignored and will be placed into a group that matches their contiguous position within the child elements.
Take a look at an example up on js fiddle, or copy/paste the code below into a file and run locally. Hope this helps :)
<!DOCTYPE html><html lang="en"><head><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script><title>wrapChildren Demo</title><meta http-equiv="Content-type" content="text/html; charset=utf-8" /><style type="text/css" media="screen"> .wrapper { background-color: red; margin: 5px; }</style><script type="text/javascript"> (function($){ $.fn.wrapChildren = function(options) { options = $.extend({ childElem : undefined, groupSize : 1, wrapper : '<div>' }, options || {}); if (options.childElem === undefined) return this; return this.each(function() { var elems = $(this).children(), len = pos = 0; elems.each(function(i,value) { len += $(value).is(options.childElem)? 1 : 0; if (len > 0 && (len % options.groupSize === 0) || (i === elems.length - 1)) { elems.slice(pos,i + 1).wrapAll(options.wrapper); len = 0; pos = i + 1; } }); }); } })(jQuery); $(function() { $('div').wrapChildren({ childElem : 'a' , groupSize: 4, wrapper : '<div class="wrapper">'}); });</script></head><body><p>anchors wrapped in groups of 4 including non-matching child elements</p><div><a href="#">1</a><a href="#">2</a><p>Child element that will be ignored</p><a href="#">3</a><a href="#">4</a><p>Another that will be ignored</p><a href="#">5</a><a href="#">6</a><a href="#">7</a><p>Yet another that will be ignored</p><a href="#">8</a><p>And another</p><a href="#">9</a><a href="#">10</a></div><br/><p>anchors wrapped in groups of 4</p><div><a href="#">1</a><a href="#">2</a><a href="#">3</a><a href="#">4</a><a href="#">5</a><a href="#">6</a><a href="#">7</a><a href="#">8</a><a href="#">9</a><a href="#">10</a></div></body></html>