Tips for automating the execution of Chrome extension code on pages with infinite scrolling

Creating my debut Chrome extension, I'm developing a tool to substitute text on web pages.

The current code effectively operates on content loaded by DOMContentLoaded. However, when pages employ infinite scrolling and new content is added, the text replacement process fails.

I am seeking a solution that will automatically execute text replacement on any dynamically added content.

Prior attempts with an 'onscroll' event listener proved to be cumbersome and resource-intensive. Surely, there must be a more efficient approach.

Although I explored using the manifest's run_at property, I have not yet discovered a method to apply it in this context.

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();

Answer №1

If you want to monitor changes in the DOM, you can utilize the built-in MutationObserver. This handy tool allows you to spot when alterations occur in the structure of the DOM, like nodes being added on pages that scroll endlessly, while disregarding other changes such as attribute modifications triggered by simply hovering over elements. Here is an example implementation:

const targetNode = document.body;

// Configure which mutations to observe
const config = { attributes: false, childList: true, subtree: true };

// Callback function for observed mutations
const callback = function(mutationsList, observer) {
    makeChanges();
};

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

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

The above code should complement your existing code if makeChanges() accurately identifies previously modified text (similarly to how it operates with the onScroll event).

To enhance efficiency, consider revising your makeChanges() function to accept arguments specifying the nodes requiring updates. By doing so, you could adjust the callback to exclusively refresh the newly loaded nodes. The revised callback would look something like this:

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

For further insights into MutationObserver and its functionalities, refer to MDN Web docs on MutationObserver.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to set up a universal type definition in TypeScript version 2 and above?

I have a collection of straightforward .ts files, not part of any projects but standalone .ts scripts. They implement certain node.js features. Both TypeScript and node type definitions are set up through the following commands: npm install -g typescript ...

What sets apart the method of assigning event handlers using bind() versus each() in jQuery?

Could someone explain the difference between using bind() to assign event handlers and using each() for the same task? $(function () { $('someElement') .bind('mouseover', function (e) { $(this).css({ ...

Tips for handling an InvalidSelectorException in Selenium when logging into a website

I've been working on automating website logins using Selenium and here is the code I have written: from selenium import webdriver driver = webdriver.Chrome() driver.get("https://abcde.com") assert "xxx" in driver.title user = driver.find_element_by ...

Guide on populating a table with user input using jQuery and ajax

For the past few days, I've been attempting to populate a table using jQuery and ajax based on search results, but unfortunately, it's not working out for me. Below is the HTML code snippet: <form class="form"> <div class="form-gro ...

How can I completely alter the content of aaData in jquery.dataTables?

Looking to completely change the content of a datatable purely from a javascript perspective, without relying on Ajax calls. I've attempted using the following script: oTable.fnClearTable(); oTable.fnAddData(R); oTable.fnAdjustColumnSizin ...

The data in Next.js getStaticProps does not update or refresh as expected

As I recently transitioned to working with Next.js, I have encountered several challenges. One issue that arose was related to the use of useEffect in React compared to its behavior in Next.js. In my index file, I have implemented the following code: impo ...

Customizing Marker Clusters with ui-leaflet: A guide on changing marker cluster colors

I'm trying to customize the markerCluster color in a non-default way. I've been exploring the API and it looks like the recommendation is to modify a divIcon after creation, possibly like this: var markers = L.markerClusterGroup({ iconCreateFunc ...

The value entered for creating a payment method is invalid: the card must be in the form of an object

I am in the process of setting up a payment method using the Next.js library from Stripe. Here is the code snippet: import React, { FunctionComponent } from 'react'; import type { DisplaySettingsProps } from '@company/frontoffice/types' ...

Employing jQuery Mobile with MVC3 for seamless auto-submit functionality

When I remove jQuery Mobile, the code works perfectly! The form: @using (Html.BeginForm("SearchTown", "Home", FormMethod.Post, new { id = "TheForm1" })) { @Html.DropDownList("TownID", (SelectList)ViewBag.TownId, "Select a Town") } The Javascript: & ...

Update the state of the parent component based on changes made in the child component (both are functional

Here is the layout for the current issue: . ├── components │ ├── ModalPolicy.js │ ├── Footer │ ├── index.js ├── pages │ ├── index.js I attempted to display the Modal on Footer/index.js but it did no ...

ElementUI Cascader not rendering properly

Utilizing elementUI's cascading selector to present data, I have crafted this code in accordance with the official documentation. <el-cascader v-model="address" :options="addressOptions" :props="{expandTrigger: 'hover'}" ...

Implement a loading bar on the entire page in Vue.js while a request is being made

There is an "edit" button on my page which allows me to edit certain elements and either save or close without saving. I would like to implement a loading bar that displays when the user clicks the "save" button, indicating that the data is being processe ...

A step-by-step guide on increasing native Time variables in JavaScript

How can I dynamically and repetitively add time (both hours and minutes) in JavaScript to effectively increment a date object? There are times when I need to add minutes, or hours, or a combination of both - and I want the resulting total time to be return ...

What could be causing the error message "CSRF token missing or incorrect" to appear?

I am facing an issue with returning a value from a View function in Django. This particular function is called from a JavaScript code using Ajax, but I'm encountering an error that says 'Forbidden (CSRF token missing or incorrect)'. JavaScr ...

Best resolutions and formats for Nativescript-Vue application icons

I'm a newbie when it comes to Nativescript, and I'm looking to change the icon for my app. After doing some research, I found this command: tns resources generate splashes <path to image> [--background <color>] This command seems li ...

The process of utilizing the override feature in the package.json file to make updates to child dependencies

There seems to be a vulnerability in the async package that I want to update to version 3.2.2. Here is the dependency tree if I use npm list async: └─┬ [email protected] └─┬ [email protected] └── [email protected] After referring t ...

Incorporating DefinitelyTyped files into an Angular 2 project: A step-by-step guide

I am currently developing an application using angular 2 and node.js. My current task involves installing typings for the project. In the past, when starting the server and activating the TypeScript compiler, I would encounter a log with various errors rel ...

What is the best way to change an object into a string in node.js?

Recently, I've delved into the world of node js and I'm eager to create a basic coap client and server using this technology. Successfully, I managed to set up a server hosting a text file, but now I aim to access it from the client. var coap = ...

Building intricate hierarchical menus with Material-UI 4.9

I am currently incorporating the @material-ui/core library into my application and aiming to implement a nested menu feature. I have referred to the material.io specification which discusses nested menus, but unfortunately, the material-ui library does not ...

Changing the Color of Material-UI Slider: A Step-by-Step Guide

Looking to update the color of Material UI Slider component I have attempted to adjust the CSS styling without success, followed by trying the solution provided in this issue and applying the following code, but the changes are not being reflected: getMu ...