Skip to content
July 25, 2010 / phillipsb1

Date and Time based Charts

It’s been a while since my last post (blame work and Call of Duty 4) but I finally have a project that will generate a few dojo posts.  Lately I’ve been working on web application that uses charting, one axis is numeric, and the other contains dates.  Sounds easy right?  Well, it turns out that there was a bit of a learning curve.  This post contains a few hard earned gems that I found while creating it.

When creating a dojo chart, there are a few invisible things going on, and not going on.  When I went through the web looking for charting examples, I found a lot of examples showing how to define a simple series, but not a lot of examples with 2 dimensional data.  Dojo charts need to be configured by adding axis objects to the chart.  It is incredible important that these axis names correspond to the value names in your data.  What do I mean by this?


dojo.addOnLoad(function(){
var chart1 = new dojox.charting.Chart2D("simplechart");
chart1.addPlot("default",
{ type: "Lines" } );
chart1.addAxis("x",{labelFunc:labelfTime});
chart1.addAxis("y", {vertical: true});
chart1.addSeries("Series 1", data.pts);

The above is a code snippet that works pretty well when you have json that looks like this:[{x:1,y:2},{x:2,y:4}]. In some cases, I have managed to get the charting system to fail when using names other than x and y. It seemed to be intuitive that I could have an axis called xd, then set up the json to look like [{xd:1,y:2},{xd:2,y:4}]. It fails under Firefox.  So the first rule of charting safety is AXIS NAMES ARE ALWAYS x OR y.  I’m sure there are caveats to this, but for 2 dimensional charting, stick with the basics.

The next issue is the date itself.  It is tempting to think of a date as something like ‘3/8/2010’, but if you do, you’ve just signed up for trouble.  When dealing with linear displays, the dojo charting system has no idea how to take formatted dates and put them on a chart.  When you are using categories, it’s no problem.  But lines, well, that’s different.  The solution to this issue is to think about a date as a number, not a string.  Javascript Date objects can represent themselves using the date epoch, which is the number of milliseconds since midnight 1 Jan 1970.  If you simply use this epoch date instead of a string, then the charting system can figure out how to draw the line.

Of course, when you do that, you end up with a bunch of huge numbers on your axis for your users to read (in disbelief).  We want to display a human readable date, while plotting the computer readable epoch date.  Luckily, the dojo team have provide a method to do just that.  When an axis is defined for dojo, a function can be assigned to the labelFunc property.  This function accepts a number based on that axis, and returns a label to be displayed.

function labelfTime(o)
{
var dt = new Date();
dt.setTime(o);
var d = (dt.getMonth()+1)+"/"+dt.getDate()+"/"+dt.getFullYear();
return d;
}
chart1.addAxis("x",{labelFunc:labelfTime});

The above code accepts input from the chart based upon the numeric epoch date. It then translates that date into a human readable label, and returns it to the charting system. Now your axis simply places it on the display in the right spot.

Of course, none of this does any good if you are using IE 8 with Dojo 1.4. The label system is buggy under that combination. Labels will not appear, nor will any error messages, leaving you to spend weeks pulling your hair out. Upgrade to dojo 1.5 to fix it and save your sanity.

The source code can be downloaded from here if needed.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: