Utilize regular expressions in TamperMonkey to extract specific groups of text

I'm currently working on a TamperMonkey userscript that aims to identify URLs matching a specific pattern, visit these pages, extract relevant information, and then update the link for each URL with the extracted text. I'm facing some challenges with the regex matching/extraction process.

Although I've confirmed that my regex is functioning correctly, it seems to fail when I run the script, and I'm struggling to extract the desired group. Any assistance would be greatly appreciated.

// ==UserScript==
// @name         Pull through titles
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  ---
// @author       You
// @match        https://xxx/curriculum-overview/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const regexPattern = /portfolio-item__text-input-wide\" .*value=\"(.+)\"/;
    var evidence = "";
    var title = "";

    //Show descriptors by default
    var x = document.getElementsByClassName("js-descriptors");
    for (var i = 0, max = x.length; i < max; i++) {
        x[i].style.display = "block";
    }

    //Find all URLs that link to evidence
    var urls = document.querySelectorAll('a[href*="portfolio-item/review"]');

    //For each URL, visit the page and extract the title of the evidence and update the innerText with that title
    for (i = 0; i < urls.length; i++){

        const xhr = new XMLHttpRequest();
        xhr.open("GET", urls[i], true);
        xhr.responseType = "text";
        xhr.onload = () => {
            if (xhr.readyState === xhr.DONE) {
                if (xhr.status === 200) {
                    evidence = xhr.responseText;
                }
            }
        };

        xhr.send(null);
        title = evidence.match(regexPattern); //extract matching regex pattern
        alert(title.toString()); //once I know the string is extracted will append to
        //urls[i].innerText = urls[i].toString(); //this line tests that the innerText can be changed to the URL; will change to title variable once working
    }
})
();

Answer №1

Perform your regex operations within the xhr.onload function after fetching the data. Since the xhr.open call is asynchronous, trying to match the regex pattern using evidence.match(regexPattern); immediately will not work as evidence will be empty.

For example:

xhr.onload = () => {
  if (xhr.readyState === xhr.DONE) {
    if (xhr.status === 200) {
      evidence = xhr.responseText;
      title = evidence.match(regexPattern); //extract matching regex pattern
      alert(title.toString());
    }
  }
};

Alternatively, you can create a separate function and call it from within the onload method:

function getTitle(text) {
   var mytitle = text.match(regexPattern); 
   console.log(mytitle); // or any other action...
}

// then...

xhr.onload = () => {
  if (xhr.readyState === xhr.DONE) {
    if (xhr.status === 200) {
      getTitle(xhr.responseText);
    }
  }
};

Answer №2

During a collaborative debugging session, my friend and I discovered that the urls[i] variable was not accessible within the onload function. This seems to be what @Fraser was hinting at, explaining why we were having trouble updating the innerText. To address this issue, we devised a slightly different approach which I am sharing here in case it can benefit others.

(function() {
    'use strict';

    const regexPattern = /portfolio-item__text-input-wide\" .*value=\"(.+)\"/;
    var evidence = "";
    var title = "";

    //Display descriptors by default
    var x = document.getElementsByClassName("js-descriptors");
    for (var i = 0, max = x.length; i < max; i++) {
        x[i].style.display = "block";
    }

    //Identify all URLs linking to evidence
    var urls = document.querySelectorAll('a[href*="portfolio-item/review"]');

    //Visit each URL, extract the evidence title, and update the innerText with that title
    for (i = 0; i < urls.length; i++){
        const xhr = new XMLHttpRequest();
        xhr.open("GET", urls[i], true);
        xhr.tmlink = urls[i]; // Workaround: adding url as a property to xhr
        xhr.responseType = "text";
        xhr.onload = function() {
            if (xhr.readyState === xhr.DONE) {
                if (xhr.status === 200) {
                    evidence = xhr.responseText;
                    title = evidence.match(regexPattern); // Extract matching regex pattern
                    this.tmlink.innerText = title[1].toString(); // Update innerText for the hyperlink
                }
            }
        };

        xhr.send(null);
    }
})
();

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

What is the best way to implement this component into my vue.js project?

I am having trouble integrating this vue component into my app as it is not loading properly. You can find the source of the component here. The following warnings are showing up: Unresolved function or method isNumeric() at line 35 Unused parameter e at ...

Generate JSON with a distinct structure

