jQuery在<hr />标记之间包装文本和元素

时间:2010-07-18 15:35:29

标签: jquery jquery-selectors

我需要包装两个<hr>元素之间的所有内容,包括自由文本。

鉴于此来源:

<hr class=begin>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  <a href=mauris.html>Mauris</a> id diam turpis, et faucibus nunc.
  <div><img src=foo.png /></div>
<hr class=end>

我需要在hr.beginhr.end标记之间包装所有内容,如下所示:

<hr class=begin>
  <div class=content>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    <a href=mauris.html>Mauris</a> id diam turpis, et faucibus nunc.
    <div><img src=foo.png /></div>
  </div>
<hr class=end>

我无法使用像.nextUntil('hr.end')这样的方法,因为这不会选择未标记的文字。

6 个答案:

答案 0 :(得分:5)

<强>更新

我比以前更喜欢这个版本:http://jsfiddle.net/LbmCg/3/

(部分灵感来自 J-P 给出的答案。)

$('hr.begin').each(function(){
    var $set = $();
    var nxt = this.nextSibling;
    while(nxt) {
        if(!$(nxt).is('hr.end')) {
            $set.push(nxt);
            nxt = nxt.nextSibling;
        } else break;
    } 
   $set.wrapAll('<div class="content" />');
});

原始回答

试试这个:http://jsfiddle.net/LbmCg/

如果要包装多个套装,则需要进行一些调整。

var foundBegin = false;
var foundEnd = false;

$('hr.begin').parent()
    .contents()
    .filter(function() {
        if($(this).is('hr.begin')) {
            foundBegin = true;
        }
        if($(this).is('hr.end')) {
            foundEnd = true;
        }
        return foundBegin && !foundEnd;
    })

    .wrapAll('<div class="content"/>');​

jQuery的.contents()返回包括文本节点在内的所有节点。因此,我们在此处遍历.parent()的{​​{1}},使用hr.begin获取所有节点,然后对其进行过滤,跟踪我们何时找到开头和结尾,并且仅返回他们之间的元素。

然后我们使用.contents().wrapAll()包装它们。


编辑:如果有多套要换行,请试试:http://jsfiddle.net/LbmCg/1/

编辑:在两个示例中都清理了一点。

答案 1 :(得分:2)

​$('hr.begin ~ hr.end').each(function(){

    var contents = [], node, begin = $(this).prevAll('hr.begin')[0];

    if (node = this.previousSibling) do {
        if (node === begin) break;
        contents.unshift(node);
    } while (node = node.previousSibling);

    $(contents).wrapAll('<div class="content">');

});​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

这可以处理多组begin - contents - end序列。它将查找hr.end元素前面的所有hr.begin元素,并且对于每个hr.end,将查找它与hr.begin之间的前面节点,然后它将包装它们全部在<div class=content>

答案 2 :(得分:1)

theElement.contents()将识别文本节点。由于jQuery.nextUntil()实际上是jQuery.dir的包装,而

dir: function( elem, dir, until ) {

    var matched = [], cur = elem[dir];
    while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
        if ( cur.nodeType === 1 ) {
            matched.push( cur );
        }
        cur = cur[dir];
    }
    return matched;
},

过滤掉的文本节点的nodeType为3,自定义jQuery.dir可能会有所帮助。

-

我用Patrick的测试数据尝试了这个解决方案并且它可以工作:

jQuery.dirIncludingTextNodes = function( elem, dir, until ) {
    var matched = [], cur = elem[dir];
    while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
        if ( cur.nodeType === 1 ||cur.nodeType === 3 ) {
            matched.push( cur );
        }
        cur = cur[dir];
    }
    return matched;
};

jQuery.nextUntilIncludingTextNodes = function( elem, i, until ) {

    return jQuery.dirIncludingTextNodes( elem, "nextSibling", until );

};

$('hr.begin').nextUntilIncludingTextNodes("hr").wrap($("<div>").addClass("content"));​​​​​​​​​​​​​​​​​

答案 3 :(得分:1)

有一个类似的问题,但是我使用的是基于FCKEditor的CMS,由于使用nextSibling属性插入换行符号TextNodes,因此工作不太热。如果我能帮助它,我通常不喜欢将jQuery的东西与原生JavaScript混合在一起。我想出了这个片段,它更新了Patrick DW的解决方案,可能对jQuery的使用更加友好。也不需要类来确定下一个块。

$('hr').each(function(){
    var $set = $([]);
    var $nxt = $(this).next();
    while($nxt.length) {
        if(!$($nxt).is('hr')) {
            $set = $set.add($nxt);
            $nxt=$nxt.next();
        } else break;
    } 
    $set.wrapAll('<div class="content" />');
});

答案 4 :(得分:0)

如果HR和其他标签位于div内,例如

<div id="mydiv">
  <hr class=begin>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  <a href=mauris.html>Mauris</a> id diam turpis, et faucibus nunc.
  <div><img src=foo.png /></div>
  <hr class=end>
</div>

您可以使用jQuery.contents()例如

 $("#mydiv").contents().each(function(i,el){
  console.log(i,el)
  })

输出:

0, [object Text]
1, [object HTMLHRElement]
2, [object Text]
3, http://jsbin.com/mauris.html
4, [object Text]
5, [object HTMLDivElement]
6, [object Text]
7, [object HTMLHRElement]
8, [object Text]

因此,您可以根据需要轻松地分组。

答案 5 :(得分:0)

user191688代码的扩展版本。 这不仅仅是在兄弟姐妹中寻找“直到”,而且还在树上寻找。

(function($){

    $.fn.extend({
        nextUntilExtended: function(until) {
            var $set = $();
            var nxt = this.get(0).nextSibling;
            while(nxt) {
                if(!$(nxt).is(until)) {
                    if(nxt.nodeType != 3 && $(nxt).has(until)){
                        nxt = nxt.firstChild;
                    }else{
                        $set.push(nxt);
                        if(nxt.nextSibling){
                            nxt = nxt.nextSibling;
                        }else{
                            nxt = nxt.parentNode.nextSibling;
                        }
                    }
                } else break;
            }
            return($set);
        }
    });

})(jQuery);