HighCharts Base64 cannot be decoded to convert to .png or .jpg image - highcharts

I'm using the code below to generate a HighCharts graph and get the base64 code from the SVG image generated. I'm then using an engine like php and the base64_decode function to decode the Base64 and generate a .png or .jpg image from that.
The problem I'm having is that php complains that the Base64 code is invalid. When I try that with the Base64 code for any other random image, php accepts it and the .png or .jpg is created immediately.
I'm conveniced it's not the php code, but it's something to do with the Base64 code I'm getting from HighCharts. I've tried the same exercise using other tools instead of php like ColdFusion and the result was the same. The ones generated by HighCharts never worked but others did.
I would appreciate some guidance if anyone has an idea. You can run the snippet below to check the Base64 generated. Thanks.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container"></div>
<button id="add-image">Show base64 string for above chart</button>
<script type="text/javascript">
var chart = Highcharts.chart('container', {
series: [{
data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
}]
});
$("#add-image").click(function() {
var svg = $("#container").find('svg')[0],
svgData = new XMLSerializer().serializeToString(svg),
base64ImageValue = btoa(unescape(encodeURIComponent(svgData)));
document.getElementById('base64Container').innerHTML = base64ImageValue;
});
</script> <br><br>
<textarea id="base64Container" style="width:90%" rows="10"></textarea>

Related

HighCharts offline-exporting module not working

I'm having trouble forcing highcharts to export offline. I've added the offline-exporting.js module along with the exporting module. I've set the fallbackToExportServer to false, but I still go to the highcharts server (https://export.highcharts.com/) and get this error: 13 Request Entity Too Large.
<script src="//code.highcharts.com/highcharts.js"></script>
<script src="//code.highcharts.com/modules/data.js"></script>
<script src="//code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/offline-exporting.js"></script>
exporting: {
filename: title,
fallbackToExportServer: false,
To see the issue, go to: https://www.nrel.gov/transportation/drive-cycle-tool/
In the Drive cycles table, search for “Fleet DNA”.
Click on “Fleet DNA Drayage Maximum Energy*”
Scroll up and click “Download Drive Cycle Data or Image” under the chart.
Choose “Download JPEG image”
Some data sets work fine.
It is linked to this reported issue:
https://github.com/highcharts/highcharts/issues/4614
As a workaround you could set up a custom exporting server with increased size limit:
https://www.highcharts.com/docs/export-module/setting-up-the-server
I noticed the same issue few days back, kind of strange, despite setting the flag to false, it was calling the highchart server for chart pdf.
I then resorted to use exportChartLocal method of highchart chart instance:
chart.exportChartLocal({
type: 'image/jpeg', // replace with image/jpeg
filename: 'test.jpg',
fallbackToExportServer: false,
sourceWidth: 900,
scale: 1,
});
Look at this example: https://jsfiddle.net/riteshwaghela/huw8e31z/7/

autoTable (3.5.9) not a function

I have been using jsPDF and autoTable for quite a while and am now trying to update to the latest version of both; jsPDF 2.0.0 and autoTable 3.5.9 were both released a couple of days ago.
jsPDF itself is working fine but I'm getting the "doc.autoTable is not a function" error when trying to use autoTable.
Here's a very simple example:
<script src="https://unpkg.com/jspdf"></script>
<script src="https://unpkg.com/jspdf-autotable"></script>
<script>
const doc = new jspdf.jsPDF();
doc.autoTable({
head: [['Name', 'Email', 'Country']],
body: [
['David', 'david#example.com', 'Sweden'],
['Castille', 'castille#example.com', 'Spain']
]
});
doc.save('table.pdf');
</script>
You can see it in action (or not!) at https://jsfiddle.net/r8dah0m7/.
Has anyone managed to get autoTable 3.5.9 working with jsPDF 2.0.0 using downloaded / CDN dist files and if so, what am I missing?
Try the following
autoTable(doc, {
head: [['Name', 'Email', 'Country']],
body: [
['David', 'david#example.com', 'Sweden'],
['Castille', 'castille#example.com', 'Spain']
]
});
The documentation for 3.5.9 has not been updated.

Chart is not defined in a Rails 6 view page with webpacker

I'm trying to figure out the right way to use a Chart from chart.js in a Rails 6 app using webpacker. I would like my chart generation javascript code to remain in the page since I'll be dynamically generating it from the view.
I started with
yum add chartjs
then added to the application pack (and javascript_pack_tag is in my application.html.erb)
// app/javascript/packs/application.js
import Chart from "chartjs";
And then, in a view I try and use that library:
<div class="row">
<div class="col">
<canvas id="backlog-chart" width="100%" height="400px">
<script>
var ctx = document.getElementById('backlog-chart').getContext('2d');
new Chart(ctx, { ...
This fails with an Chart is not defined javascript error.
Things I've tried:
the require("chartjs") form of including the library in application.js seems to have no impact one way or the other.
I tried adding to config/webpack/environment.js to the ProvidePlugin object with Chart: "chartjs/chart.js" but no changes.
And I've tried adding import Chart from "chart.js" directly to the <script> section in the view but this fails with a "import only allowed in module" error on the browser.
My javascript skills have definitely not kept up with the last couple years of new technologies so any suggestions on the right way to do this would be appreciated.
You can't use Chart in a script in your HTML body because Chart hasn't been globably defined. You could import the chart.js javascript by embedding the script tag, and then Chart would be available. But you said you wanted to use Webpacker, so...
Include your chart definition in your application.js, rather than in the script tag.
// app/javascript/packs/application.js
import Chart from "chartjs";
var ctx = document.getElementById('backlog-chart').getContext('2d');
var myChart = new Chart(ctx, {...});
This will target that canvas in your HTML:
<canvas id="backlog-chart" ... />

Invoke native file browser using phonegap

I have to implement file upload feature in my phonegap project. User should be able to upload any type of file from the phone memory or sd card. The application screens I designed using jQuery Mobile framework. I tried input type="file", but it is not supported in android 4.4. I tried phonegap camera API too, but it is supported only media files. I found some cordova plugins (exm1,exm2 ). But these plugins using custom UI. I want to invoke native file browser for choosing the file & it has to work in both Android & iPhone platforms. Is there a way to implement the same?
I found cordova file chooser plugin (https://github.com/cdibened/filechooser) would be helpful for android platform, but I am unable to make it work. The success callback function is not immediately getting triggered after the file selection (tested with android 4.4.2). Please find my code below,
<input type="file" id="fileinput" name="fileinput"/>
$("#fileinput").bind('click',function(){
console.log("choose file selected");
filechooser.open( {}, fileChooseSuccess, fileChooseFailed );
});
function fileChooseSuccess(data) {
var filepath = data.filepath;
console.log("file path:"+filepath);
}
function fileChooseFailed(msg) {
console.log(msg);
}
I was able to get your plugin, FileChooser working.
There are certain things that have to be done though.
You need to open the following with your editor
FileChooser.java
FileChooserActivity.java
FileListAdapter.java
FileListFragment.java
LocalStorageProvider.java
and append
import your.package.name.R;
to each of those files.
Here is the demo code I used:
<html>
<head>
<title>Hello World</title>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
document.addEventListener("deviceready", function(){
var success = function(data) {
alert("File chosen: " + data.filepath);
};
var error = function(msg) {
console.log( msg );
};
$('#fileinput').click(function(e) {
filechooser.open({}, success,error);
});
});
</script>
</head>
<body>
<input type="file" id="fileinput" name="fileinput"/>
</body>
</html>
Also, be aware that the author intended this to be used in KitKat 4.4.4. It may work with lower versions but he's uncertain.
Take note that the only difference between the HTML5 choice window and this is the "Internal Storage" option.
Hope this helps.
For android you can use this plugin:
https://github.com/cdibened/filechooser
input file should work on android too (on most of the versions, but it doesn't work on android 4.4, 4.4.1 and 4.4.2)
HTML file input in android webview (android 4.4, kitkat)
for iOS there is no plugin, you don't have a native file browser.
Sample project
https://github.com/jcesarmobile/FileBrowserAndroidTest

Generate graphs in PDF file using TCPDF

There are tons of topics on this, none of which have solved my issue. What I'd like to do is simple - generate a bar graph and then embed this graph into a pdf file that I will be generating with a library called TCPDF.
I'm having no problems generating HTML content using TCPDF but when it comes to generating the graph and including it in the pdf file, I'm having all kinds of issues.
Generating the graph
I'm creating the graph using a library called svggraph. Generating the graph is very simple, the only problem is that there are headers being sent through the inclusion of the main class file. When headers are sent, TCPDF cannot generate the PDF document.
My setup now:
generatereport.php - TCPDF generates the pdf document on this page
graph.php - SVGGraph generates the bar graph on this page
I've tried:
file_get_contents('graph.php') from generatereport.php - nothing is being output in the pdf report when I use the built in writeHTML function that TCPDF offers
require_once('graph.php') - headers already sent error
echo file_get_contents('graph.php') - Headers already sent, but that was expected. The good news is that the graph was displayed properly.
Goal (What I'd like to happen)
TCPDF has a built in ImageSVG function that is used for this exact purpose. The first parameter can take a XML string of SVG data; the problem here is that I can't figure out how to return XML data from the graph.php page (I've read every documentation page I could find).
Does anyone have any experience using either of these two libraries?
Thanks!
Edit: Some code
Graph.php:
<?php
require_once 'svggraph/SVGGraph.php';
$graph = new SVGGraph(500, 400);
$graph->Values(1, 4, 8, 9, 16, 25, 27);
$graph->Render('LineGraph', true, true)
?>
generatereport.php
$html = file_get_contents('http://localhost:8080/vu/graph.php');
if(!empty($file)){
//$pdf->Write(0, $html, '', 0, 'L', true, 0, false, false, 0);
//$pdf->writeHTML($html, true, false, true, false, '');
$pdf->ImageSVG('#' . $html, $x=15, $y=30, $w='', $h='', $link='http://www.tcpdf.org', $align='', $palign='', $border=1, $fitonpage=false);
}
The # symbol tells the function that XML data is being sent to it, as opposed to an SVG file.
Use fetch - See below
<?php
require_once 'svggraph/SVGGraph.php';
$graph = new SVGGraph(500, 400);
$graph->Values(1, 4, 8, 9, 16, 25, 27);
$output = $graph->fetch('LineGraph');
?>
and then feed it to TCPDF (Since fetch without options generates the XML declaration and doctype)
This should generate $output of the format:
<svg style="overflow: hidden; position: relative;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1226" version="1.1" height="826"><image transform="matrix(1.0364,-0.3305,0.3305,1.0364,-41.846,108.0143)" preserveAspectRatio="none" x="10" y="10" width="205" height="154" xlink:href="wallpaper.jpg" opacity="1" stroke-width="1"></image><rect transform="matrix(1.0364,-0.3305,0.3305,1.0364,-41.846,108.0143)" x="165" y="114" width="50" height="50" r="0" rx="0" ry="0" fill="#C0C0C0" stroke="#000" opacity="0" stroke-width="1"></rect><image transform="matrix(1.1575,0.2385,-0.2385,1.1575,-442.1395,-145.4163)" preserveAspectRatio="none" x="500" y="10" width="205" height="154" xlink:href="wallpaper.jpg" opacity="1" stroke-width="1"></image><rect transform="matrix(1.1575,0.2385,-0.2385,1.1575,-442.1395,-145.4163)" x="655" y="114" width="50" height="50" r="0" rx="0" ry="0" fill="#C0C0C0" stroke="#000" opacity="0" stroke-width="1"></rect></svg>
Feed it like this
$pdf->ImageSVG('#' . $output, $x=15, $y=30, $w='', $h='', $link='http://www.tcpdf.org', $align='', $palign='', $border=1, $fitonpage=false);
In line with the comment above from $VSOverFlow.
Of course you can also save the output in a file and then provide the path to the file like so
$pdf->ImageSVG($file='images/file.svg', $x=15, $y=30, $w='', $h='', $link='', $align='', $palign='', $border=0, $fitonpage=false);

Resources