wkhtmltopdf / wkhtmltopdf

Convert HTML to PDF using Webkit (QtWebKit)
https://wkhtmltopdf.org
GNU Lesser General Public License v3.0
13.94k stars 1.81k forks source link

hang with google charts loader.js #2855

Open jrr opened 8 years ago

jrr commented 8 years ago

wkthmltopdf seems to hang forever when loading Google Charts via the currently recommended loader.js method.

It works just fine with the old "jsapi" interface.

Simple testcases below, based on Google's Quick Start

Output:

jrr@jrrmbp:~/Desktop/wk_goog
] wkhtmltopdf --version
wkhtmltopdf 0.12.3 (with patched qt)
jrr@jrrmbp:~/Desktop/wk_goog
] file `which wkhtmltopdf`
/usr/local/bin/wkhtmltopdf: Mach-O 64-bit executable x86_64
jrr@jrrmbp:~/Desktop/wk_goog
] wkhtmltopdf --debug-javascript --window-status drawDone old.html old.pdf
Loading pages (1/6)
Warning: file:///Users/jrr/Desktop/wk_goog/old.html:4 loading via old jsapi google.load..
Warning: file:///Users/jrr/Desktop/wk_goog/old.html:9 drawChart
Warning: file:///Users/jrr/Desktop/wk_goog/old.html:9 set window.status side effect
Counting pages (2/6)
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Done
jrr@jrrmbp:~/Desktop/wk_goog
] wkhtmltopdf --version
wkhtmltopdf 0.12.3 (with patched qt)
jrr@jrrmbp:~/Desktop/wk_goog
] wkhtmltopdf --debug-javascript --window-status drawDone new.html new.pdf
Loading pages (1/6)
Warning: file:///Users/jrr/Desktop/wk_goog/new.html:4 loading via the new loader.js google.charts.load..
[============================================================] 100%

(hangs indefinitely)

related: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1964

old.html:

<html>
  <head>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">
      console.log('loading via old jsapi google.load..');
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(drawChart);

      function drawChart() {
        console.log('drawChart');
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Topping');
        data.addColumn('number', 'Slices');
        data.addRows([
          ['Mushrooms', 3],
          ['Onions', 1],
          ['Olives', 1],
          ['Zucchini', 1],
          ['Pepperoni', 2]
        ]);
        var options = {'title':'How Much Pizza I Ate Last Night',
                       'width':400,
                       'height':300};
        var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
        chart.draw(data, options);
        window.status = 'drawDone';
        console.log('set window.status side effect');
      }
    </script>
  </head>

  <body>
    <div id="chart_div"></div>
  </body>
</html>

new.html:

<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      console.log('loading via the new loader.js google.charts.load..');
      google.charts.load('current', {'packages':['corechart']});
      google.charts.setOnLoadCallback(drawChart);

      function drawChart() {
        console.log('drawChart');
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Topping');
        data.addColumn('number', 'Slices');
        data.addRows([
          ['Mushrooms', 3],
          ['Onions', 1],
          ['Olives', 1],
          ['Zucchini', 1],
          ['Pepperoni', 2]
        ]);
        var options = {'title':'How Much Pizza I Ate Last Night',
                       'width':400,
                       'height':300};
        var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
        chart.draw(data, options);
        window.status = 'drawDone';
        console.log('set window.status side effect');
      }
    </script>
  </head>

  <body>
    <div id="chart_div"></div>
  </body>
</html>
litan1106 commented 8 years ago

same issue on my end with the //www.gstatic.com/charts/loader.js

somnathmuluk commented 8 years ago

Same issue to me. Is there any solution for this?

temuri416 commented 7 years ago

