Can other JavaScript event listeners be synchronized with an asynchronous event?

My goal is to manipulate a web page using Tampermonkey where there is a button with certain event listeners followed by a redirect.

Is it possible for me to insert my own click event handler into the button, which triggers an AJAX request and waits for it to finish before proceeding with the other event listeners? I want to ensure that my AJAX request is fully executed before the redirection takes place.

I am aware of stopImmediatePropagation, but I'm uncertain how to asynchronously "delay" propagation.

Answer №1

You cannot force other event handlers to wait, but there are ways to override or intercept existing functions. However, this can be tricky with Tampermonkey and may cause complications, especially in browsers like Firefox + Greasemonkey.

One workaround for clickable elements is to place an overlay on the button, set up listeners on the overlay, and then trigger the desired events on the original button when needed.

For instance, imagine a scenario where:

  1. The "#mainButton" represents the original page's button.
  2. The "Hijack" button acts as your Tampermonkey script runner.
  3. A fake button div (overlay) is created over the main button to capture clicks instead of the actual button.
  4. An intercept code performs asynchronous tasks before simulating a click on the main button.

//--------------------------
//--- Page's Initial Code:
//--------------------------
$("#mainButton").click(function() {
    logline("The button was clicked.");
});

//------------------------------
//--- Set Up Tampermonkey Script:
//------------------------------
$("#tmIntercept").click(function() {
    logline("==> Main button is now intercepted.");
    $(this).attr({ "disabled": true });

    var targetButton = $("#mainButton");
    var overlayDiv = $('<div id="tmBtnOverlay">').css({
        'width': targetButton.outerWidth(),
        'height': targetButton.outerHeight(),
        'position': 'absolute',
        'top': targetButton.offset().top,
        'left': targetButton.offset().left,
        'z-index': 8888,
        'background': "lime",
        'opacity': "0.2"
    }).appendTo("body");

    overlayDiv.click(function(zEvent) {
        zEvent.stopImmediatePropagation();

        logline("Doing some AJAXy thing... <span> </span>");

        setTimeout(doSomeAjaxyThing, 1111);
    });
});

function doSomeAjaxyThing() {
    $("#eventLog > p > span").first().text('Done.');

    var clickEvent = document.createEvent('MouseEvents');
    clickEvent.initEvent("click", true, true);
    $("#mainButton")[0].dispatchEvent(clickEvent);
}

function logline(str) {
    this.lineNumber = this.lineNumber + 1 || 1;
    var lineDisplay = (1e15 + this.lineNumber + "").slice(-3);

    $("#eventLog").prepend('<p>' + lineDisplay + ' ' + str + '</p>');
}
#mainButton {
    font-size: 2em;
    padding: 0.3ex 2ex;
}
#eventLog {
    max-height: 50vh;
    overflow-y: auto;
    overflow-x: hidden;
}
#eventLog > p {
    margin: 0.3ex 2ex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

<p><button id="mainButton">The Button</button></p>

<p><button id="tmIntercept" autocomplete="off">Hijack the button</button></p>

<fieldset>
    <legend>Event Log:</legend>
    <div id="eventLog"></div>
</fieldset>


Additional Notes:

  1. Avoid directly calling the page's code; triggering events is generally simpler, more reliable, and secure.
  2. This demo showcases the overlay technique; real-world implementation may require adjustments such as relative positioning and offset tweaking, which are beyond the scope of this example.

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

Tips for sending a property to a function that is imported and produces a component in React

I need help figuring out how to pass an argument back to my component library that is imported in a parent app as a dependency. The specific issue arises when I am trying to implement a brand concept in the theme object. The goal is to switch the theme bas ...

Is there a way to switch on and off an ngrx action?

Here is a statement that triggers a load action to the store. The relevant effect will process the request and return the response items. However, my goal is to be able to control this action with a button. When I click on start, it should initiate dispa ...

Vuejs method to showcase input fields based on form names

I am working on a Vue.js form component with multiple input fields, but now I need to split it into two separate forms that will collect different user input. Form 1 includes: Name Surname Email with a form name attribute value of form_1 Form 2 i ...

Incrementing and decrementing a textbox value by one using onClick

I'm looking for help with a JavaScript solution without using jQuery or any plugins, specifically for Cordova/PhoneGap. I am new to JavaScript and learning as I go, so please bear with me. My goal is to create a functionality where there is a textbox ...

