M. Bostock pointed out that nodejs\' jsdom have incomplete support for svg, and, critical for me, doesn\'t support getBBox()
. Also, he advised to switch to node
Since you want to do this from node.js, you should use a PhantomJS bridge like phantomjs-node (phantom npm module).
When you don't open a page in PhantomJS, you're actually working in an about:blank page, you need to add '--local-to-remote-url-access=yes' commandline option for the underlying PhantomJS process, so that remote resources can be loaded. Maybe --web-security=false
, --ssl-protocol=any
and ignore-ssl-errors=true
may be necessary.
To inject additional scripts into the DOM, you need to use injectJs() for local files and includeJs() for remote files. Furthermore, you cannot directly access the DOM in PhantomJS, because it has two contexts. The sandboxed page context (page.evaluate()) has no access to variables defined outside, so you will need to pass them explicitly in, if you need them.
var phantom = require('phantom');
var async = require('async');
function run(page, ph) {
page.evaluate(function () {
// page context: DOM code here
return document.title;
}, function (title) {
// node code here
console.log('Page title is ' + title);
ph.exit();
});
}
var remoteScripts = [ "http://d3js.org/d3.v3.min.js" ];
var localScripts = [ "../js/d3.v3.min.js", "../js/jquery-2.1.3.min.js" ];
phantom.create('--local-to-remote-url-access=yes', '--web-security=false', function (ph) {
ph.createPage(function (page) {
async.series(remoteScripts.map(function(url){
return function(next){
page.includeJs(url, function(){
next();
});
};
}), function(){
async.series(localScripts.map(function(url){
return function(next){
page.injectJs(url, function(){
next();
});
};
}), function(){
run(page, ph);
});
});
});
});
You can use async to load script lists into the DOM. I used the series()
function.