Reputation: 973
I need to populate a table of data with dynamic, minimal pie charts, sort of like a sparkline chart using HighCharts.
I'm very close to solving this but passing the array of data via the data-sparkline <td>
argument is eluding me.
<td data-sparkline="[{name: 'KARE', y: 17.33, sliced: true, selected: true}, {name: 'KSTP', y: 14.03}, {name: 'WCCO', y: 10.38}, {name: 'KMSP', y: 3.2}] ; pie"/>
Here's what I have so far.
If I hard code the chart data in the function on line 74 of the fiddle, the charts initialize and works, but I need the function to read the array in the table.
for (i = 0; i < len; i += 1) {
$td = $($tds[i]);
stringdata = $td.data('sparkline');
arr = stringdata.split('; ');
data = arr[0];
chart = {};
console.log(data);
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: [{name: 'KARE', y: 17.33, sliced: true, selected: true}, {name: 'KSTP', y: 14.03}, {name: 'WCCO', y: 10.38}, {name: 'KMSP', y: 3.2}],
pointStart: 1
}],
http://jsfiddle.net/8v63kxwp/3/
But if I cycle through the <td>
's and read the string in the data-sparkline argument, it logs the proper string in the console, but doesn't draw the pie chart.
for (i = 0; i < len; i += 1) {
$td = $($tds[i]);
stringdata = $td.data('sparkline');
arr = stringdata.split('; ');
data = arr[0];
chart = {};
console.log(data);
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: data,
pointStart: 1
}],
http://jsfiddle.net/8v63kxwp/2/
Upvotes: 1
Views: 1015
Reputation: 13017
When you read the data from the data-sparkline
attribute, it's just a string, but the Highcharts series
needs an array.
Thus, you need to parse your string into a JavaScript array. This is often done with JSON.parse()
, but the data in data-sparkline
isn't properly formatted JSON, so in this case you can use eval()
instead:
http://jsfiddle.net/8v63kxwp/4/
Note: When using eval()
, make sure you understand and avoid the security risks involved:
Is Javascript eval() so dangerous?
Exploiting JavaScript's eval() method
Upvotes: 1
Reputation: 2886
because data is just a string in the second case, you need to do somethinng like eval to object properties well formated
/**
* Create a constructor for sparklines that takes some sensible defaults and merges in the individual
* chart options. This function is also available from the jQuery plugin as $(element).highcharts('SparkLine').
*/
Highcharts.SparkLine = function (a, b, c) {
var hasRenderToArg = typeof a === 'string' || a.nodeName,
options = arguments[hasRenderToArg ? 1 : 0],
defaultOptions = {
chart: {
renderTo: (options.chart && options.chart.renderTo) || this,
backgroundColor: null,
borderWidth: 0,
type: 'area',
margin: [2, 0, 2, 0],
width: 160,
height: 160,
style: {
overflow: 'visible'
},
// small optimalization, saves 1-2 ms each sparkline
skipClone: true
},
title: {
text: ''
},
credits: {
enabled: false
},
legend: {
enabled: false
},
};
options = Highcharts.merge(defaultOptions, options);
return hasRenderToArg ?
new Highcharts.Chart(a, options, c) :
new Highcharts.Chart(options, b);
};
var start = +new Date(),
$tds = $('td[data-sparkline]'),
fullLen = $tds.length,
n = 0;
// Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile
// can take some seconds, so we split the input into chunks and apply them in timeouts
// in order avoid locking up the browser process and allow interaction.
function doChunk() {
var time = +new Date(),
i,
len = $tds.length,
$td,
stringdata,
arr,
labels,
data,
chart;
for (i = 0; i < len; i += 1) {
$td = $($tds[i]);
stringdata = $td.data('sparkline');
arr = stringdata.split('; ');
data =arr[0];
console.log(typeof(data));
console.log(typeof(eval(data)));
chart = {};
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: eval(data),
pointStart: 1
}],
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
}
}
},
dataLabels: {
enabled: false},
tooltip: {
headerFormat: '<span style="font-size: 10px">{point.key}</span><br/>',
pointFormat: '<b>{point.y}%</b>'
},
chart: chart
});
n += 1;
// If the process takes too much time, run a timeout to allow interaction with the browser
if (new Date() - time > 500) {
$tds.splice(0, i + 1);
setTimeout(doChunk, 0);
break;
}
}
}
doChunk();
#result {
text-align: right;
color: gray;
min-height: 2em;
}
#table-sparkline {
margin: 0 auto;
border-collapse: collapse;
}
th {
font-weight: bold;
text-align: left;
}
td, th {
padding: 5px;
border-bottom: 1px solid silver;
height: 160px;
}
thead th {
border-top: 2px solid gray;
border-bottom: 2px solid gray;
}
.highcharts-tooltip>span {
background: white;
border: 1px solid silver;
border-radius: 3px;
box-shadow: 1px 1px 2px #888;
padding: 8px;
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="result"></div>
<table id="table-sparkline">
<thead>
<tr>
<th>State</th>
<th>Income</th>
<th>Income per quarter</th>
<th>Costs</th>
<th>Costs per quarter</th>
<th>Result</th>
<th>Result per quarter</th>
</tr>
</thead>
<tbody id="tbody-sparkline">
<tr>
<th>Alabama</th>
<td>254</td>
<td data-sparkline="[{name: 'KARE', y: 17.33, sliced: true, selected: true}, {name: 'KSTP', y: 14.03}, {name: 'WCCO', y: 10.38}, {name: 'KMSP', y: 3.2}] ; pie"/>
</tr>
<tr>
<th>Alaska</th>
<td>246</td>
<td data-sparkline="[{name: 'KARE', y: 17.36, sliced: true, selected: true}, {name: 'KSTP', y: 14.03}, {name: 'WCCO', y: 10.38}, {name: 'KMSP', y: 3.2}] ; pie"/>
</tr>
</tbody>
</table>
Upvotes: 1