3

I want to replace all displaying text with something like "@@@@". It mean user will see all the page is full of "@@@@" instead of texts (except image, iframe or something doesn't exists in the page's HTML code).

This almost replace the html code of the page, but not effect to the tags and codes, just the text that display to user.

For example, I want to replace all the text in this page:

<!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>

And the result should be:

<!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>

Some I've been tried:

Use JQuery to replace all the elements, tags (and it's child) that only contain plain text, this works fine at the beginning:

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

But lately I realized that in case of elements, tags have child, it would failed:

<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>

So I tried another way, using document.body.innerText to select all the text, but the HTML format is lost.

I was so tired. Can someone help me?

Thanks a lot!

7
  • in case of elements, tags have child, it would failed: can you explain this case? Commented Jun 23, 2012 at 6:13
  • You need to replace anything between a > and a < in the body.innerHTML Commented Jun 23, 2012 at 6:18
  • @Furqan: If there are child tags, the function would check that is not a "plain text" and ignore them (the example HTML I showed). Commented Jun 23, 2012 at 9:20
  • @ScottS: In this case: <p> hello, click <a href=""asd.zxc">here</a></p> my link would be lost. Commented Jun 23, 2012 at 9:21
  • @TrungDQ No, since you would only replace between any two tags (be opening or closing). You would check for the > and < symbols, not the opening and closing tags that are on the same parent level. Commented Jun 23, 2012 at 9:38

4 Answers 4

9

This code seems to work for me:

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

Basically, it replaces the contents of each text node with @@@@.

For a demo, see here: http://jsfiddle.net/K8544/3/

Sign up to request clarification or add additional context in comments.

4 Comments

oh, perfect. You win. I never knew about nodeType.
Thank you very much! This works with almost page and I'm trying out this. Thank you!
If there is an <iframe> in the page, this doesn't work. Can you explain this case? Thank you! Waiting for your response, I'm nearly successful.
<iframe>s are somewhat special in this regard. Since I'm using .contents(), it should work, but I'm not really sure why it doesn't.
1

Try this one. It's a function that replaces inner text with "*", but only if its inner HTML is equal to its inner text. Otherwise, it calls itself recursively, navigating down the DOM until it reaches the innermost element.

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

It's not perfect, but should be pretty close for most purposes. I tried it on a Stack Overflow page, and most text got replaced. The only place it doesn't work is where there is stray markup and text within the same tag, for example <div>Here is some inner text <strong>and markup</strong></div>. Maybe this suffices for your purpose though ...

2 Comments

This would break most of the OP's tags.
Sorry, I was wrong. But anyway the code fails where you said, so it's not quite a general solution to the OP's request.
1

A JQuery-only solution:

$("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/

This code wraps EVERY node with a custom tag (obscure); the use of .contents() makes sure we wrap ALSO the pure text nodes. Then we substitute the obscure nodes which have no children (that were text-only nodes before) with @@@@, hence eliminating also the obscure tags. Finally, we unwrap the other elements that were wrapped with <obscure>.

2 Comments

@TrungDQ let me know if this is what you want to achieve.
Hi! Sorry for late reply. I've tried to use your code but seem like it doesn't work in almost page. Your fiddle example works fine, but when I used this code with larger HTML page, it didn't work. Blender's solution work fine for me. Anyway, thanks for your help :)
1

You can match anything between two tags - these don't have to be the same tag. For instance, <div>aaa<a href="bbb">ccc dd</a></div>, it would find aaa, replace it with @@@, then find ccc dd and replace it with @@@ @@ by looking between > and the next <.

<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>

(Note: This does not replace whitespace, since that appeared to be causing some issues).

1 Comment

Oh, I see. Sorry I was so silly. This would work very well, seem quite complex at first but I think it is faster than the JQuery one. Thanks for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.