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

Posted

技术标签:

【中文标题】需要 jQuery text() 函数来忽略隐藏元素【英文标题】:Need jQuery text() function to ignore hidden elements 【发布时间】:2011-11-14 23:50:48 【问题描述】:

我有一个这样的 div 设置:

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

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

$('#test').getText() 返回“你好,再见”。这是在 Firebug 中测试的一个衬里:jQuery('&lt;div id="test"&gt; &lt;p&gt;Hello&lt;/p&gt; &lt;p style="display: none"&gt;Goodbye&lt;/p&gt; &lt;/div&gt;').text()

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

有没有办法返回忽略 display:none'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

【问题讨论】:

【参考方案1】:

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

或者使用这个:

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

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

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

【讨论】:

澄清问题,元素嵌套深度是可变的。 然后改用这个$("#text :visible").text() 不幸的是这还不够,我认为我的问题很模糊,更新了 然后.remove()隐藏元素得到div的文字 有趣。我实际上是要说你在.remove() 之前先使用.clone(),但我似乎无法让它在jsfiddle 上工作。但如果它现在有效,那么恭喜。【参考方案2】:

在你的选择器中使用:visible

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

一个函数示例:

-- 编辑:

http://jsfiddle.net/8H5ka/(在 Chrome 上工作它在结果中显示“Hello”)

如果上述方法不起作用:

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

【讨论】:

这需要适用于任何任意元素并返回与突出显示 div 完全相同的输出。 div 可以有任意数量的嵌套子级。 @Jared,已编辑。安迪:以上怎么不符合这个目的? 编辑主要问题以澄清需求【参考方案3】:

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

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

【讨论】:

请注意,由于 x 仅包含 #test 而不是它的子级,所有这一切都会在 #test 不可见时将其删除。你需要做的是x.find('*').not(':visible').remove() 请记住,如果您克隆了某些内容但没有将其附加到 DOM 并使其可见,那么x.find('*').not(':visible').remove() 将删除 'x' 中的所有内容(文本节点除外,因为 find() 不包括他们)。【参考方案4】:

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

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

解决办法是:

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

代码:

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.

【讨论】:

【参考方案5】:

这是我使用 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, ' ');
    
)

【讨论】:

【参考方案6】:

我搜索并找到了这个问题,但没有解决方案。 对我来说,解决方案就是退出 jquery 来使用 DOM:

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

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

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

【讨论】:

以上是关于需要 jQuery text() 函数来忽略隐藏元素的主要内容,如果未能解决你的问题,请参考以下文章

jquery:需要一些函数来清空所有 <input> 值属性(在表单内),除了类型被隐藏的输入[重复]

在 jQuery 验证中忽略所有隐藏的 div 但不是一个

text 隐藏关于帖子的元数据

jQuery slideToggle,显示/隐藏速度

jQuery实现点击div外的区域,来隐藏指定节点

`tap` 函数如何被忽略?