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?
3 Answers 3
Simple regular expression to fix it:
document.body.innerHTML = document.body.innerHTML.replace(/target string/g, "replacement string");
3 Comments
I'd recommend against replacing the innerHTML for a few reasons from this blog (https://j11y.io/javascript/replacing-text-in-the-dom-solved/):
- You can't guarantee that the text replaced is text. Maybe it's an attribute in the html or other relevant code.
- 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
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!
innerHTMLfor a number of reasons; for one thing you will risk modifying the contents of HTML tags and attributes.innerHTMLis an awful approach. Read here: stackoverflow.com/q/7392930/425275