web-dev-qa-db-fra.com

PhantomJS; cliquez sur un élément

Comment cliquer sur un élément dans PhantomJS?

page.evaluate(function() {
    document.getElementById('idButtonSpan').click();  
});

Cela me donne une erreur "indéfini n'est pas une fonction ..."

Si je plutôt 

 return document.getElementById('idButtonSpan');

puis imprimez-le,

ensuite, il imprime [objet objet], de sorte que l'élément existe.

L'élément agit comme un bouton, mais il ne s'agit en réalité que d'un élément span et non d'une entrée de soumission.

J'ai pu obtenir ce clic de bouton pour travailler avec Casper, mais Casper avait d'autres limitations, je suis donc revenu à PhantomJS.

79
user984003

.click() n'est pas standard. Vous devez créer un événement et l'envoyer:

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);
}
65
user663031

Alternativement à la réponse de @ torazaburo, vous pouvez remplacer le HTMLElement.prototype.click lors de l'exécution dans PhantomJS. Par exemple, nous utilisons PhantomJS + QUnit pour exécuter nos tests et dans notre qunit-config.js nous avons quelque chose comme ceci:

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);
    };
  }
}
34
TheCloudlessSky

Ce n'est pas joli, mais je l'utilise pour me permettre d'utiliser jQuery pour la sélection:

var rect = page.evaluate(function() {
    return $('a.whatever')[0].getBoundingClientRect();
});
page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);

mais vous pouvez toujours remplacer $(s)[0] par document.querySelector(s) si vous n’utilisez pas jQuery.

(L’élément est dans l’esprit de la vue, c’est-à-dire que viewportSize.height est suffisamment grand).

15
stovroz

J'espère que la méthode suivante sera utile. Cela a fonctionné pour moi dans la 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;
});

Cela a fonctionné pour moi. J'espère que cela sera utile pour d'autres aussi

9
Jobins John

utilisez du code JavaScript simple avec evaluate, quelque chose comme ceci:

page.evaluate(function() {
    document.getElementById('yourId').click();
});
6
HappyCoder888

Avec 1.9.2 cela a fonctionné pour moi, les gestionnaires de clics ont été déclenchés: 

var a = page.evaluate(function() {
    return document.querySelector('a.open');
});

page.sendEvent('click', a.offsetLeft, a.offsetTop);
6
sshaw

Le moyen le plus simple consiste à utiliser jQuery.

page.evaluate(function() {
  page.includeJs("your_jquery_file.js", function() {
    page.evaluate(function() {
      $('button[data-control-name="see_more"]').click();
    });
  });
});
2
Forrest Chang

Les doubles clics sont également possibles avec PhantomJS.

Conseillé

Ceci est adapté de la réponse de stovroz et déclenche une dblclick native incluant les événements mousedown, mouseup et click (deux de chaque).

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);

D'autres moyens

Les deux méthodes suivantes ne déclenchent que l'événement dblclick, mais pas les autres événements qui doivent le précéder.

Adapté de cette réponse de 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);

Adapté de cette réponse de 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);

Script de test complet

2
Artjom B.

Je n'ai jamais pu cliquer directement sur l'élément. Au lieu de cela, j'ai regardé le code HTML pour trouver quelle fonction était appelée avec onclick, puis appelé cette fonction. 

2
user984003

Document.querySelector (element) .click () fonctionne avec 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);
},
2
GracefulCode

Pour ceux qui utilisent JQuery, l’interface utilisateur de JQuery a créé un utilitaire permettant de simuler: jquery-simulate . J'utilise ceci dans PhantomJS et Chrome

$ele..simulate( "click" );
0
wbdarby