如何使用JQuery(或Javascript)获取可见文本

时间:2009-12-04 10:43:01

标签: javascript jquery

我的网站转换Japanese Kanji into romaji (roman letters)

并且输出显示并隐藏了CSS用户需要查看的内容,具体取决于他们的输入条件。例如:

<div id="output">
    <span class="roman">watashi</span> 
    <span class="english">I</span>
</div>

界面允许用户在watashiI之间切换和输出,具体取决于他们想要查看的内容。

CSS使用jQuery和切换按钮隐藏其中一个或另一个。 (隐藏机制包括简单地向body添加一个类并让CSS做它的事情。)

问题在于,当用户将文本复制/粘贴到Word时,它会复制所有内容。所以我决定使用系统来复制使用JavaScriptjQuery粘贴文本,但问题会重演:

$('#output').text()
即使watashi I在页面本身不可见,

输出I 而不是watashi。有没有办法得到可见的文字?

6 个答案:

答案 0 :(得分:17)

其他解决方案没有给我我需要的东西。

简答

我的回答是:

$('#output *:not(:has(*)):visible').text()

plunkr

TL; DR

marcgg解决方案的问题

你不应该在某个根元素下询问所有元素的文本。

为什么呢? - 它将重复输出并忽略隐藏标志

让我们看一个简单的例子

<div id="output" class="my-root">
    <div class="some-div">
         <span class="first" style="display:none"> hidden text </span>
         <span class="second" > visible text </span>
    </div>
<div>

现在如果我做$('#output').children(":visible").text()

我会得到.some-div.second .. 事实上.some-div对我来说毫无顾虑......

当我在这些元素上询问text()时,.some-div也会返回隐藏文字。

所以技术上marcgg的解决方案是错误的恕我直言......

我回答的原因

现在,为了正确回答这个问题,我们必须做出一个假设。对我来说,这似乎是合理的。

假设是文本只出现在叶元素中..

所以我们不会看到这样的事情:

<div id="output" class="my-root">
    <div class="some-div">
         <span class="first" style="display:none"> hidden text </span>
         <span class="second" > visible text </span>
    </div>

    some text here.. 

<div>

为什么这个假设对我来说似乎合情合理?有两个原因:

  • 因为很难维护以这种方式构建的页面 - 并且随着时间的推移,有经验的人会学习并避免它。
  • 很容易将您的html转换为这样的结构。用跨度包装父母的文本。因此,即使现在不存在这种假设,也很容易实现。

根据这个假设,你想要做的是请求所有叶元素(没有子元素的元素),过滤掉可见元素,并询问它们的文本..

$('#output *:not(:has(*)):visible').text()

这应该会产生正确的结果。

要在叶元素外面有文字吗?

评论表明,有时你只需要在leaf元素之外有文本

<div> This is some <strong style="display:none"> text </strong>  </div>

正如您所看到的,您将<strong>作为一个叶子,并且在此示例中通常会在其外部显示文本。

你可以解决我上面建议的解决方法..但如果你不能怎么办?

您可以克隆dom,然后删除所有隐藏的元素。 这里的问题是,为了:visible选择器或:hidden选择器工作,我必须在文档上有dom元素(这意味着用户实际可见)。 因此,这种方法会带来一些副作用,所以要小心。

这是一个例子

这个html

 <div id="output" class="my-root">
     <span>
         some text <strong style="display:none">here.. </strong>
     </span>
</div>

这个javascript工作

$(function(){
     var outputClone = $('#output').clone();
    $('#output :hidden').remove(); 
    console.log($('#output').text()); // only visible text
    $('#output').replaceWith(outputClone);
    console.log($('#output').text()); // show original state achieved. 
})

请参阅plunker here

如上所述 - 副作用可能看起来像一个瞬间闪烁,或一些应该运行的初始化脚本..有些原始思维可能会避免(div大小为1px / 1px以包含克隆和原始内容?)取决于你的情景。

答案 1 :(得分:11)

使用:visible selector of Jquery

在你的情况下,我认为你想做:

$('#output').children(":visible").text() 

答案 2 :(得分:3)

在现代浏览器中尝试此操作(此处&#39; element&#39;是非JQuery DOM对象):

function getVisibleText(element) {
    window.getSelection().removeAllRanges();

    var range = document.createRange();
    range.selectNode(element);
    window.getSelection().addRange(range);

    var visibleText = window.getSelection().toString().trim();
    window.getSelection().removeAllRanges();

    return visibleText;
}

然后:

getVisibleText(document.getElementById('output'));

答案 3 :(得分:1)

盖伊有正确的答案。

但是,我正在处理一个“this”对象,所以为了得到他的工作答案,你需要使用以下语法......

$('*:not(:has(*)):visible', this).text()

答案 4 :(得分:1)

var lookup = function(element, text) {
    //DFS Recursive way of finding text on each level
    //Visible only works on elements that take up space(i.e. not fixed position elements)
    var results = element.children(':visible');

    //Look at the text at each level with the children removed
    var newText = '';
    results.each(function(index, value) {
        newText += $(value).clone()
            .children()
            .remove()
            .end()
            .text();
    });

    var moreResultText = '';
    results.each(function(index, value) {
        moreResultText += lookup($(value), text);
    })

    if (results.length > 0) {
        return text + newText + moreResultText;
    } else {
        return text;
    }
};

lookup($('#output'), ''));

大多数其他功能在页面的大部分区域运行时会崩溃,这应该是一种更准确的方法来确定实际显示给用户的内容,而不会破坏页面,也不会返回不可见的文本用户。

当然要小心,这不会保留任何格式化感,并且元素之间输出的间距可能不正确。此外,它可能无法正确排序返回的文本,在这些方面,它的用法将受到限制。另一个考虑因素是可见的真正定义对于nail down来说有点困难,但是对于这个例子我接受了#34;:visible&#34;适用于大多数常见情况。

我用它来检查一个页面是否包含可见文本(只是在body元素上运行它),但它也可能适用于这个例子。

答案 5 :(得分:0)

不是隐藏跨度,而是删除span元素并保留对它的引用。当用户单击切换按钮时,删除另一个并插入您保留引用的那个按钮。用户将无法再选择不在DOM中的内容。