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>