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:
- The "#mainButton" represents the original page's button.
- The "Hijack" button acts as your Tampermonkey script runner.
- A fake button div (overlay) is created over the main button to capture clicks instead of the actual button.
- 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:
- Avoid directly calling the page's code; triggering events is generally simpler, more reliable, and secure.
- 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.