Picking up where I left off in Part I, I have a JSON data service created. Now I want to create a dashboard to display that data.
Creating a Jade Template
To create the page that holds the dashboard data, I decided to try out the Jade template engine for Node.js. I really dig the slimmed down HTML syntax in Jade. All the normal HTML markup built around opening and closing HTML tags like this:
<ul> <li class="first"> <a href="#">foo</a> </li> <li> <a href="#">bar</a> </li> <li class="last"> <a href="#">baz</a> </li> </ul>
is shortened to this:
ul li.first a(href='#') foo li a(href='#') bar li.last a(href='#') baz
A div with an id of “whatever” is to simply #whatever
. Not bad. Plus it’s got all the usual template engine features like variables, conditionals, iteration, and template includes.
Here is the source code for the Jade template for my dashboard page:
html head script(src='http://documentcloud.github.com/underscore/underscore-min.js') script(src='https://www.google.com/jsapi') script(type='text/javascript') var blsData = !{blsData} script(src='js/googleCharts.js') link(rel='stylesheet', href='css/main.css') body title U.S. Economic Dashboard h1 U.S. Economic Dashboard #unempChart.chart #chart2.chart div.questionMark ? #chart3.chart div.questionMark ? #chart4.chart div.questionMark ?
Pretty simple. There are a few script imports at the top, including the JavaScript utility library Underscore.js and of course the Google API. The one script block for var blsData
shows where I am populating a JavaScript variable with the content of an escaped Jade variable of the same name. I’ll show where this variable is passed to the template in a sec.
The page layout is basic. Four divs, three of which have question marks to represent placeholders for future content. The only div with chart content is unempChart, which will be used by the Google Charts script.
There are a couple changes that need to be made to handle the dashboard page in server.js. First, I need to set up Express to serve my static JavaScript and CSS content. This is done by adding the following two non-route URLs:
// Expose the static resources on two non-route URLs app.use("/js", express.static(__dirname + '/js')); app.use("/css", express.static(__dirname + '/css'));
Next I create the route to the dashboard itself, passing in the unemployment data scraped from the BLS site (as described in Part I):
// Route: GET /dashboard -> Jade template app.get("/dashboard", function(req, res) { retrieveUnemployment(function(unemploymentData) { res.render("index.jade", { blsData : JSON.stringify(unemploymentData) }); }); });
Google Charts
Lastly, there is the JavaScript that creates the Google Chart out of the JSON data and drops it into the div container.
google.load("visualization", "1", { packages : [ "corechart" ] }); google.setOnLoadCallback(drawChart); function drawChart() { var data = new google.visualization.DataTable(); data.addColumn('date', 'Month'); data.addColumn('number', 'Unemployment'); // Parsed blsData var parsedBLSData = []; _.each(blsData, function(blsDataItem) { var parsedBLSDataItem = [ new Date(blsDataItem.year, blsDataItem.month, 1), blsDataItem.rate ]; parsedBLSData.push(parsedBLSDataItem); }, this); data.addRows(parsedBLSData); var options = { title : 'U.S. Unemployment Rate', chartArea : { width : '90%', height : '75%' }, vAxis : { maxValue : 11.0, minValue : 0.0 }, legend : { position : "none" } }; var chart = new google.visualization.LineChart(document .getElementById('unempChart')); chart.draw(data, options); }
I create a google.visualization.DataTable object and populate it with a two-dimensional array, converting the JSON month and year properties into JavaScript date objects as I go. Chart visualization options (of which there are many) are supplied in the options var and a LineChart object is created with the target div id. Calling chart.draw with the converted data and options object displays the chart on the screen.
Next steps
Well, obviously the dashboard needs more charts. One thing it could use is a metric that better controls for the number people who have stopped looking for employment or otherwise dropped out of the labor market. Something like total nonfarm payroll. Then there are other common measures like quarterly GDP changes.
From a technical standpoint, it’s not a great idea to pull the source data with every request for the dashboard. There needs to be a caching mechanism, so the data’s pulled at a more sensible interval (no more than once a day). That might be a good excuse to explore the MongoDB cartridge.
All of the source code is up on Github. Have a look: https://github.com/trevorquinn/econstats