Video icon 64
Learning to code? Skill up faster with our practical video courses. Start your free trial today.
Advertisement

Visualizing Data with Flot

by

There are a lot of tutorials on how to make CSS bar graphs. But sometimes, bar graphs aren't enough. What if our data tracks change over time and a line graph is more appropriate? Or maybe we're not satisfied with just a bar graph. Enter Flot, ajQuery plugin that lets us make good looking graphs with ease.

In a data centric world, we often have to display large amounts of data on the web. Generally we show a table of values with headings and if we really wanted to get fancy we would use a picture of a graph. People like pictures. I like pictures. Why? Because it is far easier to interpret data when it is in visual form. However, creating a picture graph and updating it with new data can be a pain. In this tutorial, we’re going to use a jQuery plugin called Flot to create graphs on the fly.

Step 1

To start, we need some data. For this tutorial, we’re going to be using some GDP data for a few different countries I found on Wikipedia. Unfortunately the data only goes to 2003 but since this isn’t a lesson on economics, it will suffice. Let’s put the data into a simple table and add a few lines to describe it.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Flot Tutorial</title>

</head>

<body>

<div id="plotarea">
	<table>
		<caption>GDP, based on exchange rates, over time. Values in billion USDs.</caption>
		<tr>
			<td></td>
			<th scope="col">2003</th>
			<th scope="col">2002</th>
			<th scope="col">2001</th>
			<th scope="col">2000</th>
			<th scope="col">1999</th>
			<th scope="col">1998</th>
		</tr>
		<tr>
			<th scope="row">USA</th>
			<td>10,882</td>
			<td>10,383</td>
			<td>10,020</td>
			<td>9,762</td>
			<td>9,213</td>
			<td>8,720</td>
		</tr>
		<tr>
			<th scope="row">EU</th>
			<td>10,970</td>
			<td>9,040</td>
			<td>8,303</td>
			<td>8,234</td>
			<td>8,901</td>
			<td>8,889</td>
		</tr>
		<tr>
			<th scope="row">UK</th>
			<td>1,765</td>
			<td>1,564</td>
			<td>1,430</td>
			<td>1,438</td>
			<td>1,460</td>
			<td>1,423</td>
		</tr>
		<tr>
			<th scope="row">China</th>
			<td>1,575</td>
			<td>1,434</td>
			<td>1,345</td>
			<td>1,252</td>
			<td>1,158</td>
			<td>1,148</td>
		</tr>
		<tr>
			<th scope="row">India</th>
			<td>599</td>
			<td>510</td>
			<td>479</td>
			<td>457</td>
			<td>447</td>
			<td>414</td>
		</tr>
	</table>
</div>

<p>GDP, based on exchange rates, over time. Values in billion USDs.</p>

</body>
</html>

Notice that the table is contained in a div with an id of “plotarea.” The graph we will be creating later will replace the table contained inside this div. The table looks a bit ugly at the moment so let’s add some CSS to make it more presentable.

<style type="text/css">
	body { font-family: Arial, Helvetica, sans-serif; }
	table { border-collapse: collapse; }
	td, th { border: 1px solid #222; padding: 5px; }
	
	/* Fix the legend */
	.legend td, .legend th { border: 0; padding: 2px; }
</style>

You should have something that looks like this.

Data Table

Now that we have all the data in a table, we can start adding in the JavaScript that will create a graph for us. Technically, we don’t have to have a table, but it’s nice to have for two reasons:

  1. Accessibility. There are many blind web users out there and it is important to make everything on your website screen reader friendly. Screen readers cannot interpret graphs created by Flot.
  2. Degradability. A small number of web users disable JavaScript. Although this is a very small minority, it is not much more work to add a table so that they can view the data as well.

Step 2

Link the required JavaScript libraries. There are two of them, plus one more for IE support. We need to link jQuery first and then the Flot library since it depends on jQuery. Since Flot uses the canvas element to draw the graphs, we need to include the ExplorerCanvas script which emulates the canvas element in IE. Firefox, Opera and Safari users don’t need this so we’ll use conditional comments to make sure only IE users download it.

<script src="jquery.js" language="javascript" type="text/javascript"></script>
<script src="jquery.flot.pack.js" language="javascript" type="text/javascript"></script>
<!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.pack.js"></script><![endif]-->

Creating a graph with Flot is quite simple because many of the options have sensible default values. This means you can create a good looking graph with minimal work, but can also tweak it to your liking. To make a basic graph, we need to specify a container element and the data to be graphed. The container element also needs to have a specified width and height, so we’ll use jQuery to set the “plotarea” div to have a width of 500px and a height of 250px.

<script language="javascript" type="text/javascript">
$(function() {
	var plotarea = $("#plotarea");
	plotarea.css("height", "250px");
	plotarea.css("width", "500px");
	$.plot( plotarea , data );
});
</script>

The first parameter is a jQuery object of the container element. The second element is a 3-dimensional array where the first child arrays are datasets and the "grandchild" arrays are ordered pairs specifying an X and Y value for a Cartesian plane. Let’s graph the GDP data for the US first.

<script language="javascript" type="text/javascript">
$(function () {
	var data = [ [[2003, 10882],
		[2002, 10383],
		[2001, 10020],
		[2000, 9762],
		[1999, 9213],
		[1998, 8720]] ];
	
	var plotarea = $("#plotarea");
	plotarea.css("height", "250px");
	plotarea.css("width", "500px");
	$.plot( plotarea , data );
});
</script>
Single Graph

The data table we had before should be replaced with a nice look graph. As you can see, the array containing the dataset is contained in another parent array. To graph another dataset, we just add it as another element to the parent array. Let’s add the data for the other countries we had in our table.

var data = [
	[[2003, 10882],
	[2002, 10383],
	[2001, 10020],
	[2000, 9762],
	[1999, 9213],
	[1998, 8720]],
	
	[[2003, 10970],
	[2002, 9040],
	[2001, 8303],
	[2000, 8234],
	[1999, 8901],
	[1998, 8889]],
	
	[[2003, 1795],
	[2002, 1564],
	[2001, 1430],
	[2000, 1438],
	[1999, 1460],
	[1998, 1423]],
	
	[[2003, 1575],
	[2002, 1434],
	[2001, 1345],
	[2000, 1252],
	[1999, 1158],
	[1998, 1148]],
	
	[[2003, 599],
	[2002, 510],
	[2001, 479],
	[2000, 457],
	[1999, 447],
	[1998, 414]]
];
Multi Graph

We now have a fairly good looking graph, but we don’t know which line is which country! What we need is a legend. Fortunately, Flot supports this and is a matter of putting our datasets in a JSON object and adding a label element.

var data = [
	{
		label: "USA",
		data: [[2003, 10882],
			[2002, 10383],
			[2001, 10020],
			[2000, 9762],
			[1999, 9213],
			[1998, 8720]]
	},
	
	{
		label: "EU",
		data: [[2003, 10970],
			[2002, 9040],
			[2001, 8303],
			[2000, 8234],
			[1999, 8901],
			[1998, 8889]]
	},
	
	{
		label: "UK",
		data: [[2003, 1795],
			[2002, 1564],
			[2001, 1430],
			[2000, 1438],
			[1999, 1460],
			[1998, 1423]]
	},
	
	{
		label: "China",
		data: [[2003, 1575],
			[2002, 1434],
			[2001, 1345],
			[2000, 1252],
			[1999, 1158],
			[1998, 1148]]
	},
	
	{
		label: "India",
		data: [[2003, 599],
			[2002, 510],
			[2001, 479],
			[2000, 457],
			[1999, 447],
			[1998, 414]]
	}
];
Graph with Legend

Step 3

I mentioned before that although Flot has many sensible defaults. While they’re probably be fine for most people, the legend partially obscures some of the data. Flot has a third parameter for passing in options in a JSON object.

$.plot( plotarea , data, options );

To make the data at the far end of the graph a little more visible, we’ll adjust the background opacity and margins of the legend.

var options = {
	legend: {
		show: true,
		margin: 10,
		backgroundOpacity: 0.5
	}
};
Options

Some people (like me) like being able to see exactly where the data points are, so let’s specify in the options to mark each point with a circle of a specified radius.

var options = {
	legend: {
		show: true,
		margin: 10,
		backgroundOpacity: 0.5
	},
	points: {
		show: true,
		radius: 3
	}
};
Points

Great, we have data points, but where’d the lines go?! Let’s explicitly turn them back on.

var options = {
	legend: {
		show: true,
		margin: 10,
		backgroundOpacity: 0.5
	},
	points: {
		show: true,
		radius: 3
	},
	lines: {
		show: true
	}
};
Points with Lines

Our final code looks something like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Flot Tutorial</title>

<style type="text/css">
	body { font-family: Arial, Helvetica, sans-serif; }
	table { border-collapse: collapse; }
	td, th { border: 1px solid #222; padding: 5px; }
	
	/* Fix the legend */
	.legend td, .legend th { border: 0; padding: 2px; }
</style>

<script src="jquery.js" language="javascript" type="text/javascript"></script>
<script src="jquery.flot.pack.js" language="javascript" type="text/javascript"></script>
<!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.pack.js"></script><![endif]-->

<script language="javascript" type="text/javascript">
$(function () {
	var data = [
		{
			label: "USA",
			data: [[2003, 10882],
				[2002, 10383],
				[2001, 10020],
				[2000, 9762],
				[1999, 9213],
				[1998, 8720]]
		},
		
		{
			label: "EU",
			data: [[2003, 10970],
				[2002, 9040],
				[2001, 8303],
				[2000, 8234],
				[1999, 8901],
				[1998, 8889]]
		},
		
		{
			label: "UK",
			data: [[2003, 1795],
				[2002, 1564],
				[2001, 1430],
				[2000, 1438],
				[1999, 1460],
				[1998, 1423]]
		},
		
		{
			label: "China",
			data: [[2003, 1575],
				[2002, 1434],
				[2001, 1345],
				[2000, 1252],
				[1999, 1158],
				[1998, 1148]]
		},
		
		{
			label: "India",
			data: [[2003, 599],
				[2002, 510],
				[2001, 479],
				[2000, 457],
				[1999, 447],
				[1998, 414]]
		}
	];
	
	var options = {
		legend: {
			show: true,
			margin: 10,
			backgroundOpacity: 0.5
		},
		points: {
			show: true,
			radius: 3
		},
		lines: {
			show: true
		}
	};
	
	var plotarea = $("#plotarea");
	plotarea.css("height", "250px");
	plotarea.css("width", "500px");
	$.plot( plotarea , data, options );
});
</script>
</head>

<body>

<div id="plotarea">
	<table>
		<caption>GDP, based on exchange rates, over time. Values in billion USDs.</caption>
		<tr>
			<td></td>
			<th scope="col">2003</th>
			<th scope="col">2002</th>
			<th scope="col">2001</th>
			<th scope="col">2000</th>
			<th scope="col">1999</th>
			<th scope="col">1998</th>
		</tr>
		<tr>
			<th scope="row">USA</th>
			<td>10,882</td>
			<td>10,383</td>
			<td>10,020</td>
			<td>9,762</td>
			<td>9,213</td>
			<td>8,720</td>
		</tr>
		<tr>
			<th scope="row">EU</th>
			<td>10,970</td>
			<td>9,040</td>
			<td>8,303</td>
			<td>8,234</td>
			<td>8,901</td>
			<td>8,889</td>
		</tr>
		<tr>
			<th scope="row">UK</th>
			<td>1,765</td>
			<td>1,564</td>
			<td>1,430</td>
			<td>1,438</td>
			<td>1,460</td>
			<td>1,423</td>
		</tr>
		<tr>
			<th scope="row">China</th>
			<td>1,575</td>
			<td>1,434</td>
			<td>1,345</td>
			<td>1,252</td>
			<td>1,158</td>
			<td>1,148</td>
		</tr>
		<tr>
			<th scope="row">India</th>
			<td>599</td>
			<td>510</td>
			<td>479</td>
			<td>457</td>
			<td>447</td>
			<td>414</td>
		</tr>
	</table>
</div>

<p>GDP, based on exchange rates, over time. Values in billion USDs.</p>

</body>
</html>

Concluding Thoughts

There are many possibilities with Flot. The Flot API details all the different options that are available for tweaking your graphs including specifying different graph types, colors, axes, and even enabling interactive features like selection and zooming. Another possibility is to make the entire thing fully dynamic and generate the JavaScript code dynamically with data from a database using PHP.

  • Subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.


Advertisement