【问题标题】:How to change text inside span with jQuery, leaving other span contained nodes intact?如何使用jQuery更改跨度内的文本,使其他跨度包含的节点保持不变?
【发布时间】:2012-02-28 18:12:52
【问题描述】:

我有以下 HTML sn-p:

<span class="target">Change me <a class="changeme" href="#">now</a></span>

我想从 jQuery 更改跨度内的文本节点(即“更改我”),同时保留所有属性等的嵌套 &lt;a&gt; 标记。我最初的想法是在 span 节点上使用 .text(...),但因为它是 turns out,这将用传递的文本内容替换整个内部。

我解决了这个问题,首先克隆&lt;a&gt;标签,然后设置&lt;span&gt;的新文本内容(这将删除原来的&lt;a&gt;标签),最后将克隆的&lt;a&gt;标签附加到我的@987654332 @。这行得通,但对于像这样的简单任务来说,感觉有点过头了。顺便提一句。我不能保证跨度内会有一个初始文本节点 - 它可能是空的,就像:

<span class="target"><a class="changeme" href="#">now</a></span>

我也做了jsfiddle。那么,这样做的巧妙方法是什么?

【问题讨论】:

标签: javascript jquery html dom


【解决方案1】:

尝试类似:

$('a.changeme').on('click', function() {
  $(this).closest('.target').contents().not(this).eq(0).replaceWith('Do it again ');
});

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

参考:http://api.jquery.com/contents/

更新

我想我读错了你的问题,如果文本已经存在,你试图替换它,否则注入它。为此,请尝试:

$('a.changeme').on('click', function() {
  var
    $tmp = $(this).closest('.target').contents().not(this).eq(0),
    dia = document.createTextNode('Do it again ');

  $tmp.length > 0 ? $tmp.replaceWith(dia) : $(dia).insertBefore(this);
});

​演示:http://jsfiddle.net/eEMGz/3/

【讨论】:

  • 这似乎是一个在代码中向上扩展 jQuery 的好地方,只是为了保持工作代码的整洁;你这么认为吗?
  • @CodeJunkie 我不确定。如果这只是一遍又一遍,那么插件可能没问题,但否则我会坚持不扩展 jquery 来完成这么小的任务。
【解决方案2】:

你可以使用.contents():

//set the new text to replace the old text
var newText = 'New Text';

//bind `click` event handler to the `.changeme` elements
$('.changeme').on('click', function () {

    //iterate over the nodes in this `<span>` element
    $.each($(this).parent().contents(), function () {

        //if the type of this node is undefined then it's a text node and we want to replace it
        if (typeof this.tagName == 'undefined') {

            //to replace the node we can use `.replaceWith()`
            $(this).replaceWith(newText);
        }
    });
});​

这是一个演示:http://jsfiddle.net/jasper/PURHA/1/

为你准备的一些文档:

更新

var newText = 'New Text';
$('a').on('click', function () {
    $.each($(this).parent().contents(), function () {
        if (typeof this.tagName == 'undefined') {

            //instead of replacing this node with the replacement string, just replace it with a blank string
            $(this).replaceWith('');
        }
    });

    //then add the replacement string to the `<span>` element regardless of it's initial state
    $(this).parent().prepend(newText);
});​

演示:http://jsfiddle.net/jasper/PURHA/2/

【讨论】:

  • “顺便说一句。我不能保证跨度内会有一个初始文本节点 - 它可能是空的”这个测试用例失败。
  • @AndrásSzepesházi 我没有意识到您也想将新字符串添加到空容器中。我更新了我的答案,这是一个演示:jsfiddle.net/jasper/PURHA/2
【解决方案3】:

你可以试试这个。

var $textNode, $parent;
$('.changeme').on('click', function(){
    $parent = $(this).parent(); 
    $textNode= $parent.contents().filter(function() {
            return this.nodeType == 3;
    });
    if($textNode.length){
        $textNode.replaceWith('Content changed')
    }
    else{
        $parent.prepend('New content');
    }
});

工作演示 - http://jsfiddle.net/ShankarSangoli/yx5Ju/8/

【讨论】:

  • 你忘了更新你的小提琴,但上面引用的代码在两种情况下都很好地工作(即有/没有)初始文本。
  • 一个奇怪的行为是,如果&lt;a&gt; 元素的两边都有文本节点,它们都会被新文本替换:jsfiddle.net/jasper/yx5Ju/9
  • @Jasper - 如果是这种情况,那么它可以在代码中处理。如果存在这种情况,OP 会更清楚。
【解决方案4】:

您退出 jQuery 是因为它无法帮助您处理文本节点。当且仅当它存在并且是一个文本节点时,以下将删除每个具有类“target”的&lt;span&gt; 元素的第一个子元素。

演示:http://jsfiddle.net/yx5Ju/11/

代码:

$('span.target').each(function() {
    var firstChild = this.firstChild;
    if (firstChild && firstChild.nodeType == 3) {
        firstChild.data = "Do it again";
    }
});

【讨论】:

  • 谢谢!稍作改动,这适用于我需要的两种情况(文本替换和插入模式)jsfiddle.net/yx5Ju/12
【解决方案5】:

我猜这不是一个完美的例子,但你可以使用contents 函数。

console.log($("span.target").contents()[0].data);

【讨论】:

    【解决方案6】:

    您可以将文本包装成一个跨度...但是...

    试试这个。 http://jsfiddle.net/Y8tMk/

    $(function(){
        var txt = '';
        $('.target').contents().each(function(){
            if(this.nodeType==3){
                        this.textContent = 'done ';
            }
        });
    });
    

    【讨论】:

    • “顺便说一句。我不能保证跨度内会有一个初始文本节点 - 它可能是空的”这个测试用例失败。否则很酷。
    【解决方案7】:

    您可以更改对象的本机(非 jquery)数据属性。在这里更新了 jsfiddle:http://jsfiddle.net/elgreg/yx5Ju/2/

    类似:

    $('a.changeme3').click(function(){
        $('span.target3').contents().get(0).data = 'Do it again';
    });
    

    contents() 获取内脏,get(0) 让我们回到原始元素,.data 现在是对本机 js 文本节点的引用。 (我没有测试过这个跨浏览器。)

    这个 jsfiddle 和答案实际上只是对这个问题的答案的扩展解释: Change text-nodes text

    【讨论】:

    • “顺便说一句。我不能保证跨度内会有一个初始文本节点 - 它可能是空的”这个测试用例失败。否则很酷。
    【解决方案8】:
    $('a.changeme').click(function() {                         
        var firstNode= $(this).parent().contents()[0];
            if( firstNode.nodeType==3){
            firstNode.nodeValue='New text';
        }
    })
    

    编辑:不确定您需要什么布局规则,更新以仅测试第一个节点,否则根据需要进行调整

    【讨论】:

    • “顺便说一句。我不能保证跨度内会有一个初始文本节点 - 它可能是空的”这个测试用例失败。否则很酷。
    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 2021-12-20
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-21
    相关资源
    最近更新 更多