需要jQuery text()函数来忽略隐藏的元素

时间:2011-09-12 00:57:43

标签: javascript jquery innertext

我有一个这样的div设置:

<div id="test"> <p>Hello</p> <p style="display: none">Goodbye</p> </div>

编辑:澄清一下,这是最简单的例子。 div可以有任意数量的n个深嵌套子项。

$('#test').getText()返回&#39; Hello Goodbye&#39;。这是在Firebug中测试的一个班轮:jQuery('<div id="test"> <p>Hello</p> <p style="display: none">Goodbye</p> </div>').text()

这似乎是因为jQuery在内部使用,textContent(对于非IE),将隐藏元素作为文本的一部分返回。 Hrmph。

有没有办法返回文本内容忽略display:none&#39; d元素?基本上我试图模仿你用鼠标突出显示div并复制到系统剪贴板的文本。这忽略了隐藏的文字。

有趣的是,如果您创建一个选择范围并从中获取文本,那么它也会返回display:none元素内的文本。

var range = document.body.createTextRange();
range.moveToElementText($('#test')[0]);
range.select();

console.log(range.toString()); // Also logs Hello Goodbye!

因此,创建文档选择范围似乎与使用鼠标在display:none元素方面突出显示相同。我如何解决这个肮脏的泡菜难题?

修改:建议使用.filter(':visible').text,但它不适用于此方案。我需要返回的文本完全是用鼠标选择的结果。例如:

$('<div>test1 <p>test2</p>\r\n <b>test3</b> <span style="display:none">none</span></div>').appendTo(document.body).children().filter(':visible').text()

返回

"test2test3"

当我真正想要的输出是

test1 test2
 test3

来自\ r \ n

的换行符,空格和所有内容

6 个答案:

答案 0 :(得分:4)

使用.filter(":visible")过滤元素。

或者使用它:

$("#test :visible").text();

jQuery documentation建议我们改用.filter()

因为:visible是jQuery扩展而不是CSS规范的一部分, 使用:visible的查询无法利用本机DOM querySelectorAll()方法提供的性能提升。要在使用时获得最佳性能:可见选择元素,首先使用纯CSS选择器选择元素,然后使用.filter(":visible")

答案 1 :(得分:2)

在选择器中使用:visible

$("#test > p:visible").text()

功能示例:

- 编辑:

http://jsfiddle.net/8H5ka/(适用于Chrome,在结果中显示“Hello”)

如果上述方法无效:

http://jsfiddle.net/userdude/8H5ka/1/

答案 2 :(得分:1)

如果空间不是主要问题,您可以复制标记,删除隐藏的元素,然后输出该文本。

var x = $('#test').clone();
x.filter(':not(:visible)').remove();
return x.text();

答案 3 :(得分:0)

我遇到了这个问题并发现了这个问题,看起来实际的解决方案是基于提供的答案而不是实际写出来的。所以这里有一个完整的解决方案,适用于我的情况,这与OP相同,附加规定元素可能由于基于DOM位置的外部样式而不可见。例如:

<style>.invisible-children span { display: none; }</style>
<div class="invisible-children">
  <div id="test">Hello <span>Goodbye</span></div>
</div>

解决方案是:

  1. 复制整个对象。
  2. 删除不可见的物体;如果我们在删除不可见对象之前将#test从DOM中取出,jQuery可能不知道它们是不可见的,因为它们将不再符合CSS规则。
  3. 获取对象的文本。
  4. 用我们制作的克隆替换原始对象。
  5. 代码:

    var $test = $('#test');
    // 1:
    var $testclone = $test.clone();
    // 2: We assume that $test is :visible and only remove children that are not.
    $test.find('*').not(':visible').remove();
    // 3:
    var text = $test.text();
    // 4:
    $test.replaceWith($testclone);
    // Now return the text...
    return text;
    // ...or if you're going to keep going and using the $test variable, make sure
    // to replace it so whatever you do with it affects the object now in DOM and
    // not the original from which we got the text after removing stuff.
    $test = $testclone;
    $test.css('background', 'grey'); // For example.
    

答案 4 :(得分:0)

以下是我使用MooTools的方法:

$extend(Selectors.Pseudo, {
    invisible: function() {
        if(this.getStyle('visibility') == 'hidden' || this.getStyle('display') == 'none') {
            return this;
        }
    }
});

Element.implement({
    getTextLikeTheBrowserWould = function() {
        var temp = this.clone();
        temp.getElements(':invisible').destroy();
        return temp.get('text').replace(/ |&amp;/g, ' ');
    }
})

答案 5 :(得分:0)

我进行搜索,发现了这个问题,但没有解决方案。 对我来说,解决方案是退出jquery以使用DOM:

var $test = $('#test').get(0).innerText

或者如果选择器数组中的元素多于on元素,则需要一个for循环和一个合并,但是我想大多数时候它是您需要的第一个版本。

var $test = $('#test').get().map(a => a.innerText).join(' ');