Search code examples
javascriptphantomjsselectors-api

Looping through element id's to generate screenshots with PhantomJS


Not sure what I'm doing wrong. When running this in PhantomJS it just hangs with no response. It also doesn't show my console messages.

I have a website that has section blocks defined in div tags (templatemo_content). These div tags contain the same id. What I'm trying to accomplish is to loop through the website, located all of the templatemo_content div id's and generate screenshots of each templatemo_content div block.

var page = require('webpage').create();

page.open('myWebpage', function() {

page.onConsoleMessage = function (msg) { console.log(msg); };
  page.viewportSize = { width:1100, height:800 };
  console.log('open');

  window.setTimeout(function() { 
    var clipRects = page.evaluate(function(){
        return = document.querySelectorAll('#templatemo_content');//.getBoundingClientRect();
    });
    console.log('clipRect size = ' + clipRects.length);
    for(var i = 0; i < clipRects.length; ++i) {
        if (clipRects[i]) {
            console.log('element found');
            var clipRect = clipRects[i].getBoundingClientRect();
            page.clipRect = {
                top:    clipRect.top,
                left:   clipRect.left,
                width:  clipRect.width,
                height: clipRect.height
            };
            page.render('google.png');
        }
    }
    phantom.exit();
  }, 3000); // Change timeout as required to allow sufficient time   
});

Again this hangs with not logs from the console. If I remove the for loop and change querySelectorAll to querySelector then it works for one of the div tags.

Any help would be great.


Solution

  • Really late answer, but: The problem is that you were calling the getBoundingClientRect-method outside of page.evaluate. When out of that context — the rendered DOM — getBoundingClientRect will not return anything useful. The solution:

    var clipRects = page.evaluate(function(){
        var rects = [];
        var elements = document.querySelectorAll('#templatemo_content')
        for (var i = 0; i < elements.length; ++i) {
           rects.push(elements[i].getBoundingClientRect());
        }
        return rects;
    }); 
    

    This will run getBoundingClientRect while still in the correct context, and it will return an array of DOMRect's that you'll be able to use. Perhaps something like this:

    for(var i = 0; i < clipRects.length; ++i) {
       page.clipRect = clipRects[i];
       page.render('image' + i + '.png');
    }