Is there a version of wrapAll that will only wrap consecutive elements? So this:
<p>foo</p>
<p>foo</p>
<h2>bar</h2>
<p>foo</p>
turns into this:
<div>
<p>foo</p>
<p>foo</p>
</div>
<h2>bar</h2>
<div>
<p>foo</p>
</div>
When this is run?
$('p').wrapAll2('<div />')
Here's one way to do it:
$(function(){
var cWrap=$('<div />');
$('p').each(function(){
var o = $(this).next('p').length;
$(this).replaceWith(cWrap).appendTo(cWrap);
if (!o) cWrap=$('<div />');
});
});
or as a fully fledged plugin:
(function($){
$.fn.wrapAll2 = function(wrapper){
if (!this.length) return this;
var cWrap=$(wrapper),
tag = this.get(0).nodeName.toLowerCase();
return this.each(function(){
var o = $(this).next(tag).length;
$(this).replaceWith(cWrap).appendTo(cWrap);
if (!o) cWrap = $(wrapper);
});
};
})(jQuery);
$(function(){
$('p').wrapAll2('<div />');
});
*Note that it presumes you will call it on homogeneous collections (as least all the same node type)
Experimentally, I've looked into jQuery's innards and found that it stores the selector used to create a collection! [at least on instantiation], so with that in mind I've created another version that at least works with the current version of jQuery, and accepts any selector!
(function($) {
$.fn.wrapAll2 = function(wrapper) {
if (!this.length) return this;
var wrap = $(wrapper),
sel = this.selector || this.get(0).nodeName.toLowerCase();
return this.each(function() {
var more = $(this).next(sel).length;
console.log(this,more);
$(this).replaceWith(wrap).appendTo(wrap);
if (!more) wrap = $(wrapper);
});
}
})(jQuery);
$(function() {
$('p, span').wrapAll2('<div />');
});
It does not work with things like this though: $('p').add('span').wrapAll2('<div />');
I expounded on Shad's excellent answer and created some code that would take any selector, not just node types:
(function($){
$.wrapAll2 = function(sel, wrapSel) {
var wrap = $(wrapSel);
$(sel).each(function() {
var more = $(this).next(sel).length;
$(this).replaceWith(wrap).appendTo(wrap);
if (!more) wrap = $(wrapSel);
});
};
})(jQuery);
$(function() {
$.wrapAll2('p', '<div/>');
});
Wish it could be passed a JQuery object instead of a selector string, but this works well enough for my purposes now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With