69

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.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
user3699068
  • 745
  • 2
  • 7
  • 7
  • you can use document.createEvent("MouseEvents") to simulate a click. – dandavis Jun 03 '14 at 22:07
  • I thought this was only for things such as scroll wheel – user3699068 Jun 03 '14 at 22:13
  • 4
    https://developer.mozilla.org/en-US/docs/Web/API/document.createEvent#Triggering_built-in_events – dandavis Jun 03 '14 at 22:14
  • I dont understand how its simulating a whole mouse click without mousedown or mouseup =/ I dont know if what im trying to do is pointless or im just going about it the wrong way, basically I have a button that only works on mouseup. – user3699068 Jun 03 '14 at 22:24
  • well, type in the above code can be mouseup, mouseover, mousemove, or mouseout. the advantage there is that it (ideally) hits inline events (elm.onmouseup()), jQuery events ($(elm).trigger), and addEventListener-based events ( elm.dispatchEvent ) in one swoop. or, you can hit one the above event kinds manually without createEvent, whatever works... – dandavis Jun 03 '14 at 23:23
  • 3
    Woo!!! The mozilla dev site did it for me. The key for me was: `var simMousedownEvent = new MouseEvent('mousedown', { 'view': window, 'bubbles': true, 'cancelable': true }); $(“input.myelement”)[0].dispatchEvent(simMousedownEvent)` The [0] is needed to convert from jQuery object to native JS DOM object. – redfox05 Jul 02 '15 at 15:36

3 Answers3

135

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:


Beware:
The question code has an error. You need to pass a class name to that function. Like so:

document.getElementsByClassName ("SomeClassName")[0].click();
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • You 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 Jul 08 '14 at 04:02
  • As 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. – Pinke Helga Jul 08 '14 at 14:15
  • Your code works perfect even when another methods fails! But please, can you add some code to simulate **Shift** Click? – user90726 Feb 03 '16 at 05:22
  • @jsv, See [here](http://stackoverflow.com/questions/28895866/shift-mouse-click-trigger) and [here](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent), or open a new question if you need to. Any new question should have an MCVE or link to a target page since the approach can differ based on the page and your end goal. – Brock Adams Feb 03 '16 at 06:07
  • @BrockAdams, so I posted it [here](http://stackoverflow.com/questions/35173988). Hope it is not too wordy! – user90726 Feb 03 '16 at 10:11
  • Firing 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 https://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. – Ross Presser Sep 08 '18 at 03:49
  • @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. – Brock Adams Sep 08 '18 at 04:09
  • @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. – Ross Presser Sep 08 '18 at 04:37
  • Warning: Many methods used with `createEvent`, such as `initCustomEvent`, are `deprecated`. Use event constructors instead. https://developer.mozilla.org/en-US/docs/Web/API/Document/createEvent – Iglesias Leonardo Apr 20 '22 at 12:37
19

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']"));
SNag
  • 17,681
  • 10
  • 54
  • 69
7

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']);
Naveen raj
  • 891
  • 1
  • 10
  • 18