Monday, May 28, 2012

jQuery Mobile Charts

The Plot Chart
Numeric data quickly becomes difficult for us humans to understand. Once the number of rows or columns in a table passes two or three, the meaning quickly becomes harder to grasp. The easiest way to give meaning to numeric data is to display it as a chart. Unfortunately jQuery Mobile doesn't have any built-in charting capabilities and to the best of my knowledge there isn't a jQuery Mobile charting plug-in available. But lucky for us, jQuery Mobile is built on top of jQuery and there are several charting plug-ins available for it. 

My requirements for a charting library are pretty simple:
  1. Free and open source
  2. Compatible across the three mobile platforms I support: iOS, Android, Windows Phone 7
One of my favorite JavaScript charting libraries is "Raphael". I have used it on desktop projects previously but it was quickly out of the running. Raphael uses SVG, which isn't supported well across mobile platforms.

Next I googled, "jQuery charts". Nearly 3 million websites were returned, so I knew I was going to find something. Close to the top of the list was the following link: 1st Web Designer. The post there listed six jQuery charting plug-ins: 
  1. GraphUp
  2. jQuery Visualize
  3. Highcharts
  4. Flot
  5. jQuery Sparklines
  6. jqPlot
After doing a bit of analysis, I decided to run with jqPlot. This is not to say that the other packages aren't good, it is just that I was able to understand jqPlot's examples quicker than the others and it met all of my requirements. For your own needs, please try out the libraries, they may meet your needs better than they had mine.

jqPlot

There are two methods for generating graphics in HTML5, canvas and SVG. 
Canvas is like a bitmap and JavaScript can render graphics to it. SVG's use of vector graphics makes it seem ideal for a charting library, the problem is that SVG is not as well supported as canvas and it is not available on 2.x Android or any WP7. jqPlot uses HTML5 canvas. 

The jqPlot library is huge. It has an immense number of features. But it is not a bloated pig, it is smartly architected. Rather than force you to download a lot of charts and features you won't use, it, itself is composed of a large number of plug-ins, I counted 26 of them. This means you only download the plug-ins you want to use.

I could spend weeks explaining all of the features of jqPlot, unfortunately I don't have the time for that. Instead I am going to give you a quick walk through my demo app and explain anything interesting along the way. 

JQMCharts on iPhone, Android, and WP7
index.html

Everything starts with the markup page, index.html. It contains four jQuery Mobile pages:
  1. page1 - the home page for the app
  2. pageBarChart - the bar chart page
  3. pagePieChart - the pie chart page
  4. pagePlotChart - the plot chart page
Page 1 is strictly a markup page. There isn't any JavaScript for the page since the only thing it does is link to the other pages. Which is something jQuery Mobile handles innately without the need of JavaScript.


pageBarChart

pageBarChart is where things begin to get interesting. It consist of an empty <div> which will hold the chart once it is rendered, a button to refresh the chart, and three sliders to change the values of the chart. The initial version of this page didn't have a refresh button. On the iPhone the rendering of the chart was fast enough that it could be done interactively. Unfortunately the same wasn't true under Android and WP7. Android was close, but WP7 was downright sluggish. So I removed the code hooking the input change event, added a button, and hooked the click event for the button. While not as nice as watching the chart change dynamically, it isn't too bad. This was yet another reminder of why it is important to test on all supported devices.

The JavaScript bound to the page is in the manageBarChart function. It handles to events, "pageshow" and "pagehide". It uses these events to hook and unhook events respectively. It also holds to private methods, updateChart and showChart. UpdateChart grabs the values of each of the sliders, then calls showChart. ShowChart renders the chart. One interesting thing with jqPlot is that it doesn't automatically clear the canvas when you call it successively. Instead if you want to clear the canvas, you call its replot method with clear and resetAxes equal to true.  (resetAxes allows the charting to scale itself appropriately)

pagePieChart

