jQuery 在
之间包裹文本和元素标签

发布于 2024-09-10 05:49:01 字数 774 浏览 1 评论 0原文

我需要包装两个


元素之间的所有内容,包括自由文本。

鉴于此来源:

<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') 因为这不会选择未标记的文本。

I need to wrap everything, including free text, that is between two <hr> elements.

Given this source:

<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>

I need to wrap everything between the hr.begin and hr.end tags, like so:

<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>

I cannot use a method like .nextUntil('hr.end') because this will not select the untagged text.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

眼角的笑意。 2024-09-17 05:49:01

更新

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

(部分灵感来自JP给出的答案。)

$('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() 返回所有节点,包括文本节点。所以这里我们遍历到hr.begin.parent(),使用.contents()获取其所有节点,然后过滤它们,跟踪我们何时找到开始和结束,并且只返回它们之间的元素。

然后我们使用 .wrapAll() 将它们与 div.content 包裹起来。


编辑: 如果要换行多个集合,请尝试以下操作: http://jsfiddle.net/LbmCg/1/

编辑: 清理了两者中的一些内容例子。

Updated

I like this version better than my previous: http://jsfiddle.net/LbmCg/3/

(Partly inspired from the answer J-P gave.)

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

Original answer

Try this: http://jsfiddle.net/LbmCg/

If there's more than one set to wrap, there will some adjustment needed.

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's .contents() returns all nodes including text nodes. So here we traverse to the .parent() of the hr.begin, get all of its nodes using .contents() then filter through them, tracking when we've found the beginning and the end, and only returning the elements between them.

Then we use .wrapAll() to wrap them with the div.content.


EDIT: If there are multiple sets to wrap, try this: http://jsfiddle.net/LbmCg/1/

EDIT: Cleaned things up a little in both examples.

两仪 2024-09-17 05:49:01
​$('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">');

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

这可以处理多组开始-内容-结束序列。它将查找前面有 hr.begin 元素的所有 hr.end 元素,并且对于每个 hr.end ,查找之间的前面的节点它和 hr.begin,然后它将它们全部包装在

中。

​$('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">');

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

This can handle multiple sets of the begin - contents - end sequence. It will look for all hr.end elements preceded by hr.begin elements and will, for each hr.end, find the preceding nodes between it and hr.begin, and then it'll wrap them all in a <div class=content>.

请恋爱 2024-09-17 05:49:01

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 可能会有所帮助。

我用帕特里克的测试数据尝试了这个解决方案,它有效:

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"));​​​​​​​​​​​​​​​​​

theElement.contents() will recognize text nodes. Since jQuery.nextUntil() is actually a wrapper around jQuery.dir, which does

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;
},

where text nodes that get filtered out have a nodeType of 3, a custom jQuery.dir might help here.

I tried this solution with Patrick’s test data and it works:

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"));​​​​​​​​​​​​​​​​​
恍梦境° 2024-09-17 05:49:01

有类似的问题,但我使用的是基于 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" />');
});

Had a similar problem, but I was using a CMS based on FCKEditor that didn't work so hot because of insertion of newline TextNodes from using the nextSibling property. I generally don't like to mix jQuery stuff with native JavaScript if I can help it either. I came up with this snippet that updates Patrick DW's solution that would probably be a bit more friendly for jQuery usage. Also doesn't require classes to determine next block.

$('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" />');
});
失而复得 2024-09-17 05:49:01

如果您的 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]

这样您就可以根据需要轻松地将它们分组。

If you HR and other tags are inside a div e.g.

<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>

You can use jQuery.contents() e.g.

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

outputs:

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]

So you can easily club them in groups as you need.

浪推晚风 2024-09-17 05:49:01

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);

A extended version of user191688's code.
This on is not only looking for the "until" in siblings but also up and down the tree.

(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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文