Next.js fails to properly render external links when utilizing the Link component

It was quite surprising to discover that a basic Link component doesn't function as expected in Next.js when attempting to use it with an external URL and HTML Button tag within. Here is my attempt at solving this issue: Attempt 1: <Link href="h ...

Iterating over the IDs of div elements using jQuery loop

Currently, I am working with a bootstrap accordion and attempting to retrieve the ID and HREF values for each individual accordion using jQuery. Here is the code snippet that I have been utilizing: $('.room-loop').each(function(id){ $('. ...

Populating dropdown menu with data from redux state upon component mounting

I am new to working with react-redux and have successfully implemented dependent dropdown functionality in a react component (Country => State => City). My goal now is to dynamically update the dropdown values based on data received from the redux s ...

Result array, employed as an input for auto-suggest functionality

I’m currently working with an array where I am iterating over an object from an API endpoint that is in stdClass format: foreach($searchResults->hits as $arr){ foreach ($arr as $obj) { $fullType = $obj->_source->categories; print_r($fu ...

What steps can be taken to ensure that an ObjectID does not transition into a primitive form

Is there a way to avoid an ObjectID from being converted into a primitive data type when transferring in and out of Redis? Would converting it to a JSON string be a possible solution? Thanks! ...

JavaScript - Capture the Values of Input Fields Upon Enter Key Press

Here's the input I have: <input class="form-control" id="unique-ar-array" type="text" name="unique-ar-array" value="" placeholder="Enter a keyword and press return to add items to the array"> And this is my JavaScript code: var uniqueRowsArr ...

Enhancing Vuejs Security: Best Practices and Tips for Secure Development

Recently, I developed a Web Application utilizing Vue.js and fetching data from the backend using 'vue-resource' in combination with Express and Postgres. Now, my main objective is to enhance its security by integrating an API Key. I am somewha ...

What is the best way to animate the scaling of a CSS property using jQuery?

I need help creating an animation where a circle div with the class of "bubble" grows from nothing to its full size when a button is clicked using jQuery. I am currently facing difficulties in making it work properly. Here's my current code snippet: ...

Can the Browser width/document width be maintained when shrinking the browser window size?

https://i.stack.imgur.com/a4gfA.pngLooking for a solution to maintain the browser/document width at 350px, preventing users from minimizing the window. The desired width is actually 400px, not 350px. Please refer to the image above. I require the window ...

Passing array data from JavaScript to PHP using POST method in Joomla 3.x

Looking for a way to send an array from JavaScript to a Joomla 3.x PHP file? var data = ['foo', 'bar']; $.post('index.php?option=component&view=componentview&Itemid=123&tmpl=component&layout=xlsx', {'xls ...

Error: Running the command 'yarn eg:'live-server'' is not a valid internal or external command

Currently, I am utilizing yarn v1.6.0 to manage dependencies. I have globally installed live-server by running the following command: yarn global-add live-server However, upon executing it as live server, I encounter the following error: 'live-ser ...

Finding all elements with a specified attribute in jQuery: A comprehensive guide

While looking for an example, I came across one that searches only inputs instead of all elements: https://api.jquery.com/attribute-equals-selector/ Is there a way to modify this example so that it can search all elements in the DOM, and not just inputs ...

Custom Native Scrollbar

Currently, there are jQuery plugins available that can transform a system's default scroll bar to resemble the iOS scroll bar. Examples of such plugins include . However, the example code for these plugins typically requires a fixed height in order to ...

Tips for organizing your JSON Structure within ReactJs

In the given example, I have a JSON structure with information about different airlines. The Airline Name is dynamic and we need to separate the JSON into an expected array format. const arr = [ { Airline: "Goair", Departure: "01:50" ...

Looking to dynamically update a date variable based on user selection from a drop-down menu in PHP

I am currently working with a PHP file (index.php) which features a title bar displaying the date in the format (MM YYYY). The dates themselves are extracted from another PHP file named latest_update.php. Within the latest_update file, the dates are specif ...

Is there a way to preserve line breaks when programmatically copying text to the clipboard with JavaScript?

Utilizing Javascript alongside a duo of devexpress asp.net controls to dynamically duplicate the contents of an ASPxMemo (multiline textfield) and assign those contents as the body of an email. The copying and pasting is functioning correctly for the most ...