Tips for efficiently updating numerous words in text on a webpage powered by AJAX, as well as in select attributes, by implementing a Tampermonkey script

My approach involves translating specific text, words, and terms within an HTML document using a tree walker to target only text nodes:

var replaceArry = [
    [/View your user account/gi,    'Tu cuenta'],
    // etc.
];
var numTerms    = replaceArry.length;
var txtWalker   = document.createTreeWalker (
    document.body,
    NodeFilter.SHOW_TEXT,
    {   acceptNode: function (node) {
            //-- Skip whitespace-only nodes
            if (node.nodeValue.trim() )
                return NodeFilter.FILTER_ACCEPT;

            return NodeFilter.FILTER_SKIP;
        }
    },
    false
);

var txtNode     = null;
while (txtNode  = txtWalker.nextNode () ) {
    var oldTxt  = txtNode.nodeValue;

    for (var J  = 0;  J < numTerms;  J++) {
        oldTxt  = oldTxt.replace (replaceArry[J][0], replaceArry[J][1]);
    }
    txtNode.nodeValue = oldTxt;
}


While this method is effective on static pages without affecting hyperlinks or event handlers, I am looking for ways to:

  • Handle dynamically loaded content through AJAX requests
  • Replace text in placeholder attributes as well

Is there a way to achieve this functionality without resorting to complex RegEx operations that may disrupt the existing structure?

Answer №1

If you need to manage AJAX content, you have a couple of options. You can either utilize MutationObservers or implement polling with a timer. While the former approach may be more complex and intricate, using a timer is simpler, reliable, and suitable for most practical scenarios.

To handle attributes such as placeholder, you can simply target them by using

document.querySelectorAll("[placeholder]")
to access the nodes and iterate through the resulting NodeList.

Additionally, consider translating title attributes as well.

In summary:

  • Encapsulate the replacement code within a function.
  • Invoke that function within a setInterval.
  • Include a separate loop within the interval for the attributes you wish to modify.

Combining all these elements, the cross-browser userscript will resemble the example below. Review the inline comments and
you can experiment with the script on this jsFiddle page.

// ==UserScript==
// @name     Replace lots of terms on an AJAX'd page
// @include  http://fiddle.jshell.net/Hp6K2/show/*
// @grant    none
// ==/UserScript==
var replaceArry = [
    [/text/gi,                      'blather'],
    [/View your user account/gi,    'Tu cuenta'],
    // etc.
];
var numTerms    = replaceArry.length;
                  //-- Executes every 5 times per second; Adequately fast.
var transTimer  = setInterval (translateTermsOnPage, 222); 

function translateTermsOnPage () {
    /*--- Substitutes text on the page without disrupting links or JavaScript 
        functions.
    */
    var txtWalker   = document.createTreeWalker (
        document.body,
        NodeFilter.SHOW_TEXT, {
            acceptNode: function (node) {
                //-- Skips nodes composed solely of whitespace
                if (node.nodeValue.trim() ) {
                    if (node.tmWasProcessed)
                        return NodeFilter.FILTER_SKIP;
                    else
                        return NodeFilter.FILTER_ACCEPT;
                }
                return NodeFilter.FILTER_SKIP;
            }
        },
        false
    );
    var txtNode     = null;
    while (txtNode  = txtWalker.nextNode () ) {
        txtNode.nodeValue       = replaceAllTerms (txtNode.nodeValue);
        txtNode.tmWasProcessed  = true;
    }
    //
    //--- Now replaces user-visible attributes.
    //
    var placeholderNodes    = document.querySelectorAll ("[placeholder]");
    replaceManyAttributeTexts (placeholderNodes, "placeholder");

    var titleNodes          = document.querySelectorAll ("[title]");
    replaceManyAttributeTexts (titleNodes, "title");
}

function replaceAllTerms (oldTxt) {
    for (var J  = 0;  J < numTerms;  J++) {
        oldTxt  = oldTxt.replace (replaceArry[J][0], replaceArry[J][1]);
    }
    return oldTxt;
}

function replaceManyAttributeTexts (nodeList, attributeName) {
    for (var J = nodeList.length - 1;  J >= 0;  --J) {
        var node    = nodeList[J];
        var oldText = node.getAttribute (attributeName);
        if (oldText) {
            oldText = replaceAllTerms (oldText);
            node.setAttribute (attributeName, oldText);
        }
        else
            throw "attributeName does not match nodeList in replaceManyAttributeTexts";
    }
}

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

The messageReactionAdd event has suddenly stopped functioning without any explanation

Currently, I am developing a Discord bot that assigns the role "Voteur" to a user when they react to an embed message created by the bot. Everything was functioning perfectly until recently, but for some reason, it has stopped working. The bot successfull ...

Arrange the row information in the MUI DataGrid in order to prepare it for exporting to CSV or Excel

