John Chrysostom
John Chrysostom

Reputation: 4063

Get highcharts data without parseJSON

I'm trying to have highcharts update a chart dynamically via an AJAX query. Currently, I have the server returning JSON for the new chart, which I'm then parsing using parseJSON. This is all well and good, except for one thing - the usual format of highcharts code is not true JSON, so the format of the chart is different in the file. (For example, type: 'bar' has to become "type": "bar" for proper JSON.)

Here's the code for the main page:

<script type='text/javascript' src='//code.jquery.com/jquery-1.9.1.js'></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>

<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>

<script>
$(function () {
        $('#container').highcharts({
            title: {
                text: 'Monthly Average Temperature',
                x: -20,
                style: {
                    color: 'rgb(103,103,103)',
                    fontFamily: '"Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif'
                }
            },
            subtitle: {
                text: 'Source: WorldClimate.com',
                x: -20,
                style: {
                    color: 'rgb(103,103,103)'
                }
            },
            xAxis: {
                categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
            },
            yAxis: {
                title: {
                    text: 'Temperature (C)',
                    style: {
                        color: 'rgb(103,103,103)'
                    }
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'middle',
                borderWidth: 0
            },
            series: [{
                name: 'Tokyo',
                color: 'rgb(62,144,200)',
                data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6],
                point: {
                    events: {
                        click: function() {
                            $.get('thetest/test.php', function (data) {
                                var temp=jQuery.parseJSON(data);
                                $('#container').highcharts(temp);
                            })
                        }
                    }
                }
            }, {
                name: 'New York',
                color: 'rgb(128,183,101)',
                data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
            }, {
                name: 'Berlin',
                color: 'rgb(145,111,79)',
                data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
            }, {
                name: 'London',
                color: 'rgb(207,186,132)',
                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]
            }, {
                name: 'Last One',
                color: 'rgb(70,95,119)',
                data: [13.9, 14.2, 15.7, 18.5, 21.9, 25.2, 27.0, 26.6, 24.2, 20.3, 16.6, 14.8]
            }]
        });
    });
</script>

And here's the JSON that's getting returned:

{
    "chart": {
        "type": "bar"
    },
    "title": {
        "text": "Historic World Population by Region"
    },
    "subtitle": {
        "text": "Source: Wikipedia.org"
    },
    "xAxis": {
        "categories": ["Africa", "America", "Asia", "Europe", "Oceania"],
        "title": {
            "text": null
        }
    },
    "yAxis": {
        "min": 0,
        "title": {
            "text": "Population (millions)",
            "align": "high"
        },
        "labels": {
            "overflow": "justify"
        }
    },
    "tooltip": {
        "valueSuffix": " millions"
    },
    "plotOptions": {
        "bar": {
            "dataLabels": {
                "enabled": true
            }
        }
    },
    "legend": {
        "layout": "vertical",
        "align": "right",
        "verticalAlign": "top",
        "x": -40,
        "y": 100,
        "floating": true,
        "borderWidth": 1,
        "backgroundColor": "#FFFFFF",
        "shadow": true
    },
    "credits": {
        "enabled": false
    },
    "series": [{
        "name": "Year 1800",
        "data": [107, 31, 635, 203, 2]
    }, {
        "name": "Year 1900",
        "data": [133, 156, 947, 408, 6]
    }, {
        "name": "Year 2008",
        "data": [973, 914, 4054, 732, 34]
    }]
}

This works perfectly of course... but is there any way to just pass the results back from test.php in standard "highcharts" format rather than as JSON?

Upvotes: 2

Views: 967

Answers (4)

Bren
Bren

Reputation: 2206

I am going to suggest another approach.

As Reimius said Highcharts uses a Javascript object for chart configuration. The configuration can be very basic Javascript object with no functions involved, in which case you can parse it as json and use it on client side fetching it via an Ajax call. Though, I think this would be really restrictive.

I overcame this problem in the past by including a server side generated Javascript configuration file into html just like any other Javascript file. In the end that's the way to access and run your Javascript code within the browser.

E.g. Assume I want to show temperature of selected city on my page as a chart and I have an endpoint to get the configuration as follows:

<server-address>/temperature/<id>

