OdeToCode IC Logo

Revisiting Charts: HTML5 Attributes

Tuesday, February 15, 2011

The charting sample I wrote years ago rendered image tags like this:

<img id="topDestinations" src="roller.gif" />

The roller gif was a spinning animation that let the user know some work was happening behind the scenes. JavaScript loaded into the page had the following responsibilities:

1) Identity the image tags to transform into charts.

2) Call a web service to generate the chart asynchronously.

3) Set the src attribute of each image the to image name returned by the web service call.

Although the Microsoft AJAX libraries made it easy to call WCF services, they didn’t provide much in the way of DOM element selection and manipulation. Thus, the client script was a little heavy.

// <reference name="MicrosoftAjax.js" />

function pageLoad() {

    var context =
    {
        index: 0,
        client: new ChartingService(),
        charts: 
        [
            { id: "topDestinations", builder: "TopDestinations" },
            { id: "taxiTime", builder: "TaxiTime" },
            { id: "dayOfWeek", builder: "DayOfWeek" },
            { id: "delaysByDay", builder: "DelaysByDay" }
        ]
    };

    context.client.GenerateChart(
        context.charts[context.index].builder,
        updateChart,
        displayError,
        context);
}

function updateChart(result, context) {
    var img = $get(context.charts[context.index].id);
    img.src = result;

    context.index++;
    if (context.index < context.charts.length) {
        context.client.GenerateChart(
            context.charts[context.index].builder,
            updateChart,
            displayError,
            context);
    }
}

function displayError() {
    alert("There was an error creating the dashboard charts");
}

It’s New, So It Must Be Better

Ah, what a difference a few years makes (especially when jQuery is involved). I rather like the approach Brad Wilson took to unobtrusive JavaScript in ASP.NET MVC using data- attributes. The MVC charting rewrite uses a similar approach  - it renders img tags using data- attributes to indicate the type of chart it should hold.

     <img data-chart="topdestinations" src="/Content/roller.gif"/>

I rather like the data- approach. It’s more explicit than saying class=”topdestinations” or id=”topdestinations”.

Creating the dashboard one asynchronous chart at a time is also considerably easier (not really because of the data- attribute, but because jQuery makes it easy).

/// <reference path="jquery-1.4.4-vsdoc.js" />

$(function () {

    var charts = $.makeArray($("img[data-chart]")).reverse();
    if (charts) {
        getChart($(charts.pop()));
    }

    function getChart(element) {
        if (element.length) {
            $.get("/chart/generate",
                  { name: element.attr("data-chart") },
                  function (result) {
                      element.attr("src", result);
                      getChart($(charts.pop()));
                  });
        }
    }
});

The rewrite also dropped WCF from the solution, since an MVC controller action can generate a chart and return a string with little effort. Here’s the download for the entire solution.