I have made a FIDDLE to simulate your "non-clickable" button. The blue div there has the same eventListeners attached as you have shown in your question. Playing around ended up with following results:
1) Let's get the DOM-element first:
var button = document.getElementsByClassName('.c-T-S.a-b.a-b-B.a-b-Ma.oU.v2')[0];
2) The page doesn't include jQuery. So all eventListeners there are attached by native .addEventListener()
. If you use jQuery to trigger events, it triggers only the events that are attached by jQuery, but not the native attached events. That means:
$(button).trigger('mousedown'); // this doesn't work
button.dispatchEvent(new Event('mousedown')); // this should work
3) As Scimonster pointed out, there is no click-eventListener attached. That means:
$(button).trigger('click'); // doesn't work anyway, see 2)
// next works, but has no visible result on the page,
// because there is no click-handler to do anything:
button.dispatchEvent(new Event('click'));
4) The click-event fires when the mousebutton goes up. When the mouseup
-event is used instead it looks like a click. In the fiddle the mouseup makes the red div visible. You may try to trigger the mouseup-event by adding this line to the code:
button.dispatchEvent(new Event('mouseup')); // "works", but has no visible result
The mouseup-handler is "hidden" by the mouseover
- and mouseout
-events, the first attaches it and the latter removes it. That way mouseup has only a result when mouse is over the button. I assume your google-page does something similar to cover the click-event.
5) What you should try:
First trigger some single events in native way:
button.dispatchEvent(new Event('eventName'));
If that gives no usable results use some reasonable combinations of events:
button.dispatchEvent(new Event('mouseover'));
button.dispatchEvent(new Event('mousedown'));
// or:
button.dispatchEvent(new Event('mousedown'));
button.dispatchEvent(new Event('mouseup')); // or: .....
There are many ways to combine events so that a single event doesn't do anything, but only the right combination works.
EDIT According to your invitation to investigate the source I found two ways:
1) The button itself has no eventListeners attached. The button is wrapped in an <a>
-tag. This tag is parent of the button and its attribute jsaction
's value tells that <a>
has listeners for click
, focus
, and mousedown
. Targeting it directly works:
button.parentElement.dispatchEvent(new Event('click'));
2) If you want to click the button itself you must trigger an event that bubbles up the DOM to reach an element that has a click-handler. But when creating an event with new Event('name')
, its bubbles
-property defaults to false
. It was my bad not thinking of that.. So the following works directly on the button:
button.dispatchEvent(new Event('click', {bubbles: true}));
EDIT 2 Digging deeper in whats going on on that page yielded an usable result:
It has been found that the page takes care of the mouse-pointer position and right order of the events, probable to distinguish wether a human or a robot/script triggers the events. Therefore this solution uses the MouseEvent
- object containing the clientX
and clientY
properties, which holds the coordinates of the pointer when the event is fired.
A natural "click" on an element always triggers four events in given order: mouseover
, mousedown
, mouseup
, and click
. To simulate a natural behaviour mousedown
and mouseup
are delayed. To make it handy all steps are wrapped in a function
which simulates 1) enter element at it's topLeft corner, 2) click a bit later at elements center. For details see comments.
function simulateClick(elem) {
var rect = elem.getBoundingClientRect(), // holds all position- and size-properties of element
topEnter = rect.top,
leftEnter = rect.left, // coordinates of elements topLeft corner
topMid = topEnter + rect.height / 2,
leftMid = topEnter + rect.width / 2, // coordinates of elements center
ddelay = (rect.height + rect.width) * 2, // delay depends on elements size
ducInit = {bubbles: true, clientX: leftMid, clientY: topMid}, // create init object
// set up the four events, the first with enter-coordinates,
mover = new MouseEvent('mouseover', {bubbles: true, clientX: leftEnter, clientY: topEnter}),
// the other with center-coordinates
mdown = new MouseEvent('mousedown', ducInit),
mup = new MouseEvent('mouseup', ducInit),
mclick = new MouseEvent('click', ducInit);
// trigger mouseover = enter element at toLeft corner
elem.dispatchEvent(mover);
// trigger mousedown with delay to simulate move-time to center
window.setTimeout(function() {elem.dispatchEvent(mdown)}, ddelay);
// trigger mouseup and click with a bit longer delay
// to simulate time between pressing/releasing the button
window.setTimeout(function() {
elem.dispatchEvent(mup); elem.dispatchEvent(mclick);
}, ddelay * 1.2);
}
// now it does the trick:
simulateClick(document.querySelector(".c-T-S.a-b.a-b-B.a-b-Ma.oU.v2"));
The function does not simulate the real mouse movement being unnecessary for the given task.