raycarr
raycarr

Reputation: 21

CasperJS screenshot is not rendering images to png file

I'm successfully grabbing screenshots from multiple websites using phantomjs via casperjs. I'm having real problems though getting one site, http://fiver.com , to render out the background banner in this element:

<div class="hero-slide sel" style="background-image: url('//cdnil21.fiverrcdn.com/assets/v2_photos/sellerpage-coverphoto-779e2108b002090406e707086772ad9b.jpg');">
    <img alt="Sellerpage coverphoto" src="//cdnil21.fiverrcdn.com/assets/v2_photos/sellerpage-coverphoto-779e2108b002090406e707086772ad9b.jpg">
</div>

And then the first three images in <div class="packages-list cf"> don't render either. The images following those render out to png just fine.

Versions being used:

I'm using the following page settings for casperjs:

  pageSettings: {
javascriptEnabled: true,
loadImages: true,
loadPlugins: true,
localToRemoteUrlAccessEnabled: true,
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11"

} });

I'm loading the page, which is successfully redirecting to the https url. I'm running with this config file:

{"sslProtocol": "any", 
 "ignoreSslErrors": true, 
 "ssl-certificates-path": "ssl", 
 "web-security": false, 
 "cookiesFile": "biscuit", 
 "maxDiskCacheSize": 1000, "diskCache": true }

The code that executes and waits for everything to load is:

this.thenOpen(screenshotUrl, function() {
    this.wait(25000);

    // Fix transparent background rendering bug
    // Courtesy of: http://uggedal.com/journal/phantomjs-default-background-color/
    this.evaluate(function() {
        // css injection to force backgrounds to print
        var style = document.createElement('style'),
         text = document.createTextNode('body { background: #fff; -webkit-print-color-adjust: exact; }');
        style.setAttribute('type', 'text/css');
        style.appendChild(text);
        document.head.insertBefore(style, document.head.firstChild);

        var images = document.getElementsByTagName('img');
        images = Array.prototype.filter.call(images, function(i) { return !i.complete; });
        window.imagesNotLoaded = images.length;
        Array.prototype.forEach.call(images, function(i) {
            i.onload = function() { window.imagesNotLoaded--; };
        });
    });
});
casper.waitFor(function() {
    return this.evaluate(function() {
        return window.imagesNotLoaded == 0;
    });
 });
 this.then(function(){
     this.echo('Screenshot for ' + viewport.name + ' (' + viewport.viewport.width + 'x' + viewport.viewport.height + ')', 'info');
     this.capture('screenshots/' + screenshotDateTime + '/' + viewport.name + '-' + viewport.viewport.width + 'x' + viewport.viewport.height + '.png', {
    top: 0,
    left: 0,
    width: viewport.viewport.width,
    height: viewport.viewport.height
    });
  });

I have tried setting the wait as high as 100000, but it still didn't work.In the evaluate I'm injecting some css and running a function that is trying to wait for all the images to load. Thn I go into my this.then function to render the image to disk.

I'm pulling my hair out with this one.

Here's the screenshot: http://postimg.org/image/flvpvhy6v/

Any ideas?

Upvotes: 1

Views: 1412

Answers (1)

Artjom B.
Artjom B.

Reputation: 61892

JavaScript has no blocking wait or sleep functionality. So when you wait, you schedule an asynchronous step. Your code contains an evaluate call after the wait call. The evaluate call is synchronous/blocking, but wait isn't, so the wait will be executed after the evaluate. You have to put synchronous code in a callback of a step function like wait* or then*.

this.wait(25000, function(){
    this.evaluate(function() {
        // some code
    });
});

Upvotes: 2

Related Questions