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="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" data-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>