Using AJAX to load JSON Data for Google Visualization Charts

Truly live web applications are typically data driven. For example, a Facebook wall is a collection of posts, photos, interests and personal data, a Google search result page is a collection of ten URL listings, etc. The data in these pages is independent of the page - it is loaded and usually updated after you request and interact with the page.

In this week's lesson we learn how this technique is accomplished. AJAX is a general term, as well as the name of the JQuery function, that makes a spontaneous HTTP request of a server.

The Exercise

After going through the tutorial and getting the basic page working, there are many ways you can continue to explore AJAX, the data transformation routine of this program, or Google Charts - either exploring the additional options of the GeoChart type or using the States data to create different types of charts. One simple addition would be to allow the user to select which dimension of the states data to map - population, unemployment rate or average income. If you are really ambitious, look for other JSON-based datasets on the internet and use those to map or chart data on your exercise page.

The Tutorial

US Demographic Data by State (April 2013)

Step by Step instructions

Google provides a very simple and well designed set of interactive charts through an online Javascript interface. This code creates and draws a GeoChart, a 'heatmap' of one data dimension overlaying a geographic region. First you need to load the Google Javascript API library to your page. Next you need to load the visualization package with the geochart option. Finally, Google provides its own loader function which you provide a custom function name as the argument. The rest of our code will be in this custom function.

<script type='text/javascript' src='https://www.google.com/jsapi'></script>
...
google.load('visualization', '1', {'packages': ['geochart']});
google.setOnLoadCallback(drawMap);
function drawMap() {
  //   set your data and options 
  var chart = new google.visualization.GeoChart(document.getElementById('chart_div'));
  chart.draw(data, options);
}

I have provided a data set organized as a JSON-like file of US state demographic data. The data is structured as an object containing an array of objects, each object containing several data dimensions for each state.

{"states": 
[{"abbrev":"US-AL","name":"Alabama","unemprate":6.9,"income":41415,"population":4822023,"region":"south"},
{"abbrev":"US-AK","name":"Alaska","unemprate":6.7,"income":67825,"population":731449,"region":"west"},
{"abbrev":"US-AZ","name":"Arizona","unemprate":8.0,"income":46709,"population":6553255,"region":"west"},
...

Setting the options for the chart display is done by creating an object within our function with a set of properties for the options you want to set. In our example, we'll limit the chart to display US region and each state (province) individually.

var options = {region: 'US', resolution: 'provinces'};

The next step is to identify which of the dimensions in our data we want to chart. Store a string value representing one of the dimension properties in our state objects.

var dimension = "population";

Now we are ready to retrieve the data from the JSON file, structure it into the two dimensional array expected by the chart function, and pass the data to the chart.draw function. The JQuery .ajax( ) function initiates an HTTP request to the specified URL in the options object that is its argument. We can chain a JQuery .done( ) function which is essentially an event listener triggered by the HTTP response to the AJAX request. The done function takes a function as its argument ( a callback ). This callback function takes the data that is returned from the AJAX request as its argument.) The rest of our programming (restructuring the data and calling the chart.draw function) is dependent on the data that is returned, so it will be implemented within the done ( ) callback function (in this case an anonymous function.)

$.ajax({
          url: "states.json",
          dataType: "JSON"
        }).done(function(data) {
           ....
        });

First we need to transform the data - create a valid two dimensional array from the JSON object that was returned from states.json. First we declare a new array and provide it with the first element - an array of two headings: state and the dimension. Next we can use the JQuery .each( ) function to map through each state object and push its (this) abbreviation and its value for the appropriate dimension. Note that we can use dot notation to reference the abbreviation because it is a name whereas we need to use bracket notation for the dimension because it is passed as an expression which will evaluate to a name through it's string value.

All that is left is to use Google's library functions to transform that array data to a Chart DataTable, instantiate a new Google GeoChart by passing it the element to draw it in, and call the chart.draw( ) function with the data and the options objects as its two arguments.

Finally, I append the dimension to the title of the chart (an h3 element) for the users information.

        }).done(function(data) {
                var statesArray = [["State",dimension]];
                $.each(data.states, function() {
                    var stateitem = [this.abbrev, this[dimension]];
                    statesArray.push(stateitem);
                });
          var statesData = google.visualization.arrayToDataTable(statesArray);
          var chart = new google.visualization.GeoChart(document.getElementById('chart_div'));
          chart.draw(statesData, options);
          $("h3").append(" Sorted by  "+dimension);
        });

The final Javascript Code

function drawStatesMap() {
        var options = {region: 'US', resolution: 'provinces'};
        var dimension = "population";
        $.ajax({
          url: "states.json",
          dataType: "JSON"
        }).done(function(data) {
                var statesArray = [["State",dimension]];
                $.each(data.states, function() {
                    var stateitem = [this.abbrev, this[dimension]];
                    statesArray.push(stateitem);
                });
          var statesData = google.visualization.arrayToDataTable(statesArray);
          var chart = new google.visualization.GeoChart(document.getElementById('chart_div'));
          chart.draw(statesData, options);
          $("h3").append(" Sorted by  "+dimension);
        });
}
google.load('visualization', '1', {'packages': ['geochart']});
google.setOnLoadCallback(drawStatesMap);