需要 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('<div id="test"> <p>Hello</p> <p style="display: none">Goodbye</p> </div>').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(/ |&/g, ' ');
)
【讨论】:
【参考方案6】:我搜索并找到了这个问题,但没有解决方案。 对我来说,解决方案就是退出 jquery 来使用 DOM:
var $test = $('#test').get(0).innerText
或者如果选择器数组中的元素不止一个,您需要一个 for 循环和一个合并,但我想大多数时候它是您需要的第一个版本。
var $test = $('#test').get().map(a => a.innerText).join(' ');
【讨论】:
以上是关于需要 jQuery text() 函数来忽略隐藏元素的主要内容,如果未能解决你的问题,请参考以下文章