Apps

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.

11 comments
Photogenic Memory
Photogenic Memory

I like what you did with this script! It's cool and I am going to try it out. Thanks for posting. FOX news is a misinformation tool. If you can figure out this script; then find another source of accurate political commentary other than "FUX" news. Thank you.

Justin James
Justin James

Why in the world would I go through this much effort? Obviously, there is some server side code spitting out that table of data. Why not just use of the bazillions of server side charting components to put the chart there? J.Ja

Brett.Blatchley
Brett.Blatchley

Adam, Adam, Adam, you have to sift ALL news and opinion coming from ALL sources. Reflexively dismissing Fox is just as bad as making the New York Times your only news source. I guess we all have our blind spots. :-)

RexWorld
RexWorld

It's always a good thing to hear multiple points of view, even the ones you vehemently disagree with. Though I will say there are some Fox shows I won't watch, like the O'Reilly Factor. On the other hand, there are CNN shows I can't stomach either like the always-angry Nancy Grace. Both of them could use a chill pill.

RexWorld
RexWorld

Justin, you're thinking big automated sites but the Google API is perfect for little Mom-and-Pop web sites where perhaps you do the HTML manually. This way, when you do have to update the data in the HTML table (manually, not from a server app) then the graph that goes with the HTML table will also update automagically.

Tony Hopkinson
Tony Hopkinson

freeing up the server to serve more. This is a good thing, apparently. Can't wait for Jacqui's comments on this theft enhancement.

Photogenic Memory
Photogenic Memory

To somebody; somewhere, in some time period, in a far away galaxy, state, country, town, or remote village on a border to nowhere, Nancy Grace and Bill O'Reilly are gods. I apologize if I have offended thee. How's that saying go?; "If you have hate in your heart; let it out!"? I think those two took it to heart. You're correct. They do need to take a chill-pill. In fact those pills are probably Zanax and heart medication. The human condition can only handle so much stress from stupid behavior.

Tony Hopkinson
Tony Hopkinson

do the graph as an image and update that when you manually update the page. Is about a minute's work for Ma and Pa once it's set up, instead of the client having to draw it every page refresh.

ahin4114
ahin4114

..would you really expect them to write or understand the javascript required to do it for them?

phil
phil

Many clients I deal with would just about be up to changing values in an HTML table (using a WYSIWYG interface), but would have no idea about how to go through the process of turning an excel chart into a web page graphic.

Justin James
Justin James

This really is a case of completely overthinking the issue. If the data is static HTML, they graph it in Excel, hit the "Print Screen" button and paste it into MS Paint, "Save As..." and done. 30 seconds. That's a lot less work than munging your code to make Google like it. J.Ja

Editor's Picks