casperjs: evaluating document.querySelector returns a null

12,096

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.

Share:
12,096
3cheesewheel
Author by

3cheesewheel

Updated on June 16, 2022

Comments

  • 3cheesewheel
    3cheesewheel almost 2 years

    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