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

发布于 2024-12-04 07:54:02 字数 1351 浏览 0 评论 0原文

我有一个 div 设置如下:

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

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

$('#test').getText() 返回“Hello Goodbye”。下面是在 Firebug 中测试的一行代码: jQuery('

Hello

Goodbye').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

I have a div set up something like this:

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

EDIT: To clarify, this is the simplest example. The div could have any arbitrary number of n deep nested children.

$('#test').getText() returns 'Hello Goodbye'. Here's a one liner to test in Firebug: jQuery('<div id="test"> <p>Hello</p> <p style="display: none">Goodbye</p> </div>').text()

This seems to be because what jQuery uses internally, textContent (for non IE), returns hidden elements as part of the text. Hrmph.

Is there a way to return the text content ignoring display:none'd elements? Basically I am trying to mimic the text you would get from highlighting the div with your mouse and copying to system clipboard. That ignores hidden text.

Interestingly, if you create a selection range and get the text from it, that also returns text inside display:none elements.

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

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

So creating a document selection range doesn't appear to do the same thing as highlighting with the mouse in terms of display:none elements. How do I get around this dirty pickle conundrum?

Edit: using .filter(':visible').text has been suggested, but it won't work for this scenario. I need the returned text to be EXACTLY what would come from a selection with the mouse. So for example:

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

returns

"test2test3"

When the output I actually want is

test1 test2
 test3

linebreaks, whitespace and all, which come from the \r\n

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

枫林﹌晚霞¤ 2024-12-11 07:54:02

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

或者使用这个:

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

但是 jQuery 文档 建议我们使用 .filter()< /code> 相反:

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

Filter the elements using .filter(":visible").

Or use this:

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

But the jQuery documentation advises us to use .filter() instead:

Because :visible is a jQuery extension and not part of the CSS specification,
queries using :visible cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. To achieve the best performance when using :visible to select elements, first select the elements using a pure CSS selector, then use .filter(":visible").

马蹄踏│碎落叶 2024-12-11 07:54:02

在选择器中使用 :visible ,如下所示:

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

函数示例:

-- 编辑:

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

如果上述方法不起作用:

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

Use :visible in your selector as such:

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

A Function example:

-- Edit:

http://jsfiddle.net/8H5ka/ ( Works on Chrome it displays "Hello" in Result )

If the above doesn't work:

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

海未深 2024-12-11 07:54:02

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

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

If space isn't a major concern you could copy the markup, remove the hidden elements, and output that text.

var x = $('#test').clone();
x.filter(':not(:visible)').remove();
return x.text();
小霸王臭丫头 2024-12-11 07:54:02

我搜索并发现了这个问题,但没有解决方案。
对我来说,解决方案就是摆脱 jquery 使用 DOM:

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

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

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

I search for that and found this question but without solution.
Solution for me is just get out of jquery to use DOM:

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

or if more than on element in array of selector, you need a for loop and a merge but I guess that most of time it is the first version that you need.

var $test = $('#test').get().map(a => a.innerText).join(' ');
秋心╮凉 2024-12-11 07:54:02

我遇到了这个问题并发现了这个问题,似乎实际的解决方案是基于提供的答案,但实际上并没有写出来。因此,这里有一个适合我的情况的完整解决方案,它与 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. 用我们制作的克隆替换原始对象。

代码:

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.

I had this problem and found this question, and it seems the actual solution is based on the provided answers but not actually written out. So here's a complete solution that worked for my situation, which is the same as the OP with the additional provision that elements may be invisible due to external styles based on DOM position. Example:

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

The solution is to:

  1. Make a clone of the entire object.
  2. Remove invisible objects in place; if we take #test out of the DOM before we remove invisible objects, jQuery might not know they're invisible because they will no longer match the CSS rules.
  3. Get the text of the object.
  4. Replace the original object with the clone we made.

The code:

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.
少女净妖师 2024-12-11 07:54:02

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

Here is how I did it with 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, ' ');
    }
})
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文