Charting for mobile with the Dojo Toolkit

Easily develop a charting application for mobile devices

Explore the capabilities of the dojox.mobile and dojox.charting packages. In this article, use the step-by-step examples to create a mobile charting application with the Dojo Toolkit, then enhance the application to support touch interactions. Advanced topics, such as improving rendering performance, are also covered.

Share:

Christophe Jolif (christophe.jolif@fr.ibm.com), Software Engineer, IBM

Photo of Christophe JolifChristophe Jolif is an advisory software engineer at IBM France. He leads the IBM ILOG Elixir development team and contributes to the Dojo Toolkit open source project. He writes about ILOG Elixir on the team blog and in technical articles, and also contributes to the product technical documentation. Before joining IBM, Christophe worked for ILOG for more than a decade, developing advanced visualization components in Java™, Ajax and Adobe® Flex.



Damien Mandrioli (mandrioli@fr.ibm.com), Software Engineer, IBM

Photo of Damien MandrioliDamien Mandrioli is a software engineer at IBM. His professional interests include visualization components, web application development, and user interface usability. Damien spent five years developing components and demos for the IBM ILOG Elixir visualization product before joining the Dojo Toolkit development team.



16 August 2011

Also available in Chinese Russian Japanese Portuguese

Introduction

In this article, learn how to use the Dojo Toolkit charting framework to create compelling charting applications that run on mobile devices. Learn how the charting component can be instantiated and configured inside a Dojo mobile application as well as how to enable touch interactions on the component for better integration with mobile devices. Also explore some advanced options for the charting application to load and render faster.

You can also download the source code of this article.


Creating a Dojo Mobile charting application

When building a mobile application with Dojo, it is recommended that you rely on the dojox.mobile package. It's a relatively thin Dojo layer that provides a mobile oriented set of lightweight widgets, a parser, and a transition framework. Considering the importance of these features for mobile applications, most mobile Dojo charting applications will likely use this framework.

The simplest way to instantiate your chart in the context of a dojox.mobile application is to rely on the parsing and put your charting code inside the dojox.mobile widget markup (similar to what you would do with a regular Dijit desktop application). First you need an HTML file defining the markup of your application, and a JavaScript source file referenced from the HTML that contains the JavaScript logic for your application.

The example in this article shows you how to build a simple application that displays sales data using a column chart, divided by months, over a period of three years. Create an HTML file with the code in Listing 1.

Listing 1. Initial mobile charting application HTML file
<!DOCTYPE HTML> 
<html> 
  <head> 
    <title>Dojo Toolkit Mobile Charting</title> 
    <meta name="viewport" content="width=device-width,initial-scale=1, 
      maximum-scale=1,minimum-scale=1,user-scalable=no"/> 
    <meta name="apple-mobile-web-app-capable" content="yes" /> 
    <link rel="stylesheet" type="text/css" 
      href="../../../dojo_current/dojox/mobile/themes/iphone/iphone.css"> 
    <script type="text/javascript" src="../../../dojo_current/dojo/dojo.js" 
      data-dojo-config="parseOnLoad: true"></script> 
    <script type="text/javascript" src="src_01.js" charset="utf-8"></script> 
  </head> 
  <body> 
    <div id="view1" data-dojo-type="dojox.mobile.View"> 
      <h1 id="head1" data-dojo-type="dojox.mobile.Heading">Chart View</h1> 
      <div data-dojo-type="dojox.mobile.RoundRect"> 
        <button id="b1" data-dojo-type="dojox.mobile.Button" 
          class="mblBlueButton">Zoom</button> 
        <button id="b2" data-dojo-type="dojox.mobile.Button" 
          class="mblBlueButton">Unzoom</button> 
        <div data-dojo-type="dojox.charting.widget.Chart" id="chart" 
          style="width: 100%; height: 180px;"> 
          <div class="plot" name="grid" type="Grid" 
               vMinorLines="true"></div>             
          <div class="axis" name="x" 
               fixUpper="minor"   
               majorTickStep="1" 
               minorTicks="false"></div> 
          <div class="axis" name="y" vertical="true" min="0"></div> 
          <div class="plot" name="plot" type="Columns" ></div> 
          <div class="series" name="data" plot="plot" 
            data="20, 32, 32, 45, 37, 28, 24, 48, 44, 21, 32, 33, 
                32, 34, 44, 32, 39, 43, 44, 46, 36, 41, 25, 27, 
                28, 45, 46, 33, 34, 35, 29, 44, 48, 48, 49, 43"></div> 
        </div> 
      </div> 
    </div> 
  </body> 
</html>