Same problem here... :(

crush83 commented 7 years ago

Same issue. Any progress or ideas about why this is happening?

terrabionic commented 7 years ago

any news?

ppo commented 7 years ago

Same problem :-/

AdamReece-WebBox commented 7 years ago

wkhtmltopdf 0.12.4, same issue. (Can't use 0.13.x because there aren't any statically linked libs yet.)

sergey-growthwheel commented 7 years ago

I made a small debugging of this problem and seems callback drawChart is not executed. The same is when open the page on the QtWeb browser which are used by wkhtmltopdf. Possible this problem is because the QtWeb doesn't support Local Storage.

ThomasNucleus commented 6 years ago

Have the same problem :(

michaelmafort commented 6 years ago

I found a workarround: replace the callback to setTimeout call function, like this: //google.charts.setOnLoadCallback(drawChart);// commented line

//setTimeout to call the drawChart() setTimeout(function(){ drawChart(); }, 500);

Vegekku commented 6 years ago

@michaelmafort solution help me! Run in Symfony 3.4 with wkhtmltopdf 0.12.4.

zeroquaranta commented 6 years ago

Same thing here: google.charts.load("current", {packages:["corechart", "timeline", "bar"]}); google.charts.setOnLoadCallback(drawCharts); For some reason drawCharts is never launched by the QT engine, while it is when using a standard Javascript timer (verified both with wkhtmltopdf and QTWeb). Is there any reason why these google function is not recognized by QT? Could google.load be used instead of google.charts.load ?

onassar commented 6 years ago

Wow that was goofy; no clue on the inner workings, but this worked me based on the types of charts I'm drawing:


/**
 * init
 * 
 * @access  public
 * @return  void
 */
function init() {
    google.charts.load('current', {'packages': ['corechart', 'calendar']});
    var interval = setInterval(function() {
        if (
            google.visualization !== undefined
            && google.visualization.DataTable !== undefined
            && google.visualization.PieChart !== undefined
            && google.visualization.BarChart !== undefined
        ) {
            clearInterval(interval);
            for (var index in queue) {
                queue[index]();
            }
            window.status = 'ready';
        }
    }, 100);
}

Where the variable queue is an array of the functions I want to execute once everything is ready :)

oojacoboo commented 5 years ago

Any progress on this? This is incredibly annoying.

jrr commented 5 years ago

I haven't used wkhtmltopdf in ages, so I'm unsubscribing from this thread. I'll leave it open so others may use it.

Next time I need to generate PDFs, I plan to first try headless chrome.

oojacoboo commented 5 years ago

Yea, spent the past week getting a new Node docker container added to our stack with headless Chrome, express, and puppetter. The end result of PDF's is far better than wkhtmltopdf. Unfortunately it adds another server to our stack.

ambasador commented 5 years ago

Google Charts are not good at all. I've serval issues with google charts. I'm using D3 library https://d3js.org v5.9.2.

Everything is ok.

You can find examples how to do it. I used that example https://wizardace.com/d3-piechart/

akaspick commented 2 years ago

So I think the magic sauce is replacing current with version 44.

ie: google.charts.load('44', {'packages':['corechart']});

45 doesn't appear to work, so anything later is likely broken too. Stick to 44 and you should be good.

dexidle commented 1 year ago

So I think the magic sauce is replacing current with version 44.

ie: google.charts.load('44', {'packages':['corechart']});

45 doesn't appear to work, so anything later is likely broken too. Stick to 44 and you should be good.

thanks @akaspick its worked when i replace the current with '44'

this is my code

function init() {
            google.charts.load('44', {
                packages: ['corechart', 'line']
            });
            var interval = setInterval(function() {
                console.log('not-ready-yet');
                if (
                    google.visualization !== undefined
                    && google.visualization.DataTable !== undefined
                    && google.visualization.PieChart !== undefined
                ){
                    clearInterval(interval);
                    console.log('ready');
                    window.status = 'ready';
                    drawChart();
                  }
            }, 100);
        }

based on this solution https://stackoverflow.com/a/63190035 by using --window-status ready

tested using wkhtmltopdf 0.12.6 (with patched qt)