Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run Chrome extension code repeatedly on infinite scroll pages

This is my first Chrome extension. I am building an extension to replace text on a page.

the provided code works great on anything loaded by DOMContent loaded. However on pages that use some sort of infinite scrolling, when new content is loaded text replacement doesn't happen.

I need it to run text replacement on any content that is added to the page later.

I have tried to use an onscroll event listener, but that is awkward and costly. I'm sure there is a better way.

I have looked into using the manifest run_at but haven't been able to find a way to use that.

let elements = document.getElementsByTagName('*');
let replacements = {
    "first to replace": "new text",
    "second to replace": "also new text"
};
let keys = Object.keys(replacements);

 RegExp.quote = (str) => {
     return str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
 };

let makeItAwesomer = () => {
    for (var i = 0; i < elements.length; i++) {
        var element = elements[i];

        for (var j = 0; j < element.childNodes.length; j++) {
            let node = element.childNodes[j];

            if (node.nodeType === 3) {
                let text = node.nodeValue;
                let newText = text;

                if(keys.some(function(key){ 
                    return ~text.toLowerCase().indexOf(key.toLowerCase());
                })){

                    keys.forEach( key => {
                        let regex = new RegExp(RegExp.quote(key), "gi");
                        newText = newText.replace(regex, replacements[key]);
                    });

                    if (newText != text) {
                        element.replaceChild(document.createTextNode(newText), node);
                    }
                }
            }
        }
    }
}

makeItAwesomer();
like image 359
Matt Flamm Avatar asked Aug 01 '19 16:08

Matt Flamm


People also ask

How do I use an extension code in Chrome?

To load your extension in Chrome, open up chrome://extensions/ in your browser and click “Developer mode” in the top right. Now click “Load unpacked extension…” and select the extension's directory. You should now see your extension in the list.

What is an unpacked Chrome extension?

Chrome extensions can be either packed or unpacked. Packed extensions are a single file with a . crx extension. Unpacked extensions are a directory containing the extension, including a manifest. json file.

Can you have multiple extensions on Chrome?

To answer your first question: nope, Google doesn't allow you to package multiple extensions together. Every extension has got its own Chrome Web Store page and ID.


Video Answer


1 Answers

You can use the built-in MutationObserver to detect when the DOM has changed, and can even customize it to only detect changes to the DOM structure (such as new nodes getting added on infinitely scrolling pages) and ignore other changes (such as attributes changing, which can happen at times by just hovering your mouse over something). You could have something like this:

const targetNode = document.body;

// Options for the observer (which mutations to observe)
// Set attributes to false if you do not care if existing nodes have changed,
//  otherwise set it true. 
const config = { attributes: false, childList: true, subtree: true };

// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
    makeItAwesomer();
};

// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(targetNode, config);

This may work with your code as it is written right now, as long as makeItAwesomer() correctly detects which text has already been modified (which it should if it works with the onScroll event).

However, to make it more efficient, if you re-write your makeItAwesomer() function to take parameters of the nodes you want changed, you could modify the callback to have it just update the newly loaded nodes. So callback would be more like:

const callback = function(mutationsList, observer) {
    for(let mutation of mutationsList) {
        makeItAwesomer(mutation);
    }
};

Here's the MDN Web docs on MutationObserver to help better understand how it works.

like image 199
johnfernow Avatar answered Oct 19 '22 10:10

johnfernow