I am trying to find the right JavaScript code for a browser extension that replaces the word "winter" with the word "summer" in the text of a web page.
First attempt
Based on this blog post, my first attempt was
function wordFilter() {
let target = "winter";
let replace = "summer";
var html = document.querySelector('html');
var walker = document.createTreeWalker(html, NodeFilter.SHOW_TEXT);
var node;
while (node = walker.nextNode()) {
node.nodeValue = node.nodeValue.replace(target, replace);
}
}
wordFilter()
This almost works. It does replace "winter" with "summer", but the word "winter" still appears onscreen for a few seconds before it's replaced. I want the filter to work from the very beginning.
At the very least, this attempt shows that my general extension setup an permissions are correct, so any further failures must be code problems.
Second attempt
My second attempt was based on this answer to a StackOverflow post. It's an involved post, but the section under "Naive enumeration of added nodes" is closest to what I want. The code in the onMutation()
function searches for <h1>
elements that contain the target text; just for proof-of-concept, I simplified that part of the code to apply to all Elements that are descendants of an added Element. If the initial DOM load qualifies as a set of Mutations (which I'm still not clear on, but from context that appears to be the expected behavior), then this should capture every Element and every piece of text on the page.
The code:
var observer = new MutationObserver(onMutation);
observer.observe(document, {
childList: true, // report added/removed nodes
subtree: true, // observe any descendant elements
});
function onMutation(mutations, observer) {
for (var i = 0, len = mutations.length; i < len; i++) {
var added = mutations[i].addedNodes;
for (var j = 0, node; (node = added[j]); j++) {
replaceText(node);
}
}
}
function replaceText(el) {
let target_string = "winter";
let replacement_string = "summer";
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
for (let node; (node = walker.nextNode());) {
const text = node.nodeValue;
const newText = text.replace(target_string, replacement_string);
if (text !== newText) {
node.nodeValue = newText;
}
}
}
This does not work at all. No instance of the word "winter" is replaced with anything at any time under any conditions.
Now I'm at a loss. How do I replace text on a web page without the original text appearing before replacement?