Hacking Chart.js: A Crash Course in Down-and-Dirty Front End (Part 1)

Reading Time: 6 minutes

What’s going on? I wanted to make clean, elegant, simple charts to represent data about armed conflicts in Africa. I used the Chart.js javascript library to obtain some pretty graphs, but I added functionality to the graphs and then wrote about it here so you can do it, too. This is the first in a series of three posts, and it’s about auto-generating nice-looking legends for line graphs.

Addendum: to see, copy, and run the code itself, you can pull from https://github.com/chelseatroy/acled-data-webclient.

What is Chart.js? Chart.js is a javascript library originally drafted by Nick Downie (available here on GitHub). The library offers relatively quick setup in Javascript for several types of simple and elegant charts so you or I can create visual representations of data in our apps:

Screen Shot 2014-09-11 at 7.17.49 PM

Thank you to Sajal Sarkar for the image: http://www.eolikes.com/jquery/chart-js-simple-html5-charts-plugin

A big thanks to Nick Downie for the library. Without it, this project would have been immensely more painful. I wanted to use those pretty graphs in my app, but I also needed some additional functionality.

I realized this while I was searching for a legend to stick on my line graph. I went digging through the documentation and found a chart option that looked like this:

//String - A legend template
    legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"

What does this do? It makes a bulleted list of the labels of your data. So for this:

Screen Shot 2014-09-11 at 7.35.17 PM

It’s gonna toss back this:

  • Violent Events
  • Fatalities

Ehhh, OK. It sort of does what absolutely has to do. But let’s face it: It’s nowhere near as pretty as the graph itself. Also, it functions by shoving ERB into HTML and delivering the result to a JavaScript object. I wanted a more elegant solution, both for the interface itself and for the code. I ended up with this:

Screen Shot 2014-09-11 at 7.42.31 PM

This was consistent with the light grey rounded boxes I used throughout the app, so it looks even better than this in context :).

Here is what I came up with for this purpose:

1. Inside the script that generates this chart:

First of all, here is the data so you can see where the legend is pulling its colors and strings from:

Screen Shot 2014-09-11 at 7.50.04 PM

I want the labels key inside of each data object to get represented on the legend next to a box that is the color of the line that represents that data object on my chart.

Here’s the string concatenation inside the script (below the data) that gives me the html object I need to insert into my view:

Screen Shot 2014-09-11 at 7.50.43 PM

String concatenation of this nature is never gorgeous, but when I’ve constructed the variable legend, what I have is an unordered list in which each data object will be represented, by its label, next to a box that is colored with the color of the points on the line that represents that data. If I add a data object, say a third line that shows arrests as a function of time or something, and I color its points green, the legend will update automatically when the data changes.

Rubyists: no, Javascript does not have interpolation as you picture it. No, this does not make Javascript “worse” than Ruby. It is different. It lacks some syntactic sugars that Ruby possesses. But it also possesses some syntactic sugars that Ruby lacks (sum ++, anyone?). Recognize, please, that this is just the javascript version of string concatenation syntax. Different from the one you prefer, but not objectively worse.

2. Inside the HTML:

Right beneath the canvas that shows the chart, I defined the legend to represent that same chart. I gave it a class for styling (I’ll show you the styling too), and then I assigned the canvas and the legend to a grid system so they would appear next to each other: the chart on the left, and the legend on the right. That’s what the grid_9 and grid_2 classes do: I have my view split vertically into 12 columns in a grid.css class, and so my canvas will take up 9 of those and my legend will take up 2, leaving 1 left over (one does not have to assign them all, and the view looked less cluttered this way).

Screen Shot 2014-09-11 at 7.51.05 PM

3. Inside the CSS:

What I’ve done here is used a @mixin, which is a characteristic of Sass (think super-CSS). I can define a subset of stylistic things that are common to several styles, and then I can assign them to all of those things. This makes it much easier to separate aesthetics in the CSS from style in the HTML because it’s easy for me to assign new aesthetic characteristics with one line in the CSS, rather than appending 15 classes to everything that I want to have look the same in the app. So, the CSS:

Screen Shot 2014-09-11 at 7.52.42 PM

It gets a slightly rounded corner and a light grey color (#F5F5F5). I actually ripped the color of the box directly from the boxes that appear on GitHub user profiles (thank you, color designer for GitHub!).

The grid CSS, if you find it fascinating:

Screen Shot 2014-09-11 at 8.07.48 PM

Addendum: to see, copy, and run the code itself, you can pull from https://github.com/chelseatroy/acled-data-webclient.

4 comments

    • lksjdf,

      A worse idea is to write a comment in a negative, degrading way, because it discourages people from sharing their knowledge. I hope you become a happier person someday.

  1. I do agree the code in the image makes it a lot harder for one to try on their own. Maybe a fiddler link next time? Also thanks for the info this was what I was looking for.

    • This is how to write a comment on a blog post. Thank you, quickshot. I was new to code blogging when I wrote this post, and I have since made a habit of putting the actual text of my code into my posts :).

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.