Extending
Sometimes it can be convenient to add your own methods to a Casper
object instance; you can easily do so as illustrated in the example below:
var casper = require('casper').create({ verbose: true, logLevel: "debug" }); var links = { 'http://edition.cnn.com/': 0, 'http://www.nytimes.com/': 0, 'http://www.bbc.co.uk/': 0, 'http://www.guardian.co.uk/': 0 }; casper.countLinks = function() { return this.evaluate(function() { return __utils__.findAll('a[href]').length; }); }; casper.renderJSON = function(what) { return this.echo(JSON.stringify(what, null, ' ')); }; casper.start(); casper.each(Object.keys(links), function(casper, link) { this.thenOpen(link, function() { links[link] = this.countLinks(); }); }); casper.run(function() { this.renderJSON(links).exit(); });
But that's just plain old monkey-patching the casper
object, and you may probably want a more OO approach… That's where the inherits()
function from the utils
module and ported from nodejs comes handy:
var Casper = require('casper').Casper; var utils = require('utils'); var links = { 'http://edition.cnn.com/': 0, 'http://www.nytimes.com/': 0, 'http://www.bbc.co.uk/': 0, 'http://www.guardian.co.uk/': 0 }; function Fantomas() { Fantomas.super_.apply(this, arguments); } // Let's make our Fantomas class extending the Casper one // please note that at this point, CHILD CLASS PROTOTYPE WILL BE OVERRIDEN utils.inherits(Fantomas, Casper); Fantomas.prototype.countLinks = function() { return this.evaluate(function() { return __utils__.findAll('a[href]').length; }); }; Fantomas.prototype.renderJSON = function(what) { return this.echo(JSON.stringify(what, null, ' ')); }; var fantomas = new Fantomas({ verbose: true, logLevel: "debug" }); fantomas.start(); Object.keys(links).forEach(function(url) { fantomas.thenOpen(url, function() { links[url] = this.countLinks(); }); }); fantomas.run(function() { this.renderJSON(links).exit(); });
Note
The use of the super_
child class property which becomes available once its parent has been defined using inherits()
; it contains a reference to the parent constructor.
Don't forget to call ``Casper``'s parent constructor!
Of course this approach is bit more verbose than the easy monkey-patching one, so please ensure you're not just overengineering stuff by subclassing the Casper
class.
Using CoffeeScript
If you're writing your casper scripts using CoffeeScript, extending casper is getting a bit more straightforward:
links =
'http://edition.cnn.com/': 0
'http://www.nytimes.com/': 0
'http://www.bbc.co.uk/': 0
'http://www.guardian.co.uk/': 0
class Fantomas extends require('casper').Casper
countLinks: ->
@evaluate ->
__utils__.findAll('a').length
renderJSON: (what) ->
@echo JSON.stringify what, null, ' '
fantomas = new Fantomas
loadImages: false
logLevel: "debug"
verbose: true
fantomas.start()
for url of links
do (url) ->
fantomas.thenOpen url, ->
links[url] = @countLinks()
fantomas.run ->
@renderJSON links
@exit()