Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

casperjs: evaluating document.querySelector returns a null

I'm using the waitForSelector() and captureSelector() methods in CasperJS to wait for and select an element using a CSS selector, then save a screenshot of it.

However, I'm finding that because the css background has been set to transparent, the screenshot turns out pretty ugly, so I'd like to set the background to white. I've made sure that I'm using document.querySelector in an evaluate() call, but that doesn't seem to work.

Here's my script (you can ignore everything before casper.start(..., I just included the beginning part for context for the next code snippet):

var casper = require("casper").create({
  verbose: true,
  clientScripts: ["libs/jquery-1.10.2.js"]
});
var utils = require("utils");

var requiredOptions = [ 'url', 'selector', 'filename' ];
var missingOptions = new Array();

for (var i = 0 ; i < requiredOptions.length ; i++) {
  var opt =  requiredOptions[i];
  if (!casper.cli.has(opt)) {
    missingOptions.push(opt);
  }
}

if (missingOptions.length > 0) {
  casper.die("\nMissing the following CLI options: " + missingOptions.join(", ") + "\n\nExiting.\n");
}

var url = casper.cli.get('url');
var selector = casper.cli.get('selector');
var filename = casper.cli.get('filename');

casper.start(url, function() {
  this.waitForSelector(selector, function then() {
    var element = this.evaluate(function() {
      return document.querySelector(selector);
    });
    console.log(element); // returns null
    element.style.backgroundColor = "white"; // throws TypeError: 'null' is not an object (evaluating 'element.style') 
    this.captureSelector("captures/" + filename, selector);
  }, function onTimeout() {
    this.die("URL timed out.");
  });
});

casper.run();

And this is the output I get when I pass in a url, selector, and filename to write the screenshot to:

yiqing:~/Repos/rectslice()$ casperjs slice.js --filename='screenshot.png' --url='https://github.com/n1k0/casperjs/issues/192' --selector='.discussion-bubble-inner'
null
TypeError: 'null' is not an object (evaluating 'element.style')                 
  /Users/yiqing/Repos/rectslice/slice.js:31 in then
  /Users/yiqing/Repos/rectslice:1329 in runStep
  /Users/yiqing/Repos/rectslice:332 in checkStep

Note: Yes, I am well aware that this screenshot turns out fine (in that the background is white)... I just decided to use any old url, since I'm only trying to illustrate that the document.query() call doesn't work as expected.

Also, not sure if the versions are relevant, but here they are anyway:

yiqing:~/Repos/rectslice()$ casperjs --version
1.0.2
yiqing:~/Repos/rectslice()$ phantomjs --version
1.9.0
like image 918
3cheesewheel Avatar asked Jul 30 '13 18:07

3cheesewheel


1 Answers

You are running into issues because you can't pass back DOM elements from evaluate(). You can work directly with the element inside of the evaluate block however.

casper.start(url, function() {
  this.waitForSelector(selector, function then() {
    this.evaluate(function(sel) {
      document.querySelector(sel).style.backgroundColor = "white";
    }, selector);
    this.captureSelector("captures/" + filename, selector);
  }, function onTimeout() {
    this.die("URL timed out.");
  });
});

casper.run();

I've tested this on CasperJS 1.1-beta1, but it should work with versions >= 1.0.0

Edit: Can pass back objects, but not DOM elements.

like image 64
hexid Avatar answered Sep 30 '22 04:09

hexid