PhantomJS; click an element
JavascriptClickPhantomjsJavascript Problem Overview
How do I click an element in PhantomJS?
page.evaluate(function() {
document.getElementById('idButtonSpan').click();
});
This gives me an error "undefined is not a function..."
If I instead
return document.getElementById('idButtonSpan');
and then print it,
then it prints [object object], so the element does exist.
The element acts as a button, but it's actually just a span element, not a submit input.
I was able to get this button click to work with Casper, but Casper had other limitations so I'm back to PhantomJS.
Javascript Solutions
Solution 1 - Javascript
.click()
is not standard. You need to create an event and dispatch it:
function click(el){
var ev = document.createEvent("MouseEvent");
ev.initMouseEvent(
"click",
true /* bubble */, true /* cancelable */,
window, null,
0, 0, 0, 0, /* coordinates */
false, false, false, false, /* modifier keys */
0 /*left*/, null
);
el.dispatchEvent(ev);
}
Solution 2 - Javascript
Alternatively to @torazaburo's response, you could stub HTMLElement.prototype.click
when running in PhantomJS. For example, we use PhantomJS + QUnit to run our tests and in our qunit-config.js
we have something like this:
if (window._phantom) {
// Patch since PhantomJS does not implement click() on HTMLElement. In some
// cases we need to execute the native click on an element. However, jQuery's
// $.fn.click() does not dispatch to the native function on <a> elements, so we
// can't use it in our implementations: $el[0].click() to correctly dispatch.
if (!HTMLElement.prototype.click) {
HTMLElement.prototype.click = function() {
var ev = document.createEvent('MouseEvent');
ev.initMouseEvent(
'click',
/*bubble*/true, /*cancelable*/true,
window, null,
0, 0, 0, 0, /*coordinates*/
false, false, false, false, /*modifier keys*/
0/*button=left*/, null
);
this.dispatchEvent(ev);
};
}
}
Solution 3 - Javascript
It's not pretty, but I've been using this to allow me to use jQuery for the selection:
var rect = page.evaluate(function() {
return $('a.whatever')[0].getBoundingClientRect();
});
page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);
but you can always replace $(s)[0]
with document.querySelector(s)
if not using jQuery.
(It does rely on the element being in view mind, i.e. your viewportSize.height is big enough).
Solution 4 - Javascript
Hope the following method will be useful. It worked for me in version 1.9
page.evaluate(function(){
var a = document.getElementById("spr-sign-in-btn-standard");
var e = document.createEvent('MouseEvents');
e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
a.dispatchEvent(e);
waitforload = true;
});
This worked for me. Hope this will be useful for others also
Solution 5 - Javascript
With 1.9.2
this worked for me, click handlers were triggered:
var a = page.evaluate(function() {
return document.querySelector('a.open');
});
page.sendEvent('click', a.offsetLeft, a.offsetTop);
Solution 6 - Javascript
use simple JavaScript with evaluate
, something like this:
page.evaluate(function() {
document.getElementById('yourId').click();
});
Solution 7 - Javascript
I never was able to directly click the element. Instead, I looked at the html to find what function was called with onclick, and then called that function.
Solution 8 - Javascript
Document.querySelector(element).click() works when using Phantomjs 2.0
click: function (selector, options, callback) {
var self = this;
var deferred = Q.defer();
options = options || {timeout:1000};
setTimeout(function () {
self.page.evaluate(function(targetSelector) {
$(document).ready(function() {
document.querySelector(targetSelector).click();
}) ;
}, function () {
deferred.resolve();
}, selector);
}, options.timeout);
return deferred.promise.nodeify(callback);
},
Solution 9 - Javascript
Double clicks are also possible with PhantomJS.
Recommended
This is adapted from the answer of stovroz and triggers a native dblclick
including the mousedown
, mouseup
and click
events (two of each).
var rect = page.evaluate(function(selector){
return document.querySelector(selector).getBoundingClientRect();
}, selector);
page.sendEvent('doubleclick', rect.left + rect.width / 2, rect.top + rect.height / 2);
Other ways
The following two ways only trigger the dblclick
event, but not the other events that should precede it.
Adapted from this answer of torazaburo:
page.evaluate(function(selector){
var el = document.querySelector(sel);
var ev = document.createEvent("MouseEvent");
ev.initMouseEvent(
'dblclick',
true /* bubble */, true /* cancelable */,
window, null,
0, 0, 0, 0, /* coordinates */
false, false, false, false, /* modifier keys */
0 /*left*/, null
);
el.dispatchEvent(ev);
}, selector);
Adapted from this answer of Jobins John:
page.evaluate(function(selector){
var el = document.querySelector(sel);
var e = document.createEvent('MouseEvents');
e.initMouseEvent('dblclick', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
el.dispatchEvent(e);
}, selector);
Solution 10 - Javascript
The easiest way is using jQuery.
page.evaluate(function() {
page.includeJs("your_jquery_file.js", function() {
page.evaluate(function() {
$('button[data-control-name="see_more"]').click();
});
});
});
Solution 11 - Javascript
For those using JQuery, the JQuery UI created a utility to simulate these: jquery-simulate. I use this in PhantomJS and Chrome
$ele..simulate( "click" );