Is there a way to organize row data for exporting to CSV or Excel with the MUI DataGrid? Take a look at my code snippet for the toolbar. slots={{ noRowsOverlay: NoDataComponent, noResultsOverlay: NoDataComponent, toolbar: ( ...

"Encountering difficulties while setting up an Angular project

I am currently working on setting up an Angular project from scratch. Here are the steps I have taken so far: First, I installed Node.js Then, I proceeded to install Angular CLI using the command: npm install -g @angular/cli@latest The versions of the ...

Output JSON data from PHP for use in Javascript

Is there a way to effectively convert JSON data from PHP/Laravel into JSON for JavaScript? I have the JSON string from PHP, but it is only rendering as a string. How can I convert it to a JSON object in JavaScript? Take a look at my code below. $('#e ...

How to effectively manage time and regularly execute queries every second using Node.js?

Currently working on developing a web software using node js with an Mssql database. There is a table in the database that includes a datetime value and a bit value. The bit value remains at 0 until the real-time matches the datetime value, at which point ...

I am encountering the error message "The requested resource does not contain the Access-Control-Allow-Origin header."

After going through all the possible answers and attempting to add header("Access-Control-Allow-Origin : *"); to the beginning of my asp page, I still couldn't resolve the issue. jQuery(document).ready(function(){ $.post('htt ...

The confirmation dialogue is malfunctioning

Need some assistance with my code. I have a table where data can be deleted, but there's an issue with the dialog box that pops up when trying to delete an item. Even if I press cancel, it still deletes the item. Here is the relevant code snippet: ec ...

Can a session be prolonged by an ajax request triggered by a timer?

In my Asp.Net MVC application, I am looking to dynamically hide the cart and certain buttons when a user's session expires. I stumbled upon a solution that involves calling a function on a timer in ASP.NET MVC. Here is the reference link: How to call ...

Using React Native to trigger a function based on a conditional statement

<Pressable onPress={()=> { if(newID) { EditPress(newID) } else { AddPress } }} style={styles.logBox} > <Text style={{ textAlign:"center", ...

What steps do I need to take to ensure that this Regex pattern only recognizes percentages?

I am attempting to create a specific scenario where I can restrict my string to three digits, followed by a dot and two optional digits after the dot. For example: 100.00 1 10.56 31.5 I've developed a regex pattern that allows me to filter out any ...

How to access a $scope variable in the same Angular controller function from outside the function

As a newcomer to AngularJS, I have a question about accessing my $scope variable from an outside function within the same controller. How can I achieve this? Below is the code snippet: .controller('RekapCtrl', ['$scope', '$timeout ...

Ember Gain a comprehensive understanding of the flow of execution between route and controller

Below is a snippet of my "box" route/controller: export default Ember.Controller.extend({ initialized: false, type: 'P', status: 'done', layouts: null, toggleFltr: null, gridVals: Ember.computed.alias('mode ...

Having trouble obtaining information from the state with Pinia Store

Currently, I am delving into the world of the composition API and Pinia with Vue3. I am facing an issue while calling an external API to fetch data and store it in the state of my store. The problem arises when I try to access this state from my page - it ...

Showing dynamic content retrieved from MongoDB in a list based on the user's selected option value

Implementing a feature to display MongoDB documents conditionally on a webpage is my current goal. The idea is for the user to choose an option from a select element, which will then filter the displayed documents based on that selection. For instance, if ...

Issues with Jquery/AJAX function not responding to onChange Event

I am currently working on a project where I need to populate a dropdown menu based on the value selected from another dropdown. However, I am encountering an issue with the function that I am trying to call in the onChange event of the select tag. This is ...

Collaborating with SockJS connectivity

Currently, my Node.js backend is interacting with desktop clients using websockets. The communication from the server side is initiated from a web front-end and everything is functioning properly because I am storing the SockJS Connection instances in an ...

Struggling with a character entity in Javascript? Learn how to escape it and avoid any display issues (such as showing

document.title = ("welcome &rarr; farewell"); Trying to display the arrow symbol "→" but it's not showing correctly. Any tips on how to properly escape it? ...

React slick does not display arrows when there are 4 or more photos

I am facing an issue where the next and previous arrows are not appearing when I have 4 or more photos on react-slick. However, they show up fine when there are 3 or fewer photos. You can view my code at this link: https://codesandbox.io/s/wyyrl6zz3l ...

Navigating Redirect Uri in Ionic for third-party API integration

After creating a webapp, I decided to venture into developing a mobile app using Ionic. The idea of making a progressive web app crossed my mind, but unfortunately Apple doesn't support it yet. (By the way, I'm still quite new to all of this) F ...

Wordpress Ajax deeplinking leads to a 404 error page

Hey there, This is my first time posting here, and I want to say thank you for all the help I've already received by reading through previous posts. I'm currently working on a WordPress project, but I seem to be struggling to get a clear overvi ...