2016-12-28 2 views
3

J'essaie d'exécuter des appels jQuery/Angular via WWW :: Mechanize :: Firefox eval_in_page. Je suppose qu'il y a une sorte de problème de portée, parce que je reçois des erreurs.Comment appeler les fonctions jQuery ou Angular via WWW :: Mechanize :: Firefox?

Si je tente d'exécuter ce code:

angular.element(document.getElementsByClassName("input")[0]).triggerHandler(('change'); 

Je reçois cette réponse:

MozRepl::RemoteObject: ReferenceError: angular is not defined at ...

Si je tente d'exécuter ce code:

$(".input").val("Foo") 

Je reçois cette réponse :

MozRepl::RemoteObject: ReferenceError: $ is not defined ...

Il semble que je n'ai accès à aucun des frameworks. La page semble avoir les deux chargés, cependant. Si j'exécute le code dans la console du navigateur, cela fonctionne très bien.

+2

Je ne sais pas assez sur les internes de Firefox pour être sûr, mais je pense que votre problème est lié à [cette] (https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts) (et [ceci] (https://bugs.jquery.com/ticket/4151)). 'eval_in_page' s'exécute dans un sandbox qui n'a accès qu'à certaines parties du DOM (le code correspondant est [ici] (https://metacpan.org/source/CORION/WWW-Mechanize-Firefox-0.79/lib/WWW/ Mechanize/Firefox.pm # L532)). Vous pouvez peut-être charger jQuery dans le bac à sable, mais je ne suis pas sûr de savoir pourquoi ... que voulez-vous faire avec jQuery et/ou Angular? – ThisSuitIsBlackNot

+0

J'essaye d'écrire du code pour m'interfacer avec une page web qui dépend fortement d'Angular pour le conduire. Spécifiquement, j'essaye de remplir un champ d'entrée qui n'a aucun élément d'identification ou de nom dessus. Lorsque ce champ détecte un événement de changement, il semble déclencher une fonction définie angulaire qui effectue un certain ménage. Quand il détecte un événement de flou, il convertit l'entrée textuelle en une jolie "balise" à l'intérieur d'une plage. En raison de ce ménage, je crois que je dois remplir la valeur et ensuite déclencher cette fonction. –

Répondre

1

Vous pouvez cliquer à l'intérieur du champ avec $mech->click(), il accepte les coordonnées x, y, insérez le texte et retirez le focus à nouveau. J'ai utilisé PhantomJS pour un travail similaire avant. Il devrait aussi fonctionner pour WWW::Mechanize::Firefox.

use WWW::Mechanize::PhantomJS; 
use strict; 
use warnings; 

my $mech = WWW::Mechanize::PhantomJS->new(log => 1); 
$mech->get('http://example.com'); 

if($mech->success) { 
    # accepts x, y coordinates 
    $mech->click(.. field[2]); 

    # set a text for example in input-field number 2 
    $mech->eval('document.getElementsByTagName("input")[2].value = "Your value";'); 

    # Click somewhere else to trigger blur event 
    $mech->click(.. outside the field[2]); 

    # Read the converted textual input from span 
} 
+0

C'est une bonne approche, mais il serait utile d'inclure comment trouver les coordonnées. – simbabque

+0

Cela m'a aidé à aller de l'avant. Le problème est que je dois encore déclencher un événement de changement pour que la maison derrière les coulisses continue de fonctionner. Jusqu'à présent, j'ai été incapable de faire cela sur un élément angulaire. Je suis toujours en train de chercher comment gérer correctement cela. Je rapporterai si je le trouve avant que quelqu'un d'autre publie une solution. Merci! –

+0

En aparté, j'étais capable d'utiliser getBoundingClientRect() pour trouver les éléments qui délimitent les coordonnées. –

0

Merci pour les idées tous. Je n'ai pas été capable de résoudre la question initiale, mais j'ai été capable de trouver cette solution alternative. En utilisant ce javascript, j'ai pu remplir le champ et déclencher le changement approprié et brouiller les événements. Cela a permis à angulaire de faire le traitement nécessaire.

$js = qq(
    var myElement = document.getElementsByClassName("input")[0]; 
    myElement.value = "$value"; 

    function fireEvent(element, event) { 
    var evt = document.createEvent("HTMLEvents"); 
    evt.initEvent(event, true, true); // event type,bubbling,cancelable 
    return !element.dispatchEvent(evt); 
    } 

    fireEvent(myElement, 'change'); 
    fireEvent(myElement, 'blur'); 
); 
$mech->eval_in_page($js); 

Notez la fonction I utilisé était une solution dégrossi trouvé here. Je l'ai réduit au code de Firefox. Si vous utilisez un navigateur différent, vous voudrez utiliser leur code plus robuste. Si quelqu'un trouve une solution à la question initiale, je serais heureux de l'accepter.