仅在找到“内容/文本”时附加元素

时间:2011-07-03 12:26:36

标签: jquery text append element

使用jquery可以执行以下操作:

鉴于标有h1到h6的文件,只有在标题后面和下一个标题之前写入文字时,才在每个标题元素后附加“返回顶部”链接。

所以:

<h1>h1</h1>
<p>text</p>
<h2>h2</h2>
<h3>h3</h3>
text text
<h4>h4</h4>
<br><br>
<h5>h5</h5>
<br><br>text
<h6>h6</h6>
<div>test</div>

会导致

<h1>h1</h1>
<p>text</p>
<a..>back to top</a>
<h2>h2</h2>
<h3>h3</h3>
text text
<a..>back to top</a>
<h4>h4</h4>
<br><br>
<h5>h5</h5>
<br><br>text
<a..>back to top</a>
<h6>h6</h6>
<div>test</div>
<a..>back to top</a>

所以文字可以是段落,div,跨度,或者根本没有标记......

我不知道如何做到这一点,以及如何在下一个元素之前选择最后一个元素(或者如果它是最后一个?)将链接附加到。

欢迎任何帮助(不一定是完整的解决方案)。

修改: 最大的问题是:

不幸的是我正在使用不输出段落的cms,而是输出

 <h1>..</h1><br>text<br><br><h2>h2</h2> 

依旧......

所以:

<h1>test</h1>
<br>
<h2>test</h2>

使用此处提供的第二个解决方案,当它不应该添加顶部链接时...我不确定如何防止这种情况。

编辑2:

尝试改为:

$('#content').find('h1, h2, h3, h4, h5, h6').each( function(i, item) {
    var nextItems = $(item).nextUntil('h1, h2, h3, h4, h5, h6');

    if (nextItems.filter('p, div, span').size() > 0 || nextItems.filter(function() {
        return this.nodeType == Node.TEXT_NODE;
    }).size() > 0) {
        nextItems.last().after('<p><a href="#toc-top" class="toc-top">Back To Top</a></p>');
    }
});

但它永远不会找到文本节点..任何理由?内容只是h2,后面是br和text ...

3 个答案:

答案 0 :(得分:1)

$("h1,h2,h3,h4,h5,h6").next('p,div,span').after('<a>To Top</a>');

最快我能拿出来。如果文本不在容器中,则无效。如果你可以在插入之前在文本周围包装一个容器就很容易了。

$('yourcontainer').each(function(){
    if($(this).text() != "") {
        $(this).after('<a>To Top</a>');
    }
});

修改

我认为提供的其他答案可能很好但我在输出中看到了一个模式,因此为您提供了这个简单的建议: $("h1,h2,h3").next('br').next('br').next('br').after('<a>To top</a>');

假设:您的模式为(<htag>htag</htag><br>if(text){<br>text<br>})*

答案 1 :(得分:1)

这很容易,只要你把文字放在你的后面 带有容器的标题标签:

$(document).ready(function() {

    $('h1, h2, h3, h4, h5, h6').each( function(i, item) {
        if ( $(item).nextUntil('h1, h2, h3, h4, h5, h6').text() ) {
            $(item)
                .nextUntil('h1, h2, h3, h4, h5, h6').last()
                .after('<a href="#top">Back To Top</a>');
        }
    });

});

无论您在标题后有多少个节点,只要文本包含在某种标记中,这都可以正常工作。

更新如果你不能用另一个标签包装文本节点,我的建议是首先使用jQuery来实现这一点 - 这将允许我们一致地处理代码,并解决限制nextUntil。将上面的代码更新为以下内容:

$(document).ready(function() {

    // wrap text nodes with a span
    $('#container') // note that I'm using a container reference to scope this - adjust as needed 
      .contents()
      .filter(function() {
        return this.nodeType == 3; //Node.TEXT_NODE
      }).wrap('<span class="temp" />');

    $('h1, h2, h3, h4, h5, h6').each( function(i, item) {
        var items = $(item).nextUntil('h1, h2, h3, h4, h5, h6');
        if ( items.text().match(/[^\s]/gi) ) {
            // Only insert a back to top link if these nodes contain at least one non-whitespace character
            items.last()
                .after('<a href="#top">Back To Top</a>');
        }
    });

    $('#container').find('span.temp').replaceWith(function () {
        return $(this).text();
    });

});

这是jsfiddle

答案 2 :(得分:0)

您可以使用'.contents()'方法识别文本节点。

    $(document).ready(function () {
        $('#content').contents()
            .filter(function () { return (this.nodeType == 3); })
            .wrap('<p class="temp"></p>');

        var headers = "h1,h2,h3,h4,h5,h6";
        $(headers).each(function () {
            var $currentHeader = $(this);
            if ($currentHeader.is('h6')) {
                var $siblings = $currentHeader.nextAll();
                if ($siblings.text().trim()) {
                    $siblings.last().after('<a href="#">Top</a>');
                }
            }
            else {
                if ($currentHeader.nextUntil(headers).text().trim()) {
                    $currentHeader.nextAll(headers).first().before('<a href="#">Top</a>');
                }
            }
        });

        $('#content').find('.temp').replaceWith(function () {
            return $(this).text();
        });

    });

基本上,我找到所有文本节点并将它们包装在一个临时的<p>中。然后,我们在必要时添加<a>元素。完成整个处理后,我们会安全地删除临时<p>元素。

Jsfiddle Link:http://jsfiddle.net/amritayan/GXLFL/