Simulating a mousedown, click, mouseup sequence in Tampermonkey?
66,779
Solution 1
Send mouse events. Like so:
//--- Get the first link that has "stackoverflow" in its URL.
var targetNode = document.querySelector ("a[href*='stackoverflow']");
if (targetNode) {
//--- Simulate a natural mouse-click sequence.
triggerMouseEvent (targetNode, "mouseover");
triggerMouseEvent (targetNode, "mousedown");
triggerMouseEvent (targetNode, "mouseup");
triggerMouseEvent (targetNode, "click");
}
else
console.log ("*** Target node not found!");
function triggerMouseEvent (node, eventType) {
var clickEvent = document.createEvent ('MouseEvents');
clickEvent.initEvent (eventType, true, true);
node.dispatchEvent (clickEvent);
}
That works if the web page is statically loaded. If the web page is AJAX-driven, use a technique as in:
- "Normal" button-clicking approaches are not working in Greasemonkey script?
- Choosing and activating the right controls on an AJAX-driven site
Beware:
The question code has an error. You need to pass a class name to that function. Like so:
document.getElementsByClassName ("SomeClassName")[0].click();
Solution 2
I improved Brock's code a little after it worked as expected for me.
Definition:
function simulateMouseClick(targetNode) {
function triggerMouseEvent(targetNode, eventType) {
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent(eventType, true, true);
targetNode.dispatchEvent(clickEvent);
}
["mouseover", "mousedown", "mouseup", "click"].forEach(function(eventType) {
triggerMouseEvent(targetNode, eventType);
});
}
Calling examples:
simulateMouseClick(document);
simulateMouseClick(document.querySelector("a[href*='stackoverflow']"));
Solution 3
Bit Optimized
function fireMouseEvents( query, eventNames ){
var element = document.querySelector(query);
if(element && eventNames && eventNames.length){
for(var index in eventNames){
var eventName = eventNames[index];
if(element.fireEvent ){
element.fireEvent( 'on' + eventName );
} else {
var eventObject = document.createEvent( 'MouseEvents' );
eventObject.initEvent( eventName, true, false );
element.dispatchEvent(eventObject);
}
}
}
}
You would fire like this
fireMouseEvents("a[href*='stackoverflow']",['mouseover','mousedown','mouseup','click']);
Author by
user3699068
Updated on September 28, 2020Comments
-
user3699068 over 3 years
I would like to simulate a whole click not just
document.getElementsByClassName()[0].click();
How do I do that? Search results all seem to be about handling such events, not triggering them.
-
Pinke Helga almost 10 yearsYou were not right in the sequence of native event firing. Click event is fired after mouseup. In case of double click the sequence is: mousedown, mouseup, click, mousedown, mouseup, click, dblclick. Be aware when relying on click event there is no builtin mechanism to distinguish between single and double clicks. I've suggested an edit of your answer. I hope you feel comfort with that.
-
Pinke Helga almost 10 yearsAs far as I know this behavior isn't very new. Up/down are basic events fired immediately and click or drag are composed when other conditions are matching. mouseup within the same Element the latest mousedown event has been targeted to is considered as click, likewise mousemove over a distance treshold while button is held as drag (when draggeble), similary select. Since mouseup is a hard fact while click is open to interpretation subsequently, this order should also be the expectable one.
-
user90726 over 8 yearsYour code works perfect even when another methods fails! But please, can you add some code to simulate Shift Click?
-
Brock Adams over 8 years
-
user90726 over 8 years@BrockAdams, so I posted it here. Hope it is not too wordy!
-
Ross Presser over 5 yearsFiring mouse events doesn't seem to make the browser actually do things. It connects up to javascript listeners on those events, but things handled in the browser don't happen. Specifically, see stackoverflow.com/q/52208673/864696 . Mouseup event lost because of cross domain iframe; dispatching a new mouse event, even inside the iframe, doesn't make the mouse stop moving the insertion point in the textbox.
-
Brock Adams over 5 years@RossPresser, javascript can't fire "trusted" events nor events on browser "Chrome" elements. TM and GM could provide some of that capability but currently do not. Your question looks to be about a strange edge case and possible bug.
-
Ross Presser over 5 years@BrockAdams - thanks for looking. It certainly is strange, and it happens only in Chromium based browsers. The linked Chromium bug had an answer that seemed to indicate they chose this behavior in order to support an edge case in Google Maps... anyway, very off topic for this question, so I'll stop here.
-
Iglesias Leonardo about 2 yearsWarning: Many methods used with
createEvent
, such asinitCustomEvent
, aredeprecated
. Use event constructors instead. developer.mozilla.org/en-US/docs/Web/API/Document/createEvent