Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PhantomJs clicking links or running on-page functions

I'm just getting used to PhantomJs and so far its really cool.

I'm trying to crawl a site and get data about the products on the site. Each product page loads with the default color of the product visible. When you click on a color swatch it swaps the new color out by running a function. Each clickable color swatch element looks like this:

<input type="image" id="swatch_0" onclick="pPage.getColor(0);" src="http://www.site.com/img50067.jpg">

getColor updates the thumbnail and price for that color. The id increments for each available color (swatch_0, swatch_1, etc) and the argument passed to getColor increments as well. I want to iterate through each color with PhantomJs and pull the relevant data for each.

I've loaded the page, loaded jQuery, and can pull the data for the initally loaded color, but nothing seems to allow me to execute click events.

here is what I'm trying:

page.evalaute(function){
  var selection = $('#confirmText').text(); // name of the color
  var price = $('#priceText').text();       // price for that color

  console.log('Price is: ' + price);
  console.log('Selection is: ' + selection);
  console.log($('#swatch_1'));

  $('#swatch_1').trigger("click");

  selection = $('#selectionConfirmText').text();
  price = $('#priceText').text();
  console.log('Price is: ' + price);
  console.log('Selection is: ' + selection);

}

This gives me:

console> Price is: $19.95
console> Selection is: blue
console> [Object Object]
console> TypeError: 'undefined' is not and object  // repeating until I manually exit

no other code runs. I've also tried firing the event without jQuery like this:

var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
var cb = document.getElementById("swatch_1"); 
cb.dispatchEvent(evt);

And running the function directly:

pPage.getColor(1);

And I get the same output. Any help is appreciated.

like image 745
Jeff Ryan Avatar asked Mar 16 '12 02:03

Jeff Ryan


2 Answers

If the onclick handler is specified directly in the HTML as you have it here, you can call it directly with Javascript:

$(function() {
    $('#swatch_0')[0].onclick(); 
});

​ I believe you can also use the PhantomJS page method sendEvent() to issue a native click event. But it looks like this is a bit complicated, as you have to call this from the PhantomJS context with the x,y position of the mouse. Untested code:

var elementOffset = page.evaluate(function() {
   return $('#swatch_1').offset(); 
});
page.sendEvent('click', elementOffset.left + 1, elementOffset.top + 1);
like image 82
nrabinowitz Avatar answered Oct 01 '22 18:10

nrabinowitz


not much activity here for a few months, but i've been working with this stuff lately and maybe this is an answer to your question

if jquery is already loaded as part of the page you're running, then injecting jquery won't work, you will get the behavior you describe (i encountered this too).

So when you inject the jquery code you should first make sure it's not already part of the context

like image 20
Alan Kaiser Avatar answered Oct 01 '22 20:10

Alan Kaiser