pagePieChart is very similar to pageBarChart. The call to jqPlot is different and that it doesn't call replot. Since the pie chart isn't using any labels or axis, successive redraws overwrite each other without leaving garbage behind, so the replot call isn't needed.  



pagePlotChart

The final page is pagePlotChart. It follows the pattern established in the other pages with the notable exception being the updateChart method. I decided to modify the method I use to grab the data from the sliders. 

Here I don't limit the number of sliders. Instead I interrogate all of the sliders on the page successively for their value, convert it to an integer, then push it and the index into an array. This allows us to add or remove sliders without the need to change the rendering code. The "$.mobile.activePage" limits the jQuery selector to the context of the current page. I should probably make the selector of the find method, "input", more narrow so that it only finds the sliders, but it works for this example since the only input tags on the page are sliders.

One other thing which is different is the, $.mobile.silentScroll(), call. Since there are six sliders on the page and scrolling down to the bottom one, normally slides the chart off the top of the page, I added this call in order to bring the chart back on the page when the refresh button is hit.

Summary

That is all for this post. This post is the first where the code is hosted on GitHub. So be sure to check out all of the repos I have there. Each general ties into a blog post. Over the next few days I will be moving all of my tutorial code to it. Using GitHub, which ties into my IDE, WebStorm which makes easy to add fixes and updates to code.

My next posts will be on how to convert my JQMCalculator tutorial to a PhoneGap (Cordova) app for iOS and how to create a twitter app in jQuery Mobile.