The code in Listing 1 is referencing dojox.mobile and dojox.charting classes in the Dojo data-type attributes. For this markup to be correctly parsed and instantiated, the corresponding modules must be imported in the JavaScript source file, as shown in Listing 2.

Listing 2. Initial mobile charting application JavaScript source file
require(["dojo", "dojox/mobile", "dojox/mobile/parser", 
  "dojox/mobile/Button", "dojox/charting/widget/Chart", 
  "dojox/charting/axis2d/Default", "dojox/charting/plot2d/Columns",
  "dojox/charting/plot2d/Grid"]);

The examples in this article rely on the recently introduced AMD syntax for managing dependencies of the Dojo application. (See Resources to learn more about AMD.) With backward compatibility, a similar application can be built using the superseded dojo.require format for dependencies if you don't want to switch to the new format.

If you run the corresponding application, you should get the result shown in Figure 1.

Figure 1. A mobile charting application
A bar chart on a landscape mobile view with two buttons for zooming control.

The chart in Figure 1 is just a static non-interactive chart with hard-coded data from the data attribute of the series defined in the markup. Before going further, some minor adjustments to the application are needed.

At this point, the application is tailored for Webkit mobile and desktop browsers. If you want the application to run better on other desktop browsers, such as Firefox, you can update your dependency list to add the dojox/mobile/compat module, as shown in Listing 3. The example uses the dojo/has AMD plug-in to only include that module if you're not running a Webkit browser, so the compatibility module is required.

Listing 3. Adding non-Webkit browser support
require(["dojo/_base/kernel", "dojo/_base/sniff", "dojox/mobile", "dojox/mobile/parser",
	"dojo/has!webKit?:dojox/mobile/compat", 
	"dojox/mobile/Button", "dojox/charting/widget/Chart", 
	"dojox/charting/axis2d/Default", "dojox/charting/plot2d/Columns",
	"dojox/charting/plot2d/Grid"]);

The next step is to feed the displayed charting data with an external data source instead of hard-coding data into the application. To do this, you can use the data store API of both Dojo Charting and Dojo Core.

There are classes in the dojo.data and dojox.data packages that let you load data from various data sources and connect them to Dojo components. For the example, assume you have the JSON data in Listing 4 on the server and want to load it.

Listing 4. Sample JSON data
{
  "items": 
  [ 
{"value": 0}, {"value": 32}, {"value": 32}, {"value": 45}, {"value": 37}, {"value": 28}, 
{"value": 24}, {"value": 48}, {"value": 44}, {"value": 21}, {"value": 32}, 
{"value": 33}, {"value": 32}, {"value": 34}, {"value": 44}, {"value": 32}, 
{"value": 39}, {"value": 43}, {"value": 44}, {"value": 46}, {"value": 36}, 
{"value": 41}, {"value": 25}, {"value": 27}, {"value": 28}, {"value": 45}, 
{"value": 46}, {"value": 33}, {"value": 34}, {"value": 35}, {"value": 29}, 
{"value": 44}, {"value": 48}, {"value": 48}, {"value": 49}, {"value": 43} 
  ]
}

The JSON data can be loaded by an instance of dojo.data.ItemFileReadStore. To proceed with charting, connect your dojo.data instance to a Series object that will be in charge of populating the chart with data items from the store.

You first have to modify the declaration of the series in the HTML to not take hard-coded data as input, but to reference a data store named "store." To do so, change the Series definition in Listing 6 to include store="store", as shown in Listing 7.

Listing 6. Previous Series definition
            <div class="series" name="data" plot="plot" 
              data="20, 32, 32, 45, 37, 28, 24, 48, 44, 21, 32, 33,
                    32, 34, 44, 32, 39, 43, 44, 46, 36, 41, 25, 27,
                  28, 45, 46, 33, 34, 35, 29, 44, 48, 48, 49, 43"></div>
Listing 7. Previous Series definition, including store
            <div class="series" name="data" store="store" plot="plot"></div>

In the same HTML file you can define the store with the markup in Listing 8.

Listing 8. Store HTML definition
	    <div data-dojo-type="dojo.data.ItemFileReadStore" url="data.json"
       		 data-dojo-id="store" urlPreventCache="true" clearOnClose="true"></div>

The code in Listing 8 uses the ItemFileReadStore class to load the data.json file on the server and associate the results to the store variable that is used as the input of the series. The data store class must be required into your application as part of the source file require statement, as shown in Listing 9.

