5

是否存在仅包装连续元素的 wrapAll 版本?所以这:

<p>foo</p>
<p>foo</p>
<h2>bar</h2>
<p>foo</p>

变成这样:

<div>
    <p>foo</p>
    <p>foo</p>
</div>
<h2>bar</h2>
<div>
    <p>foo</p>
</div>

什么时候运行?

$('p').wrapAll2('<div />')
4

3 回答 3

6

这是一种方法:

$(function(){
    var cWrap=$('<div />');
    $('p').each(function(){
        var o = $(this).next('p').length;
        $(this).replaceWith(cWrap).appendTo(cWrap);
        if (!o) cWrap=$('<div />');
    });
});

或作为一个成熟的插件:

(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 />');
});

*请注意,它假定您将在同类集合上调用它(至少所有相同的节点类型)

编辑

作为实验,我查看了 jQuery 的内部结构,发现它存储了用于创建集合的选择器![至少在实例化方面],因此考虑到这一点,我创建了另一个版本,至少可以与当前版本的 jQuery 一起使用,并接受任何选择器

(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 />');
});

但它不适用于这样的事情:$('p').add('span').wrapAll2('<div />');

于 2011-11-18T06:41:36.860 回答
2

我阐述了 Shad 的出色答案,并创建了一些可以采用任何选择器的代码,而不仅仅是节点类型:

(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/>');
});

希望它可以传递一个 JQuery 对象而不是选择器字符串,但这对于我现在的目的来说已经足够好了。

于 2011-11-18T17:53:32.007 回答
1

这是适用于任何 jQuery 选择器的通用解决方案,并且在修改集合时也适用,例如使用add()orandSelf()not()

演示:http: //jsfiddle.net/wujX6/

(function($){
  $.fn.wrapConsecutive = function(wrapper){
    if (!this.length) return this;
    var thisRun,prev;
    this.each(function(){
      if (!prev || $(this).prev()[0]!=prev){
        if (thisRun) thisRun.wrapAll(wrapper);
        thisRun = $();
      }
      thisRun = thisRun.add(this);
      prev = this;
    });
    if (thisRun) thisRun.wrapAll(wrapper);
    return this;
  };
})(jQuery);

演示显示它基于操纵的集合工作:http: //jsfiddle.net/wujX6/1/


唯一需要注意的是,连续元素之间的中间文本节点不包含在包装中。因此,例如,调用$('p').wrapConsecutive('<div/>')此 HTML:

<p>foo</p>
<p>bar</b>
jim
<p>baz</p>
jar

… 将产生以下输出:

<div><p>foo</p><p>bar</b><p>baz</p></div>
jim
jar
于 2012-08-14T16:34:01.737 回答