and what I get from this endpoint is a getter function as follows:

function getChartConfig() {
  return {
        title: {
            text: 'Monthly Average Temperature',
            x: -20,
            style: {
                color: 'rgb(103,103,103)',
                fontFamily: '"Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif'
            }
        },
        subtitle: {
            text: 'Source: WorldClimate.com',
            x: -20,
            style: {
                color: 'rgb(103,103,103)'
            }
        },
        xAxis: {
            categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        },
        yAxis: {
            title: {
                text: 'Temperature (C)',
                style: {
                    color: 'rgb(103,103,103)'
                }
            },
            plotLines: [{
                value: 0,
                width: 1,
                color: '#808080'
            }]
        },
        legend: {
            layout: 'vertical',
            align: 'right',
            verticalAlign: 'middle',
            borderWidth: 0
        },
        series: [{
            name: 'Tokyo',
            color: 'rgb(62,144,200)',
            data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6],
            point: {
                events: {
                    click: function() {
                        $.get('thetest/test.php', function (data) {
                            var temp=jQuery.parseJSON(data);
                            $('#container').highcharts(temp);
                        })
                    }
                }
            }
        }, {
            name: 'New York',
            color: 'rgb(128,183,101)',
            data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
        }, {
            name: 'Berlin',
            color: 'rgb(145,111,79)',
            data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
        }, {
            name: 'London',
            color: 'rgb(207,186,132)',
            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]
        }, {
            name: 'Last One',
            color: 'rgb(70,95,119)',
            data: [13.9, 14.2, 15.7, 18.5, 21.9, 25.2, 27.0, 26.6, 24.2, 20.3, 16.6, 14.8]
        }]
    });
}

}

then you could have your html source as follows:

<script type='text/javascript' src='//code.jquery.com/jquery-1.9.1.js'></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>

<!-- Notice Highcharts configuration is included as a javascript file -->
<script type='text/javascript' src='<server-address>/temperature/1'></script>   

<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>

<script>
$(function () {
    $('#container').highcharts(getChartConfig());
</script>

Now, you don't have to include it in a static way, you can dynamically load Javascript using JQuery getScript function or another way.

I am not sure if this fits into your needs, but you get the idea. I am sure you can apply the logic to your needs. This worked for me in the past.

Upvotes: 2

Reimius
Reimius

Reputation: 5712

There is a misunderstanding here... Highcharts doesn't have a configuration "format" specifically designed for it in the sense of what you are asking in your question. Highcharts takes a Javascript configuration object, which is not the same thing as JSON.

If you have ever heard the saying that: "Every square is a rectangle, but every rectangle is not a square"? This saying is similar in that all JSON can be interpreted into Javascript, but not all Javascript can be interpreted into JSON. This is important because it means that JSON can be treated as a subset of Javascript, which means it can be interpreted into JavaScript (Javascript objects particularly). It then follows that you can return JSON from the server and turn it into a JavaScript object for use as your anychart configuration object.

The reason why this is relevant is it looks like what is getting returned from your server is a Javascript object definition (which is what is actually used by Highcharts), not JSON. The problem is that you need the text converted into and ran as Javascript. There are two solutions to this situation, one of which is much better than the other.

  1. Since you are currently returning a Javascript object as text, you could use the eval() function on that object. This is a bad decision to make, there is a saying that "eval is evil". For all the reasons of why this is, you can look it up online, but you may be able to use this route without issue.

  2. The other option is when you originally store your highcharts config, or when you return it from your php file, you can just make sure that the syntax complies with the JSON format. It looks like in your example that this wont make any difference in how you program works, it would just be harder to implement. This is the correct way to fix this problem.

Upvotes: 2

Sebastian Bochan
Sebastian Bochan

Reputation: 37578

Yes, you need to get JSON, which can be returned in php by json_encode() function.

Upvotes: 0

Johan
Johan

Reputation: 35194

If I understand you correctly, all you need to do is to parse the JSON string in to an object:

var json = '{ "chart": { "type": "bar" } }',
    parsed = JSON.parse(json);

$('#container').highcharts(parsed);

http://jsfiddle.net/3QG6Q/

Upvotes: 0

Related Questions