Bill_VA
Bill_VA

Reputation: 973

Creating HighChart pie charts as sparkline-type elements

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

Answers (2)

Sphinxxx
Sphinxxx

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

scraaappy
scraaappy

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

Related Questions