Listing 9. Requiring store class
require(["dojo/_base/kernel", "dojo/_base/sniff", "dojo/data/ItemFileReadStore",
        "dojo/has!webKit?:dojox/mobile/compat", 
        "dojox/mobile", "dojox/mobile/parser", 
        "dojox/mobile/Button", "dojox/charting/widget/Chart", 
        "dojox/charting/axis2d/Default", "dojox/charting/plot2d/Columns",
        "dojox/charting/plot2d/Grid"]);

You now have a mobile charting application rendering monthly data coming from the server. The example is still missing the x-axis displaying the target month instead of the data indexes. Reference a label function on the axis, as shown in Listing 10.

Listing 10. Specifying a label function
            <div class="axis" name="x" 
	         fixUpper="minor" majorTickStep="1"
                 minorTicks="false" labelFunc="displayDate"></div>

The displayDate function is then defined in the source file, as shown in Listing 11.

Listing 11. Implementing the label function in JavaScript
var displayDate;
require(["dojo/_base/kernel", "dojo/_base/sniff", "dojo/data/ItemFileReadStore",
       "dojo/has!webKit?:dojox/mobile/compat", 
       "dojox/charting/action2d/TouchZoomAndPan", 
       "dojox/mobile", "dojox/mobile/parser", 
       "dojox/mobile/Button", "dojox/charting/widget/Chart", 
       "dojox/charting/axis2d/Default", "dojox/charting/plot2d/Columns",
       "dojox/charting/plot2d/Grid"], function(dojo){
  var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", 
                "Oct", "Nov", "Dec"];
  var years = ["08", "09", "10", "11"];
  displayDate = function(idx){
    if ((idx%2) == 0){
     return " ";
    }
			
    var m = parseInt(idx-1);
    if (m%12 == 0){
      // Display the year only for january
      return months[m%12] + " " + years[m/12];
    }else{
      return months[m%12];
    }
  }
});

The code in Listing 11 basically maps each data index to a String. In the example, because there is monthly data over three years, the string is formed with the corresponding month for a given index.

You should now have the result shown in Figure 2.

Figure 2. Customizing axis labels
This view shows the x-axis labeling customization with years and months added.

Enabling charting touch interaction

After you've created your Dojo mobile charting application, you might want to add specific mobile features to it, such as the ability to interact with the chart using touch gestures. This is relatively easy. Similar to other functions of the chart, you can add touch using a single line of code in the chart definition. For example, to add touch zoom and pan ability, you simply add the content of Listing 12 to the HTML markup.

Listing 12. Adding touch zoom and pan support
<div class="action" type="dojox.charting.action2d.TouchZoomAndPan" 
     plot="plot" maxScale="7"></div>

The plot attribute lets you attach the action to a particular plot of the chart (in the example, the one named plot). You can also use various other options, such as whether zooming is allowed (enableZoom="false"), or the maximum scale you want to be applied onto the chart (maxScale="7").

Another useful touch interaction is to display a data indicator when touching the chart. It can even be a dual data indicator showing the trend between two touch points.

Using the code in Listing 13 yields the result in Figure 3 when touching the chart with a single touch.

Listing 13. Adding touch indicator support
<div class="action" type="dojox.charting.action2d.TouchIndicator" plot="plot" 
     series="data" dualIndicator="true"></div>
Figure 3. Interactive simple touch indicator
This view shows the simple touch indicator. It shows the value of the touched data point.

With a dual touch gesture you get the result shown in Figure 4.

Figure 4. Interactive dual touch indicator
This view shows the dual touch indicator. It shows the variation in percent between the two touched data points.

Several other parameters are available on the touch interactions, such as the ability to change the colors and font of the data indicator. You can even decide to change the fill color of the indicator based on whether the trend between the two touch points is positive or negative. Listing 14 shows an example of how to build such an indicator in JavaScript.

Listing 14. Configuring a touch indicator in JavaScript
var indicatorFillFunc = function(v1, v2){
  if(v2){
    return v2.y>v1.y?"green":"red";
}else{
  // single touch point
    return "#ff9000";
  }
};
var indicator = new TouchIndicator(chart, "plot", {
               series: "series", dualIndicator: true, 
               font: "normal normal bold 12pt Helvetica",
               fillFunc: indicatorFillFunc
});

Some mobile devices, such as Android 2.2 and 2.3, do not support multiple touch events in the browser. You might want to map certain actions that rely on dual touch, such as zooming in and out, to buttons and touch interactions to cover all devices. For this situation, there have been inactive buttons in the user interface since the first listing in this article. It's now time to add some code to react when clicking or touching these buttons. Listing 15 shows how to specify a zoom function.

Listing 15. Specifying a zoom function
          <button id="b1" data-dojo-type="dojox.mobile.Button" 
		    onclick="zoomChart()"
            class="mblBlueButton">Zoom</button>
          <button id="b2" data-dojo-type="dojox.mobile.Button"
		  	onclick="zoomChart(true)" 
            class="mblBlueButton">Unzoom</button>

The code in Listing 15 calls the zoomChart function on both the zoom and unzoom buttons. Because zoom and unzoom actions are very similar, you use only one function with an argument set to true for unzoom.

Define the zoomChart function in the JavaScript source file, as shown in Listing 16. The idea is to get the current visible bounds to compute a new range to pass to the zoomIn function of the Dojo chart component.

Listing 16. Implementing the zoom function in Javascript
  zoomChart = function(back){
    var chart = dijit.byId("chart").chart;
    var b = chart.getAxis("x").getScaler().bounds;
    var r = 1.25;
    if (back){
      // Unzoom
      chart.zoomIn("x", [b.from / r, b.to * r]);
    }else{
      // Zoom
     chart.zoomIn("x", [b.from * r, b.to / r]);
    }
};

Optimizing the application

You now have a fully working Dojo mobile charting application, but it isn't fully optimized.

The first type of optimization you'll work on is improving rendering time. Mobile devices usually have slower CPU and memory than desktop devices and thus slower rendering. By default, Dojo does not cache the rendered item of a chart. When using the touch interaction to zoom or pan the chart, a lot of renderer items might be destroyed and rebuilt. Not enabling caching is good when you have a static chart because it gives a faster initial rendering. However, in a dynamic use case, it's preferable to enable caching. You can use the enableCache parameter of several charting elements.

In the code, set enableCache to true on the chart elements, as shown in Listing 17.

Listing 17. Optimizing rendering
<div data-dojo-type="dojox.charting.widget.Chart" id="chart" 
    style="width: 100%; height: 180px;">
<div class="plot" name="grid" type="Grid"
    vMinorLines="true" enableCache="true"></div>
    <div class="axis" name="x" enableCache="true"
        fixUpper="minor"   
        majorTickStep="1"
        minorTicks="false"
        labelFunc="displayDate"></div>
    <div class="axis" name="y" vertical="true" min="0"></div>
    <div class="plot" name="plot" type="Columns" enableCache="true"></div>
    <div class="series" name="data" store="store" plot="plot"></div>
    <div class="action" type="dojox.charting.action2d.TouchZoomAndPan" 
        plot="plot" maxScale="7"></div>
</div>

The example did not enable caching on the y-axis. When zooming in or out, the chart along the y-axis is not re-rendered and thus would not benefit from optimization.

Another way to optimize the mobile charting application rendering is to prevent unnecessary rendering. For example, a column plot might have outlines or shadows that are not absolutely necessary but they consume rendering time. You might consider removing them. Another example is the data indicator, for which you can remove outline strokes by setting the corresponding style properties to null, as shown in Listing 18.

Listing 18. Removing unnecessary rendering
<div class="action" type="dojox.charting.action2d.TouchIndicator" plot="plot" 
     series="data" dualIndicator="true" outline="null" lineOutline="null"
     markerOutline="null"></div>

It's important to optimize the loading time of the application, especially on mobile devices where network connections are not always as fast as their desktop counterparts. With the new AMD loader available in Dojo, instead of loading the various required files synchronously you'll be able to load the files asynchronously and increase overall loading performance. Add the async parameter on Dojo initial configuration, as shown in Listing 19.

Listing 19. Enabling asynchronous loading
    <script type="text/javascript" src="../../../dojo_current/dojo/dojo.js"
      data-dojo-config="parseOnLoad: true, async: true"></script>

You can improve loading time even further by removing any utilities that are not absolutely needed by your application. For example, the entire mobile charting application was defined using markup that relies on the dojox.mobile parser. This lightweight parser is much lighter than the regular Dojo parser. If you really want to further reduce your application download size, you can get rid of the parser entirely and build your application in JavaScript.


Conclusion

In this article, you learned how you can use the Dojo charting package inside a mobile web application. It can be tailored to mobile devices to rely on touch events for interaction instead of relying on mouse or button paradigms. This article also explored some advanced options you can use to improve loading and rendering time.

If you are interested in pursuing the topic further, Dojo charting is designed to be extensible. You can build your own features on top of it. For example, if you are in need of a touch interaction not provided by the framework, you can extend the Dojo charting action package to create your own interactions.


Download

DescriptionNameSize
Source codesource.zip10KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, Mobile development
ArticleID=751975
ArticleTitle=Charting for mobile with the Dojo Toolkit
publish-date=08162011