A reader emailed me earlier this week and suggested I take a look at Highcharts, a JavaScript charting solution created by Torstein Hønsi out of Norway. It's an interesting package and I'm glad the reader suggested I take a look.

First off - let's talk costs. Highcharts is free for non-commercial use. That's great. The commercial license is a bit odd though. For 80 dollars you get a single site license but the site "does not have customer specific data or charges for its use." I'm not quite sure what to make of that. Customer specific data could be anything from a simple login account to a cookie for your favorite background color. Above that you've got a single developer license. This also seems weird. They say a developer is :"Each person who directly or indirectly creates an application or user interface containing Highcharts is considered a developer." So according to this, if my coworker adds a chart I'm not allowed to edit it if I find a typo. For a JavaScript package I just don't think this makes sense. That being said - the prices (80 for the single site and 360 for the single developer) don't seem too terribly high for what you get. I encourage you to read the license page. Maybe it will make more sense to you then it did to me.

Feature wise you get the normal gamut of support chart types. Nothing stands out here as exception or missing so that's good. However, the examples look very professional. I did a quick comparison to jqPlot and I think Highcharts looks significantly better. It also ships with a couple of built in themes which all look very well done.

Usage follows pretty much every other framework out there. Include jQuery (you can also make it work with Mootools), include the Highcharts library, and then instantiate a chart object. Here is a complete example taken from their documentation:

<html>

<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script src="Highcharts-2.1.2/js/highcharts.js"></script> <script>

var chart1; // globally available $(document).ready(function() { chart1 = new Highcharts.Chart({ chart: { renderTo: 'chart-container-1', defaultSeriesType: 'bar' }, title: { text: 'Fruit Consumption' }, xAxis: { categories: ['Apples', 'Bananas', 'Oranges'] }, yAxis: { title: { text: 'Fruit eaten' } }, series: [{ name: 'Jane', data: [1, 0, 4] }, { name: 'John', data: [5, 7, 3] }] }); }); </script> </head>

<body>

<div id="chart-container-1" style="width: 400px; height: 400px"></div>

</body> </html>

You can view that code here. Modifying the theme is pretty cool - instead of using an object you can just include another JavaScript file, ie:

<html>

<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script src="Highcharts-2.1.2/js/highcharts.js"></script> <script src="Highcharts-2.1.2/js/themes/dark-green.js"></script> <script>

var chart1; // globally available $(document).ready(function() { chart1 = new Highcharts.Chart({ chart: { renderTo: 'chart-container-1', defaultSeriesType: 'bar' }, title: { text: 'Fruit Consumption' }, xAxis: { categories: ['Apples', 'Bananas', 'Oranges'] }, yAxis: { title: { text: 'Fruit eaten' } }, series: [{ name: 'Jane', data: [1, 0, 4] }, { name: 'John', data: [5, 7, 3] }] }); }); </script> </head>

<body>

<div id="chart-container-1" style="width: 400px; height: 400px"></div>

</body> </html>

You can view that demo here. What I find cool is how nicely the new theme changed the default colors to work well with the new background.

Another interesting feature of this framework is that it supports exporting. You can export to PDF, PNG, and JPG. This is done in a slick way. You can either point to his own web server or you can point to a PHP file on your own system. Now to be clear - this is not the same as being able to get a real binary copy of the chart. For example, ColdFusion's built in charting allows you to generate straight to an image that can be stored, emailed, or printed even. All JavaScript based charting engines will still require you to have a real browser to render and execute the code to get the display.

I worked on a simple ColdFusion example and here is where I ran into my only real problem. I don't feel like the documentation for data formats is very clear. The main documentation page is really just an introduction. The examples all give you a quick way to see the code but are just - examples. There is a reference guide as well. But in terms of using data it seems like you have to guess a bit. I know it was a bit rough for me. Then again - I worked on this for thirty minutes so with more practice I think it would get easier. Here is the ColdFusion sample I came up. It's not Ajax based (which Highcharts supports of course) but it is dynamic.

<cfquery name="getArtStats" datasource="cfartgallery"> select count(a.artid) as total, m.mediatype as media from art a join media m on a.mediaid = m.mediaid group by a.mediaid, m.mediatype </cfquery>

<cfset cats = []> <cfset data = []> <cfloop query="getArtStats"> <cfset arrayAppend(cats, media)> <cfset arrayAppend(data, total)> </cfloop>

<html>

<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script src="Highcharts-2.1.2/js/highcharts.js"></script> <script>

var chart1; // globally available $(document).ready(function() { chart1 = new Highcharts.Chart({ chart: { renderTo: 'chart-container-1', defaultSeriesType: 'bar' }, title: { text: 'Art by Media' }, xAxis: { categories: <cfoutput>#serializejson(cats)#</cfoutput> }, yAxis: { title: { text: 'Total' } }, series: [{name:"Totals",data:<cfoutput>#replace(serializejson(data),"""","","all")#</cfoutput>}]

}); }); </script> </head>

<body>

<div id="chart-container-1" style="width: 400px; height: 400px"></div>

</body> </html>

You can view this here. So - thoughts? I know I've seen a few people recently tweet about Highcharts so I'd love to see some comments from folks using it. (And please - if you have used it and can share a URL, please do. I'd love to see real life examples.)