I am trying to generate multiple charts in a PDF using Google Charts. For the PDFs, I am using CakePDF with the Wkhtmltopdf engine. I appear to be having a problem with actually loading the Google Chart code into the PDF though. This is my current code for my Javascript.
<script type="text/javascript" src="https://www.google.com/jsapi">
</script>
<script type="text/javascript">
google.load('visualization', '1.0', {'packages':['corechart']});
//setTimeout(function() {google.load('visualization', '1.0', {'packages':['corechart']});}, 100);
google.setOnLoadCallback(drawChart);
function drawChart(doIt,taken, total, element)
{
if (typeof doIt === 'boolean')
{
var data = new google.visualization.DataTable();
data.addColumn('string', 'Type');
data.addColumn('number', 'Courses');
data.addRows([
['Taken', taken],
['Remaining', total - taken]
]);
var options = {
'width':40,
'height':40};
var chart = new google.visualization.PieChart(document.getElementById(element));
chart.draw(data, options);
}
}
</script>
The problem is that when I do the google.load for the visualization package, it causes Wkhtmltopdf to return with an error saying that the engine returned no data. I found a problem that I thought was similar at Why does google.load cause my page to go blank? so I tried to do setTimeout(function() {google.load('visualization', '1.0', {'packages':['corechart']});}, 100); The problem with this solution was that if the delay is too low, the page will return with no errors, but it will be completely blank; however, if I set the delay too high, the page will just not load the package and the Javascript will break at
var data = new google.visualization.DataTable();
when I call the function. Additionally, that poster stated problem with document.write(), but I have no issues if I add document.write() lines before or after I add the content to the page. I would appreciate it if anyone knew how to get Google Charts to work with Wkhtmltopdf and could help me.
Ok, In an attempt to give the API more time to load, I moved where I call the function to the end of the PHP. Now, it just sets an array of elements that need graphs drawn in them and the proper values, then it calls the function with the value from the arrays. I am not sure what the problem is now though because it is breaking on chart.draw(data, options);
now. It appears to be getting the correct values and element passed to it though.
This will seem really roundabout since it is. For whatever reason, Wkhtmltopdf cannot read anything I put in a javascript tag. I have tried everything I can to get it to read it, but it just will not haha. The CakePDF plugin can read Javascript though, so my JS code is in the default PDF layout. Then in the actual view that is rendered by WkhtmltoPdf, I create an array of elements and values. I then do this (after many different possible solutions, this is the only way I was able to call the JS function)
for ($i = 0; $i < sizeof($grade_array); $i++)
{
$element = $grade_array[$i][2];
echo '<script type="text/javascript">drawChart(true, '.$this->Js->value($grade_array[$i][0]).', '.$this->Js->value($grade_array[$i][1]).','.json_encode($element).');</script>';
}
It appears to pass all of the correct data. Upon calling the function, I have debug lines printing the parameters, and all parameters are correctly printed. I also noticed that if I do document.write('test') in the same place as the chart.draw(), it will write 'test' without any error. For some reason, if I do chart.draw(), it just says Wkhtmltopdf didn't return any data.
Problem: When using wkhtmltopdf / wkhtmltoimage the pdf / image on a html page (with Google Chart), it did not contain the Google chart. The output (pdf / png) was simply blank at the position the Google Chart should show up. The original html page was okay, of course.
Solution: I solved this issue (Google Charts + wkhtmltopdf) by replacing:
<script src="http://www.gstatic.com/charts/loader.js"></script>
by
<script src="http://www.google.com/jsapi"></script>
Somehow the wkhtmltopdf library could not handle a Google Chart html page which contains the first javascript include.
I resolved this problem today myself, so here is what worked out for me. For a more detailed walkthrough, you are welcome to read my blog post about the subject.
I only had to make two simple changes to make it work:
javascript-delay
argument, e.g. javascript-delay 1000
. This delays the execution of JavaScript code for 1000 millisecondsfunction init() {
google.load("visualization", "1.1", {
packages: ["corechart"],
callback: 'drawCharts'
});
}
Then you can simply implement the drawCharts
function where you can draw your charts exactly as you normally would.
Make sure your markup includes the following:
<body onload="init()">
<div id="my-chart"></div>
</body>
Simply draw your chart to the div with the above ID, and you should be good to go.
Note: I am using the newest available binary (0.12.0 as of now). Tested on a 64-bit Ubuntu installation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With