58 comments:

  1. I have read this post. collection of post is a nice one ..that am doing website designing company chennai india and website development company chennai india. That I will inform about your post to my friends and all the best for your future posts..

    ReplyDelete
    Replies
    1. Thank you. I usually write one or two new posts a week. You might want to follow me on Twitter @therockncoder. I always announce new posts there first.

      Delete
  2. Thanks for the info... it helped me..

    ReplyDelete
    Replies
    1. Glad I can help. Be sure to check out some of my other tutorials or to follow me on twitter @therockncoder to know when I release new posts.

      Delete
  3. First of all Thank you for putting up a great site.
    I was on a similar quest and came across your site. Did follow up on your leads and would like to add 2 more to the list.
    1. AwesomeChart.js (http://cyberpython.github.com/AwesomeChartJS/)
    If you want to be up and running quickly then this is a very good library. Just one file and very good defaults.Only drawback is that there is no line chart out of the box but it is still pretty useful.
    2. Flotr2 (http://humblesoftware.com/flotr2/)
    This is a full fledged charting library and under active development.

    ReplyDelete
    Replies
    1. Hi Ravishankar V,

      Thanks for your comments and the info. I will take a look at the packages you mentioned, and do a follow up post later.

      I will be making the charts program more responsive later and allow it to re-size itself dynamically based on available screen real estate.

      Have so many good and free options is one of things I love about the Open Source community.

      Delete
  4. Hey Troy,

    Have you considered google charts api?

    https://developers.google.com/chart/

    Very easy to use and has options to generate images.

    ReplyDelete
    Replies
    1. Hi Stan,

      I have used google charts api on a couple of projects in the past and it is a great service. The only reason I didn't use it for this example is because it is a service and not a plugin.

      On mobile it is usually not a good idea to dependent on 3rd party services, since you don't know how long it will take for the service to respond. Using a plugin and generating the graphics on the client is more predictable and even with the size of the jqPlot file (166kb) will probably be much faster.

      Plus, it is one of my goals to eventually port this example to phonegap. Much easier to do with a plugin.

      Thanks for the question. Be sure to follow me on Twitter @therockncoder since I usually announce new tutorials there first.

      Troy

      Delete
    2. I guess that is open to debate regarding the use of 3rd party services as you type on a google hosted blog, ask me to follow you on another service, twitter as many mobile apps use third party services to send and receive data (amazon s3, facebook oauth, twitter api, random REST apis, the list goes on).

      jqPlot is a good charting script, I use that in one of my products now. Sencha touch has a fantastic touch chart library, eliminates the need for jQuery mobile as its a competing product. I perfer jQuery myself.

      Anyways to follow up on the first paragraph, I have been looking at parse for mobile development. REST apis to access data (SDKs for other platforms as well). Looks interesting.

      Only a matter of time before mobile development becomes an exercise of drag drop, integrating into 3rd party services. All you will need is a designer for the UI :) http://tiggzi.com/home

      Delete
    3. Hi Stan,
      Sorry, if I am not being clear. I don't have a problem with using 3rd party services at all. I have used Google's charts and I think it is excellent.
      My concern is using 3rd party service with a mobile app on the client side. Using a plugin gives me predictability. I have a good estimate of how long it will take to render. I haven't tried charts on mobile yet. I know google maps delivers great performance over mobile.
      Please let me know how your experience with charts over mobile is.

      Thanks,

      Troy

      Delete
  5. For native apps I just build them in their native environment as jquery mobile lacks the performance as you described. I expose the data via rest apis and if I don't have the expertise to build it on a particular platform, I find someone that does.

    The best js charting engine I have seen is Sencha touch charts.

    ReplyDelete
  6. good, very good post.

    Max
    http://jquerymobilebymaxsp.blogspot.it/

    ReplyDelete
  7. You can include and jqChart to the list. jqChart takes advantages of HTML5 Canvas to deliver high performance client-side charts and graphs across browsers and devices, including iOS and Android mobile devices.

    ReplyDelete
    Replies
    1. Thanks for sharing. I will be sure to add them to the list. I will be updating this post next month.

      Delete
  8. great stuff troy you got a new follower on twitter @miconico

    ReplyDelete
    Replies
    1. Thanks for your support. Be sure to check out some of the other posts.

      Delete
  9. jqPlot looks pretty good. I was excited about NVD3.js (reusable charts built on d3.js) until I found out SVG wasn't supported in Android 2.x. jqPlot is a bit lacking when it comes to types of charts though. Any plugins for gauges?

    ReplyDelete
    Replies
    1. Hi Kenji,

      The only gauge that I am aware of is the meter gauge. All of the different types of charts are plugins, but they all come from jqPlot. Here is the link to the meter gauge: http://www.jqplot.com/deploy/dist/examples/meterGauge.html.
      Thanks for reading my blog. Be sure to have a look at the other posts!

      Troy

      Delete
  10. I truly like to reading your post. Thank you so much for taking the time to share such a nice information.
    web grid

    ReplyDelete
  11. Hi Troy, I'm relatively new to Jquery mobile and I'm have trouble hooking the input change event to updating the chart. Maybe you can show your original code for our reference? That would be fantastic! Thanks!

    ReplyDelete
    Replies
    1. Hi Jay,
      I am a little unsure what you mean by original code? There is a link to the complete source code plus a link to a working demo. Are both of these insufficient?

      Troy

      Delete
  12. This comment has been removed by the author.

    ReplyDelete
  13. Hi Troy! Thanks for replying so quickly! I'm sorry I wasn't clear. I'm trying to interactively control the chart using the range slider input. You mentioned you removed the code hooking the input change event for the slider because Android and WP7 was too sluggish, thats why you added the refresh button instead. I tried something like
    $( "#pageBarSliderA" ).on( 'slidestop', function( event ) {updateChart();});

    and also change events, amongst others but I'm obviously doing something wrong. Thats why I was hoping to see the code you replaced with the refresh button.

    Btw fantastic post and code examples!

    ReplyDelete
    Replies
    1. Hi Jay,
      Here is the code:

      RocknCoder.Pages.manageBarChart = function () {
      var pageshow = function () {
      updateChart();
      $("#refreshBarChart").click(function(){
      updateChart();
      });
      $('#pageBarSliderA,#pageBarSliderB,#pageBarSliderC').on('change',function(e){
      updateChart();
      });
      },

      The important part is the last few lines where we hook the 'change' event of the sliders.

      Delete
    2. P.S.

      Please +1 this post if you like it. Thanks.

      T

      Delete
  14. Hello Troy,

    nice to see you post actually.
    but now my need is, i want data from some outer php file. and i dnt need sliders & refreshing option.

    i had a data table in my page. & i want plot chart just bottom of that data table, WITH THE VALUES OF THAT TABLE.(TABLE TAKES DATA FROM DATABASE IN JSON FORMATE) NOW TASK IS CHART IS SHOULD ALSO USE THAT JSON DATA TO DISPLAY CHART.

    please help me friend..

    [there will be no issue whether chart updates using table columns or directly json data.]

    ReplyDelete
  15. Hello Troy,

    i have a question to vertical bars. When the bar has the same amount, two bars get draw as one bar. Any option i forget to write?

    i just change the barDirection:'vertical' and axis too xaxis

    here the code:
    seriesDefaults:{
    renderer:$.jqplot.BarRenderer,
    shadowAngle:135,
    rendererOptions:{
    barDirection:'vertical'
    },
    pointLabels:{show:true, formatString:'%d'}
    },
    axes:{
    xaxis:{
    renderer:$.jqplot.CategoryAxisRenderer
    }

    }
    }).replot({clear:true, resetAxes:true});
    };

    ReplyDelete
    Replies
    1. Hi,

      I haven't tried it, but have you tried putting a third column in with a value of 0? It would be a hack but...

      Troy

      Delete
  16. There is a third alternative, i have experiment to program in OpenGL and create charts that way. Now i try to test it for WebGL.

    ReplyDelete
  17. Thanks for the informative post. While all of them are great options for charting, I’ve heard lots of positive reviews of www.FusionCharts.com for their wide range of chart types, and long list of features. do add them as well?

    ReplyDelete
  18. Very very useful article, i will use it on my site.

    http://giadinhthinhvuong.com

    Thanks again my friend

    ReplyDelete
  19. Hello
    Thanks for the wonderful post..
    very helpful in my current application.
    but zoom:true is not working on mobile devices.
    How to enabled that support?

    Thanks

    ReplyDelete
    Replies
    1. Is zooming working for you on mobile devices? I am trying the same thing but it is not working for me.

      Delete
    2. Could you be more specific as to what you mean by zooming? In most of my mobile web applications I purposely turn off zooming. This is done in the viewport meta tags.
      Or are you trying to just zoom the chart?

      Delete
  20. hello
    thanks for these post it is very helful
    but how to open barGraph on another page.. slider on one page and graph on another page...
    Thanks

    ReplyDelete
    Replies
    1. Hi Payal,

      Did you still want an example of two graphs? If so, let me know by responding to this comment and I will create a new example.

      Troy

      Delete
  21. Thanks for the wonderful post..going to be really contributing.
    BTW, generated graphs are static in nature or is it possible to make them interactive. For an example, show some tooltip or highlight some values on click of the graph?

    ReplyDelete
    Replies
    1. Hi,

      I initially wrote the code to be interactive, but older phones couldn't keep up, so I slowed it down by requiring a button click in order for the chart to be redrawn. This functionality could be restored by removing the click event on #refreshBarChart and adding change events on the sliders.

      --Troy

      Delete
  22. Hi Troy,

    Very nice article. How can I add more than one chart in the same page in different divs?

    I am new to html5 and not finding where the divs are linked to the chart.

    Thanks,
    Reddy

    ReplyDelete
  23. This is a site to view volume and technical tradingchart analysis. This site provides leading technical indicator analysis and provides a great stock screener.

    ReplyDelete
  24. I have an application that uses JQM, PhoneGap and Flot.

    I displays charts with the browser.
    I displays nothing when using an emulator (Ripple) or my iPhone 5.
    I would appreciate if somebody could help me resolve this issue (Flot and PhoneGap integration).
    FYI - I am using the PhoneGap Build service.

    Regards and Thanks a bunch!

    Eric

    ReplyDelete
    Replies
    1. Hi Eric,

      Unfortunately I don't have a lot of experience with Flot. My preferred charting solution is jqPlot. As for Ripple, I am able to get it working using my demo web site. Can you switch charting solution? http://www.tekadept.com/m/index

      Sorry I couldn't be of more help.

      Troy

      Delete
  25. hello troy, I'm an Italian developer and I found very interesting your work .... I'm trying to display a simple graph with jqplot but without success is not that you would have a html with a simple example
    gianfranco.ronci @ gmail.com, thanks

    ReplyDelete
  26. Hi Gianfranco,

    How are things in Italy? The quickest answer I can give you about making a quick prototype is download the jQuery Mobile Jump Start code from my GitHub repo. Chapter 13's solution contains the code for an extremely simple chart. https://github.com/Rockncoder/JQMJumpStart
    If you encounter any difficulties, let me know.

    Take care,

    Troy

    ReplyDelete
    Replies
    1. Hi Troy,
      I tested the code that you have shown me ... I have no errors, but I have the screen (content) white.
      My environment: android sdk + eclipse + cordova (2.6.0) + jQuery Mobile (1.3.1) + jqplot
      you have an idea of what could be the problem? are now five days I try to make a graph. I'm desperate ...
      thanks, Gianfranco.

      Delete
    2. Hi Gianfranco,
      Don't stress-out, I am sure we can resolve your issue(s). First - try running the code simply in the browser. Don't "PhoneGap it". We want to make sure that everything works correctly as a web app.
      Let me know if it works or not. Please connect with me directly via rockncoder@gmail.com

      Troy

      Delete
  27. Samsung Galaxy Note 3Samsung Galaxy Note 3 Price in india. Samsung Galaxy Note 3 Specifications, Feature. Samsung Galaxy Note 3 Review.Samsung Galaxy Note 3 Specifications and Review.

    ReplyDelete
  28. Thanks for the info. I tried applying jqplot to a homework assignment and quickly ran into a problem. Searching stackoverflow resulted in some one who had the same problem so I posted a bounty. After several days, a person in Europe was able to figure out a workaround. That solver suggests suggests filing an issue. I am unfamiliar with working with open source projects so I could use some help with that. I felt like perhaps I should attempt to submit a patch together with the report, but I am worried that will take too much time given my skills and am not sure where to start. Also I found what I recall was a similar problem report at the issue site before but cannot find it now. Could you please advise on what to do now: how to file report, how to make a patch, or just find similar problem already reported and leave it be.

    stackoverflow problem and workaround

    ReplyDelete
  29. Can you tell whether the bar click event will work the same for mobile touch events also for jqlot??

    ReplyDelete
  30. Great article. Useful for mobile charts. Thanks for sharing.
    http://www.dreamdestinations.in/

    ReplyDelete
  31. Hi its really very nice blog i enjoyed a lot to visit.cheap mobiles

    ReplyDelete
  32. Very very useful article, i will use it on my site.mobile phones

    ReplyDelete
  33. What do you recommend for very simple Client Side charting on a Embedded
    Web server (line and bar chart) that has no connection to the internet?
    I need very small library and I will use XML files to update information

    ReplyDelete
  34. Hi Allan,

    I would recommend jqPlot. It is small fast and full featured. Oh, and free.

    ReplyDelete
  35. Thank you so much Troy. You saved my time. :)

    ReplyDelete
  36. What should you recommend for the JQMChart using GWT(google web toolkit)

    Currently I am using GWT library for JQuery Mobile (https://github.com/jqm4gwt/jqm4gwt)

    Thanks

    ReplyDelete