替换在浏览器中显示的所有文本

3
我希望替换所有显示的文本为"@ @ @ @", 这意味着用户将会看到整个页面都是"@ @ @ @"而不是文字(除了图片,iframe或其他不存在于页面HTML代码中的东西)。
这几乎替换了页面的HTML代码,但不影响标签和代码,只影响显示给用户的文本。
例如,我想替换此页面中的所有文本:
<!DOCTYPE html>
<html>
<body>                  
<ul class="topnav">
    <li>Item 1</li>
    <li>Item 2 
        <ul><li>Nested item 1</li><li>Nested item 2</li><li>Nested item 3</li></ul>
       </li>
    <li>Item 3</li>
</ul>
<div>DIV1</div>
<div>DIV2</div>
<span>SPAN</span>
<table>
<tr>
    <td>Username</td>
</tr>
<tr>
    <td>Password</td>
</tr>
</table>
<p>
  <input type="checkbox" name="remember" tabindex=3 />
  <label for="checkbox">Remember <strong>password</strong></label>
</p>
<p>Click here to <a href='register.php'>Register</a></p>
</body>
</html>

结果应该是:

<!DOCTYPE html>
<html>
<body>                  
<ul class="topnav">
    <li>@@@@</li>
    <li>@@@@ 
        <ul><li>@@@@</li><li>@@@@</li><li>@@@@</li></ul>
       </li>
    <li>@@@@</li>
</ul>
<div>@@@@</div>
<div>@@@@</div>
<span>@@@@</span>
<table>
<tr>
    <td>@@@@</td>
</tr>
<tr>
    <td>@@@@</td>
</tr>
</table>
<p>
  <input type="checkbox" name="remember" tabindex=3 />
  <label for="checkbox">@@@@<strong>@@@@</strong></label>
</p>
<p>@@@@<a href='register.php'>@@@@</a></p>
</body>
</html>

我已经尝试过以下方法:

使用JQuery替换所有仅包含纯文本的元素、标签(及其子标签),这在一开始是可行的:

<ul class="topnav">
    <li>@@@@</li>
    <li>@@@@ 
        <ul><li>@@@@</li><li>@@@@</li><li>@@@@</li></ul>
       </li>
    <li>@@@@</li>
</ul>
<div>@@@@</div>
<div>@@@@</div>
<span>@@@@</span>

但最近我意识到,在元素的情况下,如果标签有子元素,它将失败:

<p>
  <input type="checkbox" name="remember" tabindex=3 />
  <label for="checkbox">Remember <strong>password</strong></label>
</p>
<p>Click here to <a href='register.php'>Register</a></p>

因此,我尝试了另一种方法,使用 document.body.innerText 选择所有文本,但是 HTML 格式丢失了。

我感到很累。有人能帮忙吗?

非常感谢!


如果元素或标签有子元素,它将会失败:你能解释一下这种情况吗? - Furqan Hameedi
你需要替换 body.innerHTML 中在 >< 之间的任何内容。 - Scott Stevens
@ScottS:在这种情况下:<p>你好,点击<a href=""这里" rel = "nofollow noreferrer">http://asd.zxc">这里</a></p>我的链接会丢失。 - Tony Dinh
@TrungDQ 不,因为您只会在任何两个标记之间进行替换(无论是开放还是关闭)。 您将检查><符号,而不是位于同一父级上的开放和关闭标记。 - Scott Stevens
@ScottS 我明白你的意思,但是这里有一个例子:<p> hello <strong>world</strong>, now kiss</p>。根据你的方法,结果是:<p> hello <strong>@@@@</strong>, now kiss</p>,但我想要的结果是:<p>@@@<strong>@@@</strong>@@@</p>。我考虑使用正则表达式,但它变得非常复杂。你能找到更有效的方法吗? :-( - Tony Dinh
显示剩余2条评论
4个回答

9

这段代码对我来说似乎有效:

$('*').contents().filter(function() {
    return this.nodeType == Node.TEXT_NODE && this.nodeValue.trim() != '';
}).each(function() {
    this.nodeValue = '@@@@';
});

基本上,它将每个文本节点的内容替换为@@@@。
演示请看这里:http://jsfiddle.net/K8544/3/

哦,太好了。你赢了。我从来不知道 nodeType - McGarnagle
非常感谢!这几乎适用于所有页面,我正在尝试这个。谢谢! - Tony Dinh
如果页面中有一个<iframe>,这就不起作用了。您能解释一下这种情况吗?谢谢!等待您的回复,我快要成功了。 - Tony Dinh
在这方面,<iframe>有些特殊。由于我正在使用.contents(),它应该可以工作,但我不太确定为什么它不起作用。 - Blender

1

试试这个。它是一个函数,用"*"替换内部文本,但仅当其内部HTML等于其内部文本时才这样做。否则,它会递归调用自身,沿着DOM向下导航,直到达到最内部的元素。

    $(document).ready(function() {
        function replaceChildren(node) {
            if ($(node).html() == $(node).text()) $(node).text("@@@@");
            else {
                $(node).children().each(function() {
                    replaceChildren(this);
                });
            }
        }
        replaceChildren($("body"));
    });

这不是完美的,但对于大多数情况应该相当接近。我在 Stack Overflow 页面上尝试过它,大部分文本都被替换了。唯一不起作用的地方是存在杂乱标记和文本的同一标签中,例如<div>Here is some inner text <strong>and markup</strong></div>。也许这已经足够满足您的目的了...


这将破坏大多数OP的标签。 - Cranio
抱歉,我错了。但无论如何,代码在你所说的地方失败了,因此它并不完全是对OP请求的一般解决方案。 - Cranio

1

一个仅使用 JQuery 的解决方案:

$("body *").contents().wrap("<obscure></obscure>");
$("obscure").each(function(i,e) {if ($(e).children().length==0) $(e).replaceWith("@@@@");}​);
$("obscure > *").unwrap();

http://jsfiddle.net/cranio/CW9jY/1/

这段代码使用自定义标签(obscure)包装了每个节点;使用 .contents() 确保我们也包装了纯文本节点。 然后,我们将没有子元素的 obscure 节点(之前是纯文本节点)替换为 @@@@,从而消除了 obscure 标签。 最后,我们取消包装其他被包装在 <obscure> 中的元素。


@TrungDQ,请告诉我这是否是您想实现的内容。 - Cranio
嗨!抱歉回复晚了。我尝试使用你的代码,但似乎在几乎所有页面上都不起作用。你的fiddle示例运行良好,但当我在更大的HTML页面中使用此代码时,它无法正常工作。Blender的解决方案对我很有效。无论如何,感谢你的帮助 :) - Tony Dinh

1

您可以匹配两个标签之间的任何内容 - 这些标签不必相同。例如,<div>aaa<a href="bbb">ccc dd</a></div>,它会找到 aaa,用 @@@ 替换它,然后查找 ccc dd 并通过在 > 和下一个 < 之间查找来替换它为 @@@ @@

<script type="text/javascript">
function obscure() {
    var newhtml = document.body.innerHTML.split("<");
    for (var i=1; i<newhtml.length; i++) {
        var list = newhtml[i].split(">");
        newhtml[i] = (list[0]) + ">" + ((list[1]).replace(/[^@\s]/gim, "@"));
    }
    newhtml[0] = (newhtml[0].replace(/[^@\s]/gim, "@"));
    document.body.innerHTML = newhtml.join("<");
}
</script>

(注:这不会替换空格,因为那可能会引起一些问题。)

哦,我明白了。真抱歉,我刚才太傻了。这个方法会很好用,一开始看起来有点复杂,但是我觉得比使用JQuery要快。谢谢你的帮助! - Tony Dinh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接