8

I'm trying to write a JavaScript program without the use of jQuery to replace all visible target text on a webpage without messing up the page's functionality.

Specifically I'm trying to make a Chrome extension that does it passively on sites such as Facebook.

I've experienced limited success with the following:

checkLoad();
function checkLoad(){
    if (document.readyState === "complete") {
        document.body.innerHTML = document.body.innerHTML.replace("target string", "replacement string");
    } else {
        setTimeout('checkLoad();', 500)
    }
}

This code misses things like people's names, titles and such.

I've looked around and can't seem to find a working solution. Any ideas?

7
  • 1
    Can you give an example of what it misses? If it's stuff loaded via AJAX for example then, yeah, you might miss it unless you keep checking constantly. Commented Nov 25, 2012 at 0:59
  • 4
    I don't recommend using innerHTML for a number of reasons; for one thing you will risk modifying the contents of HTML tags and attributes. Commented Nov 25, 2012 at 1:00
  • The Javascript function .replace takes a regex as the first argument. Try replacing the first argument with the equivalent regex version of it (i.e. escaping all regex special characters, etc.) Commented Nov 25, 2012 at 1:00
  • Re-writing innerHTML is an awful approach. Read here: stackoverflow.com/q/7392930/425275 Commented Nov 25, 2012 at 1:01
  • It misses things like if I enter a person's name, the name will be unchanged beside all their posts, where as their name in comments or post content changes fine. Commented Nov 25, 2012 at 1:11

3 Answers 3

11

Simple regular expression to fix it:

document.body.innerHTML = document.body.innerHTML.replace(/target string/g, "replacement string");
Sign up to request clarification or add additional context in comments.

3 Comments

That did solve my problem with innerHTML replace! Thank you. Though apparently this is no longer the right approach to my problem, good to know for the future.
One issue with this approach is that it unbinds javascript event handlers from the DOM.
A warning - this seems to reload the entire document, causing any events fired from a chrome extension to refire. I haven't found a fix for it, as I just discovered the problem. FYI for the one other person in the universe this affects...
1

I'd recommend against replacing the innerHTML for a few reasons from this blog (https://j11y.io/javascript/replacing-text-in-the-dom-solved/):

  1. You can't guarantee that the text replaced is text. Maybe it's an attribute in the html or other relevant code.
  2. It resets the document and, in my case, fired my chrome extension again. This led to my extension reloading again and again.

I solved this by downloading the js file from the blog and called it like so:

  var regex = new RegExp(targetString, "g");
  findAndReplaceDOMText(document.body, {
    find: regex,
    replace: function(portion) {
      var e = document.createElement('span');
      e.appendChild(document.createTextNode(replacementString));
      return e;
    }
  });

My use case above wraps the text being replaced in a span tag, so it's slightly different than yours. This javascript function has lots of flexibility.

Comments

1

The link https://j11y.io/javascript/replacing-text-in-the-dom-solved/ is cool but I'm not 100% agree with a solution. IMHO walking on DOM could be overkill.

Here is my tricky solution working on regexp only so can element.innerHTML be used. So that replaces text everywhere except tags and nbsp-like things:

function highlightInHtml(html, textToHighlight) {
  const t = textToHighlight'

  const tagsRe = new RegExp('(<.+?>|&\\w+;)');

  const htmlParts = html.split(tagsRe).filter(Boolean);

  const r = htmlParts.map( item =>
    tagsRe.test(item)
      ? item
      : item.replace(new RegExp(`(${t})`, 'ig'), `<span class="highlight">$1</span>`)
  ).join('');

  return r;
}

If there is something weak in this solution please let me know!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.