My goal is to send a JSON via POST request to an API in the following format: "answer" => { "name"=>"Test", "email"=>"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3d49584e497d49584e49135e52">[email  ...

How to use Express Validator to validate both email and username within a single field?

I am currently developing an application using the Express (Node.js framework) and I want to allow users to log in with either their email address or username. My question is, how can I implement validation for both types of input on the same field using e ...

Is there a way to execute a function after EACH user interaction?

I am in the process of developing a React Native kiosk application for an Android tablet that will be mounted on a wall. The main requirement is to include a "screen saver" feature, where if the user does not interact with the screen for 30 seconds, it wil ...

The Node.js controller is in disarray

As a newcomer to javascript, node.js, and backend development in general, I am tackling the task of creating a controller for handling login page requests. My confusion lies in extracting data from a MYSQL table, user authentication, and working with the J ...

Revamp the current webpage to display attribute values in textual format

As I peruse a webpage, I notice that there is room for improvement in terms of user-friendliness. The page is filled with a list of movie titles, each accompanied by a link to IMDb. However, the IMDB user rating is only visible when hovering over the titl ...

What is causing the ERR_HTTP_HEADERS_SENT('set') error when running on Windows Server, but not on my development machine?

Currently, I am in the process of developing a Node/Express application that will integrate with ActiveDirectory. The login form is designed to post the username and password to a specific /auth route, where the AD authentication takes place, along with se ...

What is the best way to toggle the visibility of multiple column groups in Ag-Grid community using dynamic

I am seeking to replicate a basic version of the sidebar found in Ag-Grid Enterprise. The goal is to use JavaScript to gather all column groups within a grid and then provide a checkbox for each group to toggle visibility. While I am aware that individual ...

Encountering a GraphQL error during the compilation process

I've been following along with this informative tutorial: https://www.gatsbyjs.org/blog/2017-07-19-creating-a-blog-with-gatsby/ After completing all the steps, I encountered a GraphQL compile error: GraphQL Error There was an error while compiling y ...

Adjust the height of a DIV element using Jquery Resizable to a minimum height of 1px, smaller than its default value

Having an issue with the Jquery UI Resizable functionality. I've implemented Jquery resizable to adjust a div's width and height dynamically. It's been working well, but I'm encountering a problem when attempting to decrease the height ...

Is there a way to extract the values from a range slider individually and then display them as the minimum and maximum values on the screen?

Currently, I am facing an issue with a range slider where the value I am retrieving is concatenated. For example, when printed, it appears as 2080, with 20 and 80 being separate values visually combined on screen. My goal is to extract the minimum and maxi ...

Discovering the method to extract a Specific Form Field value with JQuery

Recently, I encountered a form that looked like this: <form id="post_comment" action="cmt.php" method="post"> <input type="hidden" name="type" value="sub" /> <textarea id="body"></textarea> </form> To interact with the ...

The server remains unreachable despite multiple attempts to send data using Angular's $http

I am encountering an issue with triggering $http.post: app.controller('editPageController', function($scope, $routeParams, $http) { $scope.page = $routeParams.pageid; // retrieve page data from the server $http.get('/pages/&ap ...

Ways to unveil a concealed div element using JavaScript

If javascript is disabled, I want to hide a div. If javascript is enabled, however, I don't want to rely on using the <noscript> tag due to issues in Chrome and Opera. Instead, my approach is as follows: <div id="box" style="display:none"> ...

Button click not triggering JQuery click event

$(document).ready(function () { $('#btnApplyFilter').click(function () { alert("JQuery is not running!"); }); }); Why is the above function not working when the button is clicked? Here is the code for my button : ...

Do factory and service represent examples of Declarative Programming within AngularJS?

Angular JS involves the declaration of services and factories. Services are created by declaring functions that we do not manually call ourselves. Could this be considered declarative programming, with the framework handling the imperative tasks? What ex ...

Is it possible to establish the page state upon loading (in the context of a GET request

At present, my navigation bar is set up to utilize AJAX for loading new pages and window.pushState() in order to update the URL when the AJAX call is successful. I've come to realize that it's crucial to push the page state during GET requests s ...

Resolve the conflict with the upstream dependency when installing NPM packages

I'm encountering an issue while attempting to npm install vue-mapbox mapbox-gl - I keep getting a dependency tree error. Just to provide some context, I am utilizing Nuxt.js SSR with Vuetify and have not installed anything related to Mapbox before ru ...

Executing API calls utilizing Axios in a NodeJS environment with the Authorization Basic feature

I have developed an API to retrieve a token from PayPal. curl -v POST https://api.sandbox.paypal.com/v1/oauth2/token \ -H "Accept: application/json" \ -H "Accept-Language: en_US" \ -u "CLIENT_ID:SECRET" &b ...

Acquiring a fresh scope in Angular via a different component

In my project, I am developing an app using a component-based approach with Angular 1.5.5. As part of this development, I am utilizing d3js to create some elements with the class .floating-node. For each of these nodes, I am creating a new $scope and appe ...