Chapter 3: Integrating Charts on a Page
You might expect a data visualization for the web to be featured very prominently on the page, or even make up the entire web page. That’s not always the right approach, though. The best visualizations are effective because they help the user understand the data, not because they “look pretty” on the page. Some data may be straightforward enough to present without context, but meaningful data probably isn’t. And if our presentation requires context, its visualizations are likely sharing the page with other content. When we design web pages, we should take care to balance any individual component with the page as a whole. If a single visualization is not the entire story, it shouldn’t take up all (or even most) of the space on the page. It can be challenging, however, to minimize the space a traditional chart requires. There are, after all, axes, labels, titles, legends, and more to place.
Edward Tufte considered this problem in his groundbreaking work The Visual Display of Quantitative Information, and he proposed a novel solution he called sparklines. Sparklines are charts stripped to their bare essentials, presented without the aforementioned elements we often see in a chart. Sparklines can present a lot of information in very little space, even to the point where it is possible to include a chart right in the middle of a sentence. There is no need for “See figure below” or “Click for larger view.” One of Tufte’s earliest examples presents the glucose level of a medical patient; figure shows a reproduction.
In a mere 154×20 pixels we’ve shown the patient’s current glucose level, its trend for more than two months, high and low values, and the range of normal values. This high information density makes sparklines effective any time space is a premium—inline in textual paragraphs, as cells in tables, or as part of information dashboards.
Sparklines do have disadvantages of course. They cannot provide as much fine-grained detail as a full-size chart with axes and labels. They also cannot support significant interactivity, so we can’t give users a lot of flexibility in selecting data or zooming in for detail. But for many visualizations, these aren’t major concerns. Plus, as we’ll see in this chapter’s examples, the web gives us the chance to augment sparklines in ways that aren’t possible in print.
There are a few JavaScript libraries and toolkits for creating sparklines, but we’ll focus on the most popular of them: jQuery sparklines. As the name implies, this open source library is an extension to jQuery. The examples in this chapter look closely at how to use these tools to incorporate information dense visualizations into your web page. Here’s what you’ll learn:
- How to create a classic sparkline for integration directly in text
- How to combine multiple sparklines to show comparisons
- How to annotate sparklines with additional details
- How to create composite charts
- How to respond to click events on the page
- How to update our charts in real time
Creating a Classic Sparkline
As later examples will demonstrate, the sparklines library is both flexible and powerful, and we can use it in many different contexts. As a start, though, it seems appropriate to use the library to create a sparkline exactly as Edward Tufte first defined it. The process is quite straightforward and only takes four simple steps.
Step 1: Include the Required JavaScript Libraries
Since we’re using the jQuery sparklines library to create the chart, we need to include that library in our web pages, along with jQuery. Both jQuery and sparklines are available on public content distribution networks (CDNs). For this example (and the others in this chapter), we’ll use the CloudFlare CDN, but for some notes on the advantages and disadvantages of using CDNs, see Chapter 2.
In addition to the jQuery library, sparklines rely on the HTML canvas feature. Since Internet Explorer didn’t support canvas until version 9, we’ll use some special markup in line 9 to ensure that IE 8 and earlier will load an additional library (excanvas.min.js
), just like we did in Chapter 2. Here’s the skeleton with which we start:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
As you can see, we’re including the JavaScript libraries at the end of the document. This approach lets the browser load all of the document’s HTML markup and begin laying out the page while it waits for the server to provide the JavaScript libraries.
Step 2: Create the HTML Markup for the Sparkline
Because we’re closely integrating the sparkline chart with other elements, we simply use a <span>
tag to hold the HTML markup for our visualization, rather than using a <div>
. In addition to the chart itself, we include the final value and a label as standard HTML. Here is the HTML for the glucose sparkline.
1 2 3 4 5 6 7 8 9 10 |
|
Compared to other visualizations, two characteristics of our sparkline chart are unusual.
- We include the data right in the HTML itself, not in the JavaScript that creates the chart.
- The
<span>
for the chart does not have a uniqueid
attribute.
Both of these differences are optional; we could construct the chart as in other visualizations by passing data to a JavaScript function and identifying its container with a unique id
. For sparklines, however, the approach we’re using here often makes more sense. By including the chart data directly in the HTML, we can easily see the data’s relation to other content on the page. It’s clear, for example, that the final value of our chart (128) is the same as the value we’re using for the label. If we had made a mistake and used a different value for the label, the error would be much easier to spot and correct. Using a common class
for all sparklines instead of unique id
s simplifies how we might use the library to create multiple charts on one page. With unique id
s we would have to call a library function for every chart. With a common class
, on the other hand, we need only call a single library function to create multiple charts. That’s especially helpful when a web page contains a lot of sparklines.
Step 3: Draw the Sparkline
Now that we’ve included the necessary libraries and set up our HTML, it’s remarkably easy to draw the charts. In fact, a single line of JavaScript is sufficient. We simply select the containing element(s) using jQuery ($('.sparkline')
) and call the sparklines plugin.
1 2 3 |
|
As you can see in figure , the sparklines library creates a standard sparkline from our data:
The library’s default options don’t quite match Tufte’s classic sparkline definition. The differences include colors, chart type, and density. We’ll tweak those next.
Step 4: Adjust the Chart Style
To make our sparkline match Tufte’s definition exactly, we can specify new values for some of the default options. Let’s collect the changes first, and then see how to pass them to the library.
- Tufte’s classic sparklines are black and white except for key data points (minimum, maximum, and final values). His color scheme adds extra emphasis to those points. To change the library’s default (blue), we can set a
lineColor
. For screen displays we might chose a dark gray rather than pure black. That’s what we’re using in line 2 below. - Tufte doesn’t fill the area below the line so he can use shading to indicate a normal range. To eliminate the library’s light blue shading, we set
fillColor
tofalse
. (Line 3.) - Tufte uses red for key data points. To change the library’s default (orange), we set
spotColor
,minSpotColor
, andmaxSpotColor
in lines 5 through 7. - By default, the library uses three pixels as the width for each data point. To maximize information density, Tufte would likely suggest using only a single pixel. Setting the
defaultPixelsPerValue
option in line 4 makes that change. - Finally, Tufte’s sparklines can include shading to mark the normal range for a value. To show, for example, a range of 82 to 180 mg/dL, we set the
normalRangeMin
andnormalRangeMax
options in lines 8 and 9.
To pass these options to sparklines, we construct a JavaScript object and include it as the second parameter in the sparkline
function call. The function’s first parameter is the data itself, which here we specify with 'html'
because our data is included in the HTML markup.
1 2 3 4 5 6 7 8 9 10 |
|
To complete our transformation to Tufte’s original we can style the HTML content as well. Making the final value the same color as the key data points clarifies that connection, and making the chart label bold emphasizes it as a title.
1 2 3 4 5 6 7 8 9 10 11 |
|
With these changes we have the classic Tufte sparkline on our web page. We can even include it within a text paragraph ( 170,134,115,128,168,166,122,81,56,39,97,114,114,130,151, 184,148,145,134,145,145,145,143,148,224,181,112,111,129, 151,131,131,131,114,112,112,112,124,187,202,200,203,237, 263,221,197,184,185,203,290,330,330,226,113,148,169,148, 78,96,96,96,77,59,22,22,70,110,128 128 Glucose ) so that the visualization enhances the content of the text.
Charting Many Variables
By design, sparklines take up very little space on a page, and that makes them ideal for another visualization challenge: showing many variables at once. Of course regular line charts and bar charts can plot multiple data sets simultaneously; however, these multiple series charts rapidly grow unwieldy if the number of data sets exceeds four or five. Some visualization projects show dozens of different variables, far beyond what a multiple series chart can accommodate. A small multiples approach turns the standard chart approach completely around. Instead of showing one chart with multiple data sets, we can show multiple charts, each with a single data set. Placing lots of charts on a page means that each individual chart cannot take up much space. That is the exactly the problem that sparklines solve.
We won’t go too crazy here to keep the code examples manageable, but it’s easy to extend this approach to many more variables. In our case we’ll construct a visualization for analyzing stock market performance. The companies in our analysis will include the 10 largest American companies in 2012, (the “Fortune 10”), Barclay’s best technology stocks for 2012 (as identified in December 2011), and Bristol-Myers Squibb, which CR Magazine named the top company in America for corporate responsibility. Those selections are completely arbitrary, but the example is designed to include three different cases that we will style differently in our visualization. We’ll treat one as a general case (the Fortune 10 list), one as a special class (the Barclay’s list), and one as a unique variable (Bristol-Myers Squibb).
Just as in this chapter’s first example, we need to include the sparklines and jQuery libraries in our web page.
Step 1: Prepare the HTML Markup
The sparklines library makes it easy to embed the data directly inside the HTML markup. For this example, an HTML table is the most appropriate structure for the data. Here’s how such a table could begin. (For brevity’s sake, the following excerpt doesn’t include the full HTML, but the complete example is available in the book’s source code.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
The table has three important characteristics relevant to our visualization.
- Each stock is a single table row (
<tr>
). - Stocks from Barclay’s Technology list have the class attribute
'barclays'
added to that<tr>
element. - The top Corporate Responsibility stock has no special attributes or characteristics (yet).
Step 2: Draw the Charts
Just as in this chapter’s first example, creating the sparklines using default options is amazingly simple: it only takes a single line of JavaScript. We use jQuery to select all the elements that contain sparkline data, and we call the sparkline()
function to generate the charts. Notice that we only have to make one call to sparkline()
, even though each chart has unique data. That’s a major benefit of placing the data within the HTML itself.
1 2 3 |
|
The resulting charts, shown in figure , all have identical styles, but we’ll fix that in the next few steps.
Symbol | Company | 2012 Performance | Gain |
---|---|---|---|
AAPL | Apple Inc. | 418.68,416.11,416.6,443.34,455.63,489.08,497.7,517.81,540.38,540.37,580.42,590.8,594.27,628.1,599.9,567.94,597.69,560.27,561.72,525.71,557.34,556.05,575.21,569.08,576.98,578.86,600.55,599.64,598.98,580.01,610.28,618.87,645.16,660.2,662.22,677.35,688.14,696.91,664.07,649.62,626.85,607.07,601.25,574.18,547.06,527.68,571.5,585.28,533.25,509.79,519.33,509.59,532.17 | 27% |
ALTR | Altera Corporation | 37.1,36.92,39.93,39.81,40.43,39.76,39.73,38.55,36.89,37.68,39.18,38.47,39.49,37.85,37.17,34.95,35.26,33.4,33.53,33.03,34.21,32.09,33.29,32.86,33.24,33.64,32.54,31.16,31.04,35.82,35.58,37,36.23,36.23,37.21,37.85,38.03,36.62,33.89,33.32,32.22,32.4,30.3,30.41,30.64,30.45,31.86,32.39,31.58,32.86,34.5,34.01,34.39 | (7%) |
BMY | Bristol Meyers Squibb Co. | 32.86,32.46,31.36,31.01,30.98,30.64,31.81,31.31,31.3,31.61,31.87,31.65,32.41,32.67,31.57,33.21,32.32,32.37,32.12,31.74,32.1,32.33,33.34,33.21,34.3,34.88,33.9,34.64,34.69,35.31,31.97,31.07,30.92,31.9,32.33,32.61,32.55,32.92,33.05,33.28,32.73,33.45,33.26,32.82,31.88,31.37,32.27,32.28,32.21,32.38,32.21,31.56,32.24 | (2%) |
BRKA | Berkshire Hathaway Inc. | 114500,116520,119775,119211,119800,117980,119190,120000,117434,119065,122190,122170,121900,121295,118385,118580,120925,121950,122795,119850,119500,119845,122000,123375,122670,124945,123898,126625,125730,127735,128479,127175,128880,128225,126560,129942,133000,134584,132700,135555,132502,133841,129725,130550,127585,129345,132606,131916,131090,133795,134800,133000,134060 | 17% |
COP | ConocoPhillips | 52.95,51.26,51.89,50.58,51.35,52.65,53.95,55.85,57.1,56.74,56.76,56.26,55.9,55.42,54.15,53.59,52.93,51.29,51.61,49.65,50.91,50.01,52.73,54.18,52.18,54.59,53.49,53.71,55.34,54.34,55.07,56.62,56.73,55.71,56.14,55.99,57.54,56.7,56.52,56.92,56.17,57.45,57.31,57.65,55.67,55.03,56.67,56.94,57.94,57.69,58.61,57.07,57.99 | 10% |
CTXS | Citrix Systems, Inc. | 62.02,64.85,68.12,65.14,68.78,71.46,74.77,75.16,75.43,76.27,78.2,77.68,78.91,78.28,75.12,77.78,85.78,82.85,79.46,74.82,75.43,70.79,77.12,80.12,80.14,83.94,77.45,76.63,80.75,77.81,72.44,76.26,78.08,77,77.69,80.59,81.74,81.19,76.53,71.57,67.7,64.16,62.82,62.77,60.17,59.21,61.77,61.16,62.03,65.02,66.15,64.3,65.62 | 6% |
CVX | Chevron Corporation | 104.78,102.63,103.4,100.57,102.06,101.85,103.97,106.33,106.85,106.81,107.5,103.68,104.51,102.11,98.24,99.94,103.52,101.11,100.1,96.84,97.24,94.83,99.18,102.62,98.79,103.77,103.34,104.27,107.4,107.47,109.3,111.69,111.7,111.05,111.2,113.03,116.25,116.79,115.56,116.5,111.11,112.41,110.23,107.44,104.94,102.4,105.47,105.69,106.99,107.82,109.71,106.45,108.14 | 3% |
F | Ford Motor Company | 11.5,11.82,12.36,12.03,12.6,12.26,12.57,12.05,12.54,12.4,12.33,12.14,12.3,12.29,11.75,11.24,11.43,10.56,10.47,9.91,10.49,10.02,10.55,10.24,10.09,9.49,9.4,9.18,9.12,8.91,9.05,9.3,9.58,9.44,9.29,10.09,10.48,10.35,9.81,10.11,10.07,10.13,10.31,11.17,10.93,10.5,11.1,11.45,11.48,11.1,11.86,12.87,12.95 | 13% |
FNMA | Federal National Mortgage Association | 0.2,0.23,0.24,0.23,0.24,0.3,0.38,0.32,0.32,0.32,0.31,0.31,0.29,0.28,0.27,0.29,0.28,0.27,0.3,0.27,0.27,0.26,0.26,0.26,0.26,0.26,0.25,0.24,0.24,0.24,0.24,0.28,0.24,0.25,0.25,0.24,0.28,0.28,0.28,0.28,0.27,0.27,0.27,0.27,0.28,0.27,0.28,0.27,0.27,0.27,0.26,0.26,0.26 | 30% |
GE | General Electric Company | 18.03,18.21,18.51,18.39,18.38,18.25,18.64,18.76,18.5,18.57,19.7,19.29,19.57,19.01,18.41,18.88,19.29,18.86,18.54,18.48,18.72,18.08,18.72,19.5,19.48,20.5,19.67,19.44,19.54,20.57,20.61,20.75,20.65,20.46,20.37,21.23,21.74,22.33,22.5,22.91,22.28,21.83,20.92,21.12,20.81,19.97,20.85,20.94,21.27,21.42,20.88,20.44,20.99 | 16% |
GLW | Corning Incorporated | 13.18,13.64,14.05,12.3,13.23,13.25,13.49,13.4,12.73,13.02,14.04,13.74,13.8,13.27,13.31,12.91,14.16,13.39,13.04,12.49,12.65,12.43,12.94,12.82,12.67,12.74,12.61,12.14,12.09,11.36,11.18,11.4,11.82,11.35,11.89,12.45,13.01,13.11,13.04,13.19,12.88,13.41,11.72,11.61,11.25,10.9,11.29,12.23,12.54,12.62,12.6,12.47,12.62 | (4%) |
GM | General Motors Company | 22.92,24.29,25,24.37,26.18,25.5,27.34,26.07,26.45,25.62,25.57,25.17,25.65,24.81,23.8,23.6,23.53,22.36,22,21.18,22.44,22.01,22.05,21.74,20.6,19.72,20.31,19.62,19.36,19.67,20.04,20.54,22.01,21.18,21.35,23.37,24.14,24.8,22.75,24.8,24.44,24.59,23.28,25.79,25.04,23.85,25.21,25.88,25.19,24.61,27.32,27.85,28.83 | 26% |
HPQ | Hewlett-Packard Company | 25.67,25.76,27.35,27.11,28.27,27.91,28.77,25.9,24.62,23.51,23.93,23.09,23.29,22.58,24.01,23.95,24.19,23.72,22.62,20.97,21.82,20.77,21.8,21.27,20.02,19.77,19.24,18.66,18.29,18.25,17.95,19.37,19.19,17.28,16.59,17.12,18,17.42,16.9,14.59,14.27,14.34,13.96,13.63,13.48,12.73,12.32,12.87,13.81,14.75,14.34,13.68,14.25 | (44%) |
QCOM | QUALCOMM, Inc. | 55.28,55.65,56.83,56.88,60.1,60.76,61.54,62.45,61.66,63.14,64.61,65.86,67.22,66.36,65.85,61.49,63.39,61.15,61.1,55.29,56.62,54.68,58.29,56.05,55.19,55.23,54.87,54.54,57.22,58.86,59.76,61.48,62.78,61.93,60.97,61.69,64.62,64.02,62.22,62.39,58.66,58.52,58.81,59.07,61.38,61.69,62.88,63.37,63.86,59.83,61.61,60.64,61.86 | 12% |
TER | Teradyne, Inc. | 14.63,14.84,16.14,16.95,17.03,16.5,17.01,16.38,16.11,16.21,17.05,16.82,16.89,16.42,16.29,16.3,17.39,16.13,15.71,14.32,14.79,13.61,14.38,14.46,14.31,14.06,13.67,13.21,13.64,14.97,14.8,15.59,15.94,15.74,15.62,16.28,16.43,14.6,14.22,14.07,13.62,14.12,14.5,15.31,15.51,15.03,15.93,15.64,15.84,16.49,16.75,16.42,16.89 | 15% |
TSLA | Tesla Motors Inc | 26.91,22.79,26.6,29.33,31.15,31.1,34.97,33.75,34.04,34.74,35.32,34.08,37.24,34.48,33.59,33.16,33.34,31.83,32.25,27.56,29.81,28.15,30.08,29.91,33.79,31.29,30.99,34.25,31.79,29.51,27.27,29.94,30.01,29.5,28.52,29.35,30.39,30.02,29.28,28.89,27.64,27.74,27.38,28.92,30.32,31.84,32.13,33.82,34.17,33.81,34,33.22,33.87 | 26% |
WMT | Wal-Mart Stores, Inc. | 57.58,58.11,59.54,59.25,60.54,60.41,60.98,57.38,57.59,59.03,59.77,59.68,60.13,59.61,58.72,61.35,57.99,57.67,58.77,61.75,64.6,64.84,67.48,67.01,66.57,68.96,70.58,72.38,71.46,73.71,73.74,73.27,71.59,71.71,72.2,73.41,74.09,74.04,73.39,74.72,75.39,75.2,74.7,72.37,71.91,67.65,69.81,71.62,72.29,68.75,68.65,67.61,68.23 | 18% |
XOM | Exxon Mobil Corporation | 83.01,82.78,85.33,83.71,82.82,82.17,83.96,85.65,84.66,82.67,84.76,83.89,85.05,83.17,81.34,83.65,84.41,82.93,82.05,80.44,81.04,76.94,79.82,82.17,81.07,84.49,83.73,84.39,84.86,86.34,86.44,87.89,87.85,87.5,86.76,89.36,91.73,91.35,90.88,91.97,90.46,91.58,90.06,89.71,87.21,86.45,89.09,88.14,88.6,88.08,87.23,85.1,86.55 | 4% |
Step 3: Establish a Default Style for the Charts
If we don’t like the sparklines library’s default style, it’s easy to change it using an options object, as shown next. The object is the second parameter to the sparkline()
function, and here it changes the color for the charts and disables the highlights on the minimum, maximum, and final values. The first parameter, the string 'html'
, indicates to the library that the data is already present in our HTML.
1 2 3 4 5 6 7 |
|
Figure shows the result for one row. We’ll use this style as the default for all our charts.
Symbol | Company | 2012 Performance | Gain |
---|---|---|---|
AAPL | Apple Inc. | 418.68,416.11,416.6,443.34,455.63,489.08,497.7,517.81,540.38,540.37,580.42,590.8,594.27,628.1,599.9,567.94,597.69,560.27,561.72,525.71,557.34,556.05,575.21,569.08,576.98,578.86,600.55,599.64,598.98,580.01,610.28,618.87,645.16,660.2,662.22,677.35,688.14,696.91,664.07,649.62,626.85,607.07,601.25,574.18,547.06,527.68,571.5,585.28,533.25,509.79,519.33,509.59,532.17 | 27% |
Step 4: Modify the Default Style for Special Classes
With a default style in place, we can turn our attention to the special class of charts for stocks in Barclay’s technology list. For our example, let’s change the color of the chart without any other changes to our default style. That final clause is important. We could just copy-and-paste the options, but that would be setting ourselves up for problems in the future. You can see why in the following example code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Notice that the second call to sparklines()
duplicates options from the first call that haven’t changed, specifically for the spot colors. This makes the code harder to maintain if, in the future, we decide to turn spot colors back on for all our charts, since we would have to make changes to our code in two places. There is a better way.
To avoid duplication we first define a variable that holds our default options.
1 2 3 4 5 6 7 |
|
Next we create a new variable for the Barclay’s styles. To create this new variable, we can use the jQuery .extend()
function to avoid duplication. In the following code, we pass three parameters to .extend()
. The first parameter is the target. It’s an object that the function will modify, and we start with an empty object ({}
). The next parameters are objects that .extend()
will merge into the target. The merge process adds new properties to the target and updates any properties in the target object with new values. Since we’re passing two additional parameters, we’re asking for two merges.
1 2 3 4 |
|
You can think of the call to .extend()
as a two-stage process.
- Since our target is initially empty, the first merge will add all of the properties from
sparkline_default
to the target. - Our target now has the same properties as
sparkline_default
, and the second merge will modify it by updating the two properties in the last parameter,lineColor
andfillColor
.
The resulting object will hold the options we want for charts of Barclay’s technology stocks. Here’s a complete code listing, using these objects to create the charts.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Notice in line 12 that we create the non-technology sparklines by selecting table rows (<tr>
) that don’t have the "barclays"
class. In line 13 we create the technology sparklines. Because we’ve defined the technology options based on the default, we have an easy way to maintain both default styles and styles for special classes. The chart colors in figure
Symbol | Company | 2012 Performance | Gain |
---|---|---|---|
TSLA | Tesla Motors Inc | 26.91,22.79,26.6,29.33,31.15,31.1,34.97,33.75,34.04,34.74,35.32,34.08,37.24,34.48,33.59,33.16,33.34,31.83,32.25,27.56,29.81,28.15,30.08,29.91,33.79,31.29,30.99,34.25,31.79,29.51,27.27,29.94,30.01,29.5,28.52,29.35,30.39,30.02,29.28,28.89,27.64,27.74,27.38,28.92,30.32,31.84,32.13,33.82,34.17,33.81,34,33.22,33.87 | 26% |
WMT | Wal-Mart Stores, Inc. | 57.58,58.11,59.54,59.25,60.54,60.41,60.98,57.38,57.59,59.03,59.77,59.68,60.13,59.61,58.72,61.35,57.99,57.67,58.77,61.75,64.6,64.84,67.48,67.01,66.57,68.96,70.58,72.38,71.46,73.71,73.74,73.27,71.59,71.71,72.2,73.41,74.09,74.04,73.39,74.72,75.39,75.2,74.7,72.37,71.91,67.65,69.81,71.62,72.29,68.75,68.65,67.61,68.23 | 18% |
Step 5: Create a Unique Style for a Specific Chart
For the final step in this example, let’s consider the single stock at the top of CR Magazine’s list. Suppose we want to add distinct styles to its chart, and we know those styles only when we’re generating the HTML, not when we’re writing the JavaScript. How can we adjust the chart style if we can’t modify any JavaScript?
Sparklines let you add special attributes directly to the HTML element containing a chart. To set the line color, for example, you need to specify the attribute sparkLineColor
. The problem is that if we were to enter this attribute directly in the HTML, the result would’t be valid HTML, because the HTML specification doesn’t recognize the sparkLineColor
attribute. To conform to the HTML standard, custom attributes must have names that begin with the prefix data-
.
To use HTML-compliant names to refer to sparklines’ custom attributes, we just need to tell the sparklines library how to find those names. For our HTML, we use the standard data-
prefix instead of spark
in line 4.
1 2 3 4 5 6 7 8 |
|
Now we have to add a couple more options in our call to sparkline()
. First we set enableTagOptions
to true to tell the library that we’re including options directly in the HTML. Then we set tagOptionsPrefix
to "data-"
to specify the specific prefix we’re using for those attributes.
Note: As of this writing, the jQuery sparklines documentation for
tagOptionsPrefix
is not correct. The documentation lists the option astagOptionPrefix
, where “option” is singular instead of plural. The library’s code, however, expects the plural form.
If we use these options correctly, one of our charts will have the distinct color in figure .
BMY | Bristol Meyers Squibb Co. | 32.86,32.46,31.36,31.01,30.98,30.64,31.81,31.31,31.3,31.61,31.87,31.65,32.41,32.67,31.57,33.21,32.32,32.37,32.12,31.74,32.1,32.33,33.34,33.21,34.3,34.88,33.9,34.64,34.69,35.31,31.97,31.07,30.92,31.9,32.33,32.61,32.55,32.92,33.05,33.28,32.73,33.45,33.26,32.82,31.88,31.37,32.27,32.28,32.21,32.38,32.21,31.56,32.24 | (2%) |
To pass the appropriate options to sparkline()
we can take advantage of the work we did in step 5. Since we created a special object for default options, that’s the only object we have to change.
1 2 3 4 5 6 7 8 9 |
|
We only need to make the change in one place, and all of our calls to sparkline()
use the new options. Here is the final, complete JavaScript code for this example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
And figure shows the final result. We have a table that integrates text and charts, and we can style those charts appropriately and efficiently for the default case, for a special class, and for a unique value.
Symbol | Company | 2012 Performance | Gain |
---|---|---|---|
AAPL | Apple Inc. | 418.68,416.11,416.6,443.34,455.63,489.08,497.7,517.81,540.38,540.37,580.42,590.8,594.27,628.1,599.9,567.94,597.69,560.27,561.72,525.71,557.34,556.05,575.21,569.08,576.98,578.86,600.55,599.64,598.98,580.01,610.28,618.87,645.16,660.2,662.22,677.35,688.14,696.91,664.07,649.62,626.85,607.07,601.25,574.18,547.06,527.68,571.5,585.28,533.25,509.79,519.33,509.59,532.17 | 27% |
ALTR | Altera Corporation | 37.1,36.92,39.93,39.81,40.43,39.76,39.73,38.55,36.89,37.68,39.18,38.47,39.49,37.85,37.17,34.95,35.26,33.4,33.53,33.03,34.21,32.09,33.29,32.86,33.24,33.64,32.54,31.16,31.04,35.82,35.58,37,36.23,36.23,37.21,37.85,38.03,36.62,33.89,33.32,32.22,32.4,30.3,30.41,30.64,30.45,31.86,32.39,31.58,32.86,34.5,34.01,34.39 | (7%) |
BMY | Bristol Meyers Squibb Co. | 32.86,32.46,31.36,31.01,30.98,30.64,31.81,31.31,31.3,31.61,31.87,31.65,32.41,32.67,31.57,33.21,32.32,32.37,32.12,31.74,32.1,32.33,33.34,33.21,34.3,34.88,33.9,34.64,34.69,35.31,31.97,31.07,30.92,31.9,32.33,32.61,32.55,32.92,33.05,33.28,32.73,33.45,33.26,32.82,31.88,31.37,32.27,32.28,32.21,32.38,32.21,31.56,32.24 | (2%) |
BRKA | Berkshire Hathaway Inc. | 114500,116520,119775,119211,119800,117980,119190,120000,117434,119065,122190,122170,121900,121295,118385,118580,120925,121950,122795,119850,119500,119845,122000,123375,122670,124945,123898,126625,125730,127735,128479,127175,128880,128225,126560,129942,133000,134584,132700,135555,132502,133841,129725,130550,127585,129345,132606,131916,131090,133795,134800,133000,134060 | 17% |
COP | ConocoPhillips | 52.95,51.26,51.89,50.58,51.35,52.65,53.95,55.85,57.1,56.74,56.76,56.26,55.9,55.42,54.15,53.59,52.93,51.29,51.61,49.65,50.91,50.01,52.73,54.18,52.18,54.59,53.49,53.71,55.34,54.34,55.07,56.62,56.73,55.71,56.14,55.99,57.54,56.7,56.52,56.92,56.17,57.45,57.31,57.65,55.67,55.03,56.67,56.94,57.94,57.69,58.61,57.07,57.99 | 10% |
CTXS | Citrix Systems, Inc. | 62.02,64.85,68.12,65.14,68.78,71.46,74.77,75.16,75.43,76.27,78.2,77.68,78.91,78.28,75.12,77.78,85.78,82.85,79.46,74.82,75.43,70.79,77.12,80.12,80.14,83.94,77.45,76.63,80.75,77.81,72.44,76.26,78.08,77,77.69,80.59,81.74,81.19,76.53,71.57,67.7,64.16,62.82,62.77,60.17,59.21,61.77,61.16,62.03,65.02,66.15,64.3,65.62 | 6% |
CVX | Chevron Corporation | 104.78,102.63,103.4,100.57,102.06,101.85,103.97,106.33,106.85,106.81,107.5,103.68,104.51,102.11,98.24,99.94,103.52,101.11,100.1,96.84,97.24,94.83,99.18,102.62,98.79,103.77,103.34,104.27,107.4,107.47,109.3,111.69,111.7,111.05,111.2,113.03,116.25,116.79,115.56,116.5,111.11,112.41,110.23,107.44,104.94,102.4,105.47,105.69,106.99,107.82,109.71,106.45,108.14 | 3% |
F | Ford Motor Company | 11.5,11.82,12.36,12.03,12.6,12.26,12.57,12.05,12.54,12.4,12.33,12.14,12.3,12.29,11.75,11.24,11.43,10.56,10.47,9.91,10.49,10.02,10.55,10.24,10.09,9.49,9.4,9.18,9.12,8.91,9.05,9.3,9.58,9.44,9.29,10.09,10.48,10.35,9.81,10.11,10.07,10.13,10.31,11.17,10.93,10.5,11.1,11.45,11.48,11.1,11.86,12.87,12.95 | 13% |
FNMA | Federal National Mortgage Association | 0.2,0.23,0.24,0.23,0.24,0.3,0.38,0.32,0.32,0.32,0.31,0.31,0.29,0.28,0.27,0.29,0.28,0.27,0.3,0.27,0.27,0.26,0.26,0.26,0.26,0.26,0.25,0.24,0.24,0.24,0.24,0.28,0.24,0.25,0.25,0.24,0.28,0.28,0.28,0.28,0.27,0.27,0.27,0.27,0.28,0.27,0.28,0.27,0.27,0.27,0.26,0.26,0.26 | 30% |
GE | General Electric Company | 18.03,18.21,18.51,18.39,18.38,18.25,18.64,18.76,18.5,18.57,19.7,19.29,19.57,19.01,18.41,18.88,19.29,18.86,18.54,18.48,18.72,18.08,18.72,19.5,19.48,20.5,19.67,19.44,19.54,20.57,20.61,20.75,20.65,20.46,20.37,21.23,21.74,22.33,22.5,22.91,22.28,21.83,20.92,21.12,20.81,19.97,20.85,20.94,21.27,21.42,20.88,20.44,20.99 | 16% |
GLW | Corning Incorporated | 13.18,13.64,14.05,12.3,13.23,13.25,13.49,13.4,12.73,13.02,14.04,13.74,13.8,13.27,13.31,12.91,14.16,13.39,13.04,12.49,12.65,12.43,12.94,12.82,12.67,12.74,12.61,12.14,12.09,11.36,11.18,11.4,11.82,11.35,11.89,12.45,13.01,13.11,13.04,13.19,12.88,13.41,11.72,11.61,11.25,10.9,11.29,12.23,12.54,12.62,12.6,12.47,12.62 | (4%) |
GM | General Motors Company | 22.92,24.29,25,24.37,26.18,25.5,27.34,26.07,26.45,25.62,25.57,25.17,25.65,24.81,23.8,23.6,23.53,22.36,22,21.18,22.44,22.01,22.05,21.74,20.6,19.72,20.31,19.62,19.36,19.67,20.04,20.54,22.01,21.18,21.35,23.37,24.14,24.8,22.75,24.8,24.44,24.59,23.28,25.79,25.04,23.85,25.21,25.88,25.19,24.61,27.32,27.85,28.83 | 26% |
HPQ | Hewlett-Packard Company | 25.67,25.76,27.35,27.11,28.27,27.91,28.77,25.9,24.62,23.51,23.93,23.09,23.29,22.58,24.01,23.95,24.19,23.72,22.62,20.97,21.82,20.77,21.8,21.27,20.02,19.77,19.24,18.66,18.29,18.25,17.95,19.37,19.19,17.28,16.59,17.12,18,17.42,16.9,14.59,14.27,14.34,13.96,13.63,13.48,12.73,12.32,12.87,13.81,14.75,14.34,13.68,14.25 | (44%) |
QCOM | QUALCOMM, Inc. | 55.28,55.65,56.83,56.88,60.1,60.76,61.54,62.45,61.66,63.14,64.61,65.86,67.22,66.36,65.85,61.49,63.39,61.15,61.1,55.29,56.62,54.68,58.29,56.05,55.19,55.23,54.87,54.54,57.22,58.86,59.76,61.48,62.78,61.93,60.97,61.69,64.62,64.02,62.22,62.39,58.66,58.52,58.81,59.07,61.38,61.69,62.88,63.37,63.86,59.83,61.61,60.64,61.86 | 12% |
TER | Teradyne, Inc. | 14.63,14.84,16.14,16.95,17.03,16.5,17.01,16.38,16.11,16.21,17.05,16.82,16.89,16.42,16.29,16.3,17.39,16.13,15.71,14.32,14.79,13.61,14.38,14.46,14.31,14.06,13.67,13.21,13.64,14.97,14.8,15.59,15.94,15.74,15.62,16.28,16.43,14.6,14.22,14.07,13.62,14.12,14.5,15.31,15.51,15.03,15.93,15.64,15.84,16.49,16.75,16.42,16.89 | 15% |
TSLA | Tesla Motors Inc | 26.91,22.79,26.6,29.33,31.15,31.1,34.97,33.75,34.04,34.74,35.32,34.08,37.24,34.48,33.59,33.16,33.34,31.83,32.25,27.56,29.81,28.15,30.08,29.91,33.79,31.29,30.99,34.25,31.79,29.51,27.27,29.94,30.01,29.5,28.52,29.35,30.39,30.02,29.28,28.89,27.64,27.74,27.38,28.92,30.32,31.84,32.13,33.82,34.17,33.81,34,33.22,33.87 | 26% |
WMT | Wal-Mart Stores, Inc. | 57.58,58.11,59.54,59.25,60.54,60.41,60.98,57.38,57.59,59.03,59.77,59.68,60.13,59.61,58.72,61.35,57.99,57.67,58.77,61.75,64.6,64.84,67.48,67.01,66.57,68.96,70.58,72.38,71.46,73.71,73.74,73.27,71.59,71.71,72.2,73.41,74.09,74.04,73.39,74.72,75.39,75.2,74.7,72.37,71.91,67.65,69.81,71.62,72.29,68.75,68.65,67.61,68.23 | 18% |
XOM | Exxon Mobil Corporation | 83.01,82.78,85.33,83.71,82.82,82.17,83.96,85.65,84.66,82.67,84.76,83.89,85.05,83.17,81.34,83.65,84.41,82.93,82.05,80.44,81.04,76.94,79.82,82.17,81.07,84.49,83.73,84.39,84.86,86.34,86.44,87.89,87.85,87.5,86.76,89.36,91.73,91.35,90.88,91.97,90.46,91.58,90.06,89.71,87.21,86.45,89.09,88.14,88.6,88.08,87.23,85.1,86.55 | 4% |
The third example in chapter 2 uses a full-featured charting package for a similar result. If you don’t need the space efficiency of sparklines, consider that approach as an alternative.
Annotating Sparklines
Because they’re designed to maximize information density, sparklines omit many traditional chart components such as axes and labels. This approach certainly focuses on the data itself, but it can sometimes leave users without enough context to understand the data. Print versions usually rely on traditional text to supply this context, but on the web we have more flexibility. We can present the data by itself in a sparkline, and we can give users the chance to explore the data’s context through interactions.
Tooltips, which show additional information as users hover their mouse pointers over sections of a web page, can be an effective way to annotate a sparkline, so long as the users are accessing the page from a desktop computer. (Touch-based devices such as smartphones and tablets don’t typically support the concept of hover.) We’ll walk through a visualization that includes tooltips in this example; other examples in the chapter consider alternative approaches that may be more effective for touch devices.
Let’s see how we can use a customized form of tooltips by enhancing the charts in the previous example.
Just as in this chapter’s first example, we need to include the sparklines and jQuery libraries in our web page.
Step 1: Prepare the Data
In the previous examples we’ve embedded the data directly in the HTML markup. That’s convenient since it lets us separate the data from our code. In this example, however, the JavaScript code will need more detailed knowledge of the data so it can present the right tooltip information. This time we’ll use a JavaScript array to store our data, so that all the relevant information is in one place. For this example we can focus on a single stock. And even though we’re graphing only the adjusted closing price, the array will track additional data that we can include in the tooltips. Here’s an excerpt of the data for one of the stocks.
1 2 3 4 5 6 7 8 |
|
Step 2: Prepare the HTML Markup
Our visualization will include three distinct areas, each in a <div>
element. The primary <div>
created in line 3 will hold the chart. Underneath the chart we’ll add the primary tool tip information in its own <div>
(line 4), and we’ll include supplementary details to the right (line 7). The following example uses inline styles for clarity; a production site might prefer to use CSS style sheets.
1 2 3 4 5 6 7 8 9 |
|
Step 3: Add the Chart
Adding the chart to our markup is easy with the sparklines library. We can use the jQuery .map()
function to extract the adjusted close value from our stock
array. The minSpotColor
and maxSpotColor
options tell the library how to highlight the lowest and highest values for the year.
1 2 3 4 5 6 7 8 9 10 |
|
The static chart of figure shows the stock performance nicely.
Step 4: Add the Primary Annotation
The sparklines library adds a simple tooltip to all of its charts by default. Although that tooltip shows the value over which the user’s mouse is hovering, the presentation isn’t particularly elegant, and, more importantly, it doesn’t provide as much information as we would like. Let’s enhance the default behavior to meet our needs.
Looking at the library’s defaults, we can retain the vertical marker, but we don’t want the default tooltip. Adding the option disableTooltips
with a value of true
will turn off the undesired tooltip.
For our own custom tooltip, we can rely on a handy feature of the sparklines library. The library generates a custom event whenever the user’s mouse moves over a chart region. That event is the "sparklineRegionChange"
event. The library attaches a custom property, sparklines
, to those events. By analyzing that property we can determine the mouse’s location relative to the data.
1 2 3 4 5 6 |
|
As the comment in lines 4 and 5 indicate, the library sometimes generates the event when the mouse leaves the chart area. In those cases a defined value for the offset will not exist.
Once we have the mouse position, we can place our tooltip information in the <div>
we set aside for it. We get the information in lines 3 and 5 from the stock
array using the index value from the sparklineRegionChange
event.
1 2 3 4 5 6 |
|
The sparklines library isn’t completely reliable in generating events when the mouse leaves the chart area. Instead of using the custom event, therefore, we can use the standard JavaScript mouseout
event. When the user moves the mouse off the chart, we’ll turn off the custom tooltip by setting it’s content to a blank space. We use the HTML non-breaking space (
) so the browser doesn’t think the <div>
is completely empty. If we used a standard space character, the browser would treat the <div>
as empty and recalculate the height of the page, causing an annoying jump in the page contents. (For the same reason we should initialize that <div>
with
instead of leaving it blank.)
1 2 3 |
|
For the cleanest implementation, we combine all of these steps using method chaining. (To keep it concise, the excerpt below omits the chart styling options.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Now with figure we have a nice, interactive tooltip that tracks the user’s mouse as it moves across the chart.
Step 5: Provide Additional Information
The tooltip information we’ve added so far shows the immediately relevant information to the user: the week and the adjusted closing price of the stock. Our data, however, contains additional information that might be useful to the user. We can expand on the original tooltip by displaying that information as well.
At the same time we update the primary tooltip region, let’s add the extra data.
1 2 3 4 5 6 |
|
When we clear the primary tooltip region, we’ll clear this area as well.
1 |
|
Because it won’t affect the vertical size of the page, we don’t need to fill this <div>
with a dummy
.
With figure we have the visualization we want. The chart clearly shows the overall trend for the stock during the year, but it takes up only a small amount of space on the web page. At first glance the chart is also free of distracting elements such as labels and axes. For users who just want a general sense of the stock’s performance, those elements are superfluous. Users who want the full details need only hover their mouse over the chart and it reveals the complete market information.
Because we’ve managed to display the information while retaining the compact nature of sparklines, the technique in this example works well when combined with the small multiples approach of this chapter’s second example.
The next example includes an alternate method for showing the extra details.
Drawing Composite Charts
So far in this chapter we’ve seen how sparklines can provide a lot of visual information in a very small space. That characteristic makes them perfect for integrating charts in a complete web page that includes text, tables, and other elements. We haven’t yet exhausted the capabilities of sparklines, however. We can increase the information density of our visualizations still further by creating composite charts—in effect, drawing multiple charts in the same space.
To see an example of this technique, we can build on the previous example. In that example we used a sparkline to show the closing price of a stock over an entire year. Price is indeed the most relevant data about a stock, but there’s another quantity that many investors like to see: the stock’s trading volume. And just as with price, it can be important to understand the trend for trading volume at a glance. That makes the value an excellent candidate for a chart.
Just as in this chapter’s first example, we need to include the sparklines and jQuery libraries in our web page. Because we’re visualizing the same data as in the previous example, we’ll also want to set up the data array and the HTML markup exactly as in that example.
Step 1: Draw the Trading Volume Chart
Even though we’re including a chart of trading volume, the most important quantity is the stock price. To keep the emphasis on stock price, we want to draw that chart on top of the chart for trading volume. That means we need to draw the trading volume chart first.
The code for trading volume is very similar to the stock price from the previous example. Instead of an area chart, however, we’ll use a bar chart. We use the jQuery .map()
function to extract the volume
property from our data array. Setting the type
option to "bar"
in line 3 is all it takes to tell the sparklines library to create a bar chart.
1 2 3 4 |
|
Figure shows the results.
Step 2: Add the Closing Price Chart
To add the price chart on top of the volume chart, we can call the sparklines library once again. We give it the same containing element and, most importantly, set the composite
option to true
in line 10. This parameter tells the library not to erase any existing chart in the element but to simply draw over it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Notice the way we specify the fill color for the second chart. We set a transparency (or alpha) value of 0.3. This value makes the chart area nearly transparent, so the volume chart will show through. Note, though, that some older web browsers, notably Internet Explorer version 8 and earlier, do not support the transparency standard. If your site has a significant number of users with those browsers, you might consider simply setting the fillColor
option to false
, which will disable filling the area entirely.
As figure shows, the result combines both charts in the same space.
Step 3: Add the Annotations
We can add annotations to the chart using the same approach as in the previous example. Because our charts now include the trading volume, it’s appropriate to move that value from the details area into the primary annotation <div>
. The code to do that is a simple adjustment from the prior example.
In addition to moving the text from one area to the other, we make two significant changes.
We get the
idx
value from the second element of the event’ssparklines
array (sparklines[1]
) in line 2. That’s because the first element of that array is the first chart. The sparklines library doesn’t really return any useful information about bar charts in thesparklineRegionChange
event. Fortunately, we can get all the information we need from the line chart.We show the trading volume in millions, rounded to two decimal places. The calculation is in line 8. It’s much easier for our users to quickly grasp “24.4M” than “24402100.”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
As in the previous example, the annotations in our chart (shown in figure ) provide additional details.
Step 4: Show Details as a Chart
So far we’ve shown the additional details for the stock (open, close, high, and low) as text values. As long as we’re drawing multiple charts, we can show those values graphically as well. The statistical box plot serves as a useful model for us. Traditionally, that plot type shows the range of a distribution, including deviations, quartiles, and medians. Visually, however, it provides a perfect model of a stock’s trading performance. We can use it to show the opening and closing prices, as well as the high and low values during the period.
The sparklines library can draw a box plot for us, but normally it calculates the values to display given the distribution as input data. In our case we don’t want to use the standard statistical calculations. Instead, we can use an option that tells the library to use pre-computed values. The library expects at least five values:
- The lowest sample value
- The first quartile
- The median
- The third quartile
- The highest sample value
For our example, we’ll provide the following values instead:
- The lowest price
- Whichever is less of the opening and closing prices
- The adjusted closing price
- Whichever is greater of the opening and closing prices
- The highest price
We’ll also color the median bar red or green depending on whether the stock gained or lost value during the period.
Here’s the code that creates that chart in response to the sparklineRegionChange
event. The data for the chart (lines 3-7) is simply the five values extracted from the stock data for the appropriate week. As lines 11 and 12 demonstrate, we can change the color of the median bar depending on whether the stock finished higher or lower for the day.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
When the mouse leaves the chart region, we can remove the box plot by emptying its container.
1 |
|
Now as our users mouse over the chart area, they can see a visual representation of the stock’s price range during each period.
Responding to Click Events
Throughout this chapter we’ve looked at how to include a lot of visual information in a small space, making it easier to integrate a visualization within a web page. The basic sparkline by itself is very efficient, and previous examples have added annotations and composites to increase the information density further. Sometimes, however, there’s just no way to fit all the possible data in a small enough space. Even in these cases, though, the interactive nature of the web can help us out. Our web page can start with a compact visualization but expand to a different view—one with richer details—with a simple click or tap.
Indeed, the compact quality of sparklines seems to invite interaction. In every usability test I’ve performed that included sparklines on a web page, the participants invariably clicked on the chart. That was true even when there were no other details that the page could provide and the participants had no idea what to expect in response to their clicks. They clicked just to see what happens.
This example continues our stock market example. We’ll begin with the same basic stock price chart we’ve seen before, but enhance it to provide details when users click on the chart region.
Just as in this chapter’s first example, we need to include the sparklines and jQuery libraries in our web page. Because we’re visualizing the same data as in the previous example, we’ll also want to set up the data array exactly as in that example. The HTML markup, however, can be much simpler. All we need is a simple <div>
to hold the chart.
1 |
|
Step 1: Add the Chart
Adding the chart to our markup is easy with the sparklines library. We can use the jQuery .map()
function to extract the adjusted close value from our stock
array.
1 |
|
The static chart of figure , which shows the stock performance probably looks familiar by now.
Step 2: Handle Click Events
The sparklines library makes it easy for us to handle click events. When users click on a chart region, the library generates a custom sparklineClick
event. The event data includes all of the normal click properties, plus information about where on the chart the user clicked. To be notified of clicks, we define a handler for that custom event.
1 2 3 4 5 6 7 |
|
Now that we’re set up to receive sparklineClick
events, we can write the code to respond to them. For our example, let’s reveal a detailed financial analysis widget. Many web services, including Yahoo! and Google, have similar widgets, but we’ll use one from TradingView. As is typical, TradingView provides code for the widget as an HTML <iframe>
. We can wrap that <iframe>
in our own <div>
and place it immediately after the chart. We set a display
property of none
so that the contents are initially hidden. (The following snippet omits the details of the <iframe>
element for clarity.)
1 2 |
|
Now our event handling code can reveal the widget using the jQuery show()
function.
1 2 3 |
|
That works to reveal the details, but as figure shows, the resulting presentation isn’t as elegant as it could be since the details appear so abruptly.
Step 3: Improve the Transitions
Instead of simply revealing the widget beneath the chart, it would be better to have the widget replace the chart. And if we’re going to do that, we’ll also want to give the users a chance to restore the chart and hide the widget. For that last function, we include a "widget-control"
<div>
in the following code (lines 2-4) for controlling the widget’s visibility. The only content we need for this controller is a close symbol floated right. Just like the widget itself, the controller is initially hidden.
1 2 3 4 5 6 7 |
|
Now when the user clicks on the chart, we reveal the widget, reveal the controller, and hide the chart.
1 2 3 4 5 |
|
Next we intercept clicks on the close symbol in the widget controller. We first prevent default event handling; otherwise, the browser will jump disconcertingly to the top of the page. Then we hide the widget and its controller while revealing the chart again.
1 2 3 4 5 6 |
|
Finally, we need to give the user some indication that this interaction is possible. On the chart, we can override the sparklines library’s default tooltip in line 4 to let users know that more details are available.
1 2 3 4 5 |
|
And for the widget controller, we simply add a title
attribute in line 3 to tell users how to hide the widget.
1 2 3 4 5 6 7 |
|
These additions give us the simple sparkline chart in figure , which expands to a wealth of details with a single click. The close symbol in the upper right lets users return to the more compact sparkline.
Step 4: Animation
For the final touch to our visualization, let’s do something about the abrupt hiding and revealing of the visualization components. A smoother animation will help our users follow the transition, and jQuery makes it easy enough to implement. There are lots of animation effects available in the jQuery UI library, but the basic functionality of jQuery’s core is fine for this example. We simply replace the show()
and hide()
functions with slideDown()
and slideUp()
respectively.
1 2 3 4 5 6 7 8 9 10 11 |
|
At this point we can call our visualization complete; the final product is shown in figure . The compact sparkline smoothly transitions to reveal detailed information when the user clicks, and those details transition back to the sparkline when the user closes them.
Updating Charts in Real Time
As we’ve seen in this chapter’s other examples, sparklines are great for integrating visualizations in a complete web page. They can be embedded in text content or used as table elements. Another application that suits sparklines well is an information dashboard. Effective dashboards summarize the health of the underlying system at a glance. When users don’t have the time to read through pages of texts or detailed graphics, the information density of sparklines makes them an ideal tool.
In addition to high information density, most dashboards have another requirement: they must be up-to-date. For web-based dashboards, that means the contents should be continuously updated, even while users are viewing the page. There is no excuse for requiring users to refresh their browsers. Fortunately, the sparklines library makes it easy to accommodate this requirement as well.
Just as in this chapter’s first example, we need to include the sparklines and jQuery libraries in our web page. For this visualization we’ll show both a chart and the most recent value of the data. We define <div>
elements for each and place both in a containing <div>
. The following code includes some styles inline, but you could place them in an external stylesheet. Here the styles are just meant to position the value immediately to the right of the chart rather than on a separate line.
1 2 3 4 |
|
Step 1: Retrieve the Data
In a real dashboard example, the server would provide the data to display and updates to that data. As long as the frequency of the updates was modest (not faster than once every five seconds or so), we could simply poll the server for updates on a regular interval. It’s probably not a good idea, however, to use the JavaScript setInterval()
function to control the polling interval. That may seem strange at first because setInterval()
executes a function periodically, which would seem to meet the requirements exactly. The situation is not quite that simple, however. If the server or network encounters a problem, then requests triggered by setInterval()
will continue unabated, stacking up in a queue. Then, when communication with the server is restored, all of the pending requests will immediately finish, and we’d have a flood of data to handle.
To avoid this problem, we can use the setTimeout()
function instead. That function executes only once, so we’ll have to keep calling it explicitly. By doing that, though, we can make sure that we send a request to the server only after the current one finishes. This approach avoids stacking up a queue of requests.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Notice that the structure of the code defines the getData()
function and immediately executes it. The closing pair of parentheses at the end of line 12 triggers the immediate execution.
Within the success
callback we set up a recursive call to getData()
in line 9 so the function executes again whenever the server responds with data.
Step 2: Update the Visualization
Whenever we receive updated information from the server, we can simply update the chart and value. The code needs only a straightforward call to the sparklines library and a jQuery function to update the value. We’ve added that to the code here in lines 6 and 7 below.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Figure shows what a default chart looks like. Of course you can specify both the chart and text styles as appropriate for your own dashboard.
Summing Up
In this chapter, we’ve considered various techniques for integrating visualizations within a web page. We’ve seen that sparklines are an excellent tool. Because they provide a lot of visual information in a small space, they leave room for other elements of the page, including text blocks, tables, and dashboards. We’ve considered several ways to increase the information density even further with annotations, composite charts, and click events. Finally, we looked at how to create charts that update in real time, accurately visualizing the up-to-the-minute status of an underlying system.
Continue reading: Chapter 4: Creating Specialized Graphs.