id="info"

Developer

A little JavaScript + Google Charts = quick pie charts

See how TechRepublic blogger and self-confessed political junkie Rex Baldazo whips up a CNN-style pie chart using JavaScript and the Google Chart API.

I admit that I'm a bit of a political junkie. The primary reason I have cable TV is so I can watch CNN, Fox, and MSNBC.

Like all political junkies, I was glued to the coverage of the Iowa caucuses this week. CNN kept flashing pie charts to show the relative vote tallies of the various candidates. I just happened to notice last week that Google released a nifty Chart API for public use. As I was watching TV on Thursday night, I thought I'd try whipping up a CNN-style pie chart of my own.

First, you need the chart data. Since these are pie charts, you just need two columns: one for the labels and one for the values. My table has an ID since that is how I plan on accessing it out of the DOM. The HTML looks like this:

<table id="GraphThisTable" cellpadding="2">

<tr>

<td>Candidate</td><td>Delegates</td>

</tr>

<tr>

<td>Obama</td><td>940</td>

</tr>

<tr>

<td>Edwards</td><td>744</td>

</tr>

<tr>

<td>Clinton</td><td>737</td>

</tr>

<tr>

<td>Richardson</td><td>53</td>

</tr>

<tr>

<td>Other</td><td>27</td>

</tr>

</table>

The Google Chart API doesn't accept just any old values; instead, you have to encode the values in a way that the API recognizes. I chose to use its simple encoding because, well, it's simple. It gives you a range from 0 to 61 for each value encoded with letters and numbers. This means you have to normalize your data to that max value of 61 and then encode the normalized value with the appropriate letter or number. For the simple encoding, Google provides a sample JavaScript on how to do this.

This takes care of encoding the data, but now I have to figure out how to extract the data from the table along with the labels, so that each slice of the pie has a proper label to go with it. That's where the unique ID comes into play — I just use the getElementByID method of the document object, like this:

var tbl = document.getElementById("GraphThisTable");

For my table struture, I will assume that the first row always has the headings — the first column is the labels and the second column is the values. We don't pass these labels over to the Google Chart API, but I wanted to use them to generate a heading for my chart. So I have to grab the rows out of the table object I obtained earlier and then pick out the first row and extract the values I want:

var rows = tbl.getElementsByTagName("tr");

var headings = rows[0].getElementsByTagName("td");

var graphedPer = headings[0].innerHTML;

var graphLabel = headings[1].innerHTML;

document.write("<P>" + graphLabel + " per " + graphedPer);

Here is the easy part: You just iterate over the rest of the table, grabbing the labels and values. You also have to determine which value is the maximum because the encoding method from Google requires you pass it an array of values and the max value within that array. After that, it's just a simple matter of generating the proper Google URL and writing it into your document. (I go the lazy route and just use a document.write to embed it into my document.)

Here's the whole thing (which ends up being pretty short), including the snippet from Google:

<script>

var simpleEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

function simpleEncode(values,maxValue) {

var chartData = ['s:'];

for (var i = 0; i < values.length; i++) {

var currentValue = values[i];

if (!isNaN(currentValue) && currentValue >= 0) {

chartData.push(simpleEncoding.charAt(Math.round((simpleEncoding.length-1) * currentValue / maxValue)));

}

else {

chartData.push('_');

}

}

return chartData.join('');

}

var chartBaseUrl = "http://chart.apis.google.com/chart?";

var chartParams = "chs=250x150&cht=p";

var values = "&chd=";

var labels = "&chl=";

var valueArray = new Array();

var max = 1;

var tbl = document.getElementById("GraphThisTable");

var rows = tbl.getElementsByTagName("tr");

var headings = rows[0].getElementsByTagName("td");

var graphedPer = headings[0].innerHTML;

var graphLabel = headings[1].innerHTML;

document.write("<P>" + graphLabel + " per " + graphedPer);

for(i = 1; i < rows.length; i++){

var cols = rows[i].getElementsByTagName("td");

if (i == 1) {

labels = labels + cols[0].innerHTML;

} else {

labels = labels + "|" + cols[0].innerHTML;

}

valueArray[i - 1] = cols[1].innerHTML;

if (cols[1].innerHTML > max)

max = cols[1].innerHTML;

}

values = values + simpleEncode(valueArray,max);

document.write ("<P><img src=" + chartBaseUrl + chartParams + labels + values + ">");

</script>

That's it, easy peasy. I've had trouble getting JavaScript to work in this blog, so I uploaded my working sample to my Web site if you want to see it in action.

Editor's Picks