Make a Stock Quote App: Displaying Charts with Raphael JS

Make a Stock Quote App: Displaying Charts with Raphael JS

Tutorial Details
  • Technology: Titanium Mobile + Raphael JS
  • Difficulty: Intermediate
  • Estimated Completion Time: 30 - 60 Minutes

In this tutorial series, I will be teaching you how to build a stock quote application with Raphael JS, Titanium Mobile, and Yahoo’s YQL web service. Raphael JS charts will be used to graphically present the stock quote information, Titanium Mobile will be used to cross-compile a native iOS app, and YQL data tables will actually retrieve the stock information.

Where We Left Off. . .

The last tutorial in this series introduced YQL and Raphael JS as components of a Titanium Mobile application and demonstrated the steps necessary to create our Stock Quote app interface and search for stock quotes using YQL. In this tutorial, we’ll finish out our stock quote app by adding in Raphael JS charts that plot historical data obtained using YQL.

Step 5: Setting up the Raphael JS Charting Library

Before we can start to implement a chart into our Stocks app, we have to first download the Raphael libraries, including the charting JavaScript files we’ll need to create our bar graph. To do this, follow these steps:

  1. Download the main RaphaelJS library from http://raphaeljs.com
    (Direct link: http://github.com/DmitryBaranovskiy/raphael/raw/master/raphael-min.js).
  2. Download the main Charting library from http://g.raphaeljs.com
    (Direct link: http://github.com/DmitryBaranovskiy/g.raphael/blob/master/g.raphael-min.js?raw=true) and any other charting libraries you wish to use. For this example we’ll just be implementing the Bar Chart, which is here: http://github.com/DmitryBaranovskiy/g.raphael/blob/master/g.bar-min.js?raw=true
  3. Put your downloaded files into your “Resources” directory. You could put them into a subfolder if you wish, but bear in mind you’d have to ensure your references in the following steps are correct.
  4. The next step is to rename your raphael-min.js file to something like raphael-min.lib. The main reason here is that if your file is a known JavaScript file (as in it ends in ‘.js’), the JSLint validator in Titanium will try to validate the Raphael JS library and fail, causing Titanium to lock up – meaning you won’t be able to run your app!

Now run your app again, you may get a few validation warnings appear in the Titanium Console from the Raphael code, but everything should still be running and working as it was in Step 4.

Step 6: Implementing a WebView for the Raphael JS Chart

We are going to use a WebView to present our chart to the screen. Let’s add a WebView now, and point it to a HTML file that we will create in the next step. We’ll also add a label to describe the WebView. This code should go before the line scrollArea.add(quoteChartBox);, which will be near the end of your code file:

// Add the chart label and webview we need to show our raphael chart
var lblChartName = Titanium.UI.createLabel({
    width: 280,
    height: 30,
    left: 10,
    top: 10,
    color: '#003366',
    font: {fontSize: 17, fontWeight: 'bold', fontFamily: 'Helvetica'},
    text: '12 Week Historical Chart'
});
quoteChartBox.add(lblChartName);
var webview = Titanium.UI.createWebView({
    width: 280,
    height: 240,
    left: 10,
    top: 40,
    url: 'chart.html'
});
quoteChartBox.add(webview);
var twelveWeekStartLabel = Titanium.UI.createLabel({
    width: 100,
    left: 10,
    top: 285,
    height: 10,
    textAlign: 'left',
    font: {fontSize: 9, fontFamily: 'Helvetica'},
    color: '#000'
});
quoteChartBox.add(twelveWeekStartLabel);
var twelveWeekEndLabel = Titanium.UI.createLabel({
    width: 100,
    right: 10,
    top: 285,
    height: 10,
    textAlign: 'right',
    font: {fontSize: 9, fontFamily: 'Helvetica'},
    color: '#000'
});
quoteChartBox.add(twelveWeekEndLabel);

Run your app in the emulator and you should now see an empty WebView and a label in the third box. You will have to scroll to the end of screen to see the third box in its entirety.

Step 7: Creating the Raphael Chart HTML & Event Listener

Now we are going to create an HTML file that includes all of the necessary Raphael libraries, and contains an empty <div> tag where our chart will be rendered to. Create a new, blank HTML file called chart.html and type in the following code:

<html>
<head>
 <title>RaphaelJS Chart</title>
 <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
 <script src="raphael-min.lib" type="text/javascript" charset="utf-8"></script>
 <script src="g.raphael-min.js" type="text/javascript" charset="utf-8"></script>
 <script src="g.bar-min.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
  <div id="chartDiv" style="width:280px; height: 240px; margin: 0"></div>
  <script>
   //This registers an event listener that you can call
   //from within the app.js file
   Ti.App.addEventListener('renderChart', function(chartData) {
     var r = Raphael("chartDiv");
     r.g.barchart(0, 0, 270, 240, chartData.data, 0, {type: "sharp"}).hover(fin, fout);
   });
  </script>
</body>
</html>

Save your chart.html file in your “Resources” directory if you have not already done so. What this code is doing is creating a basic HTML template, including the raphael libraries you downloaded earlier, and creating a div called chartDiv, which is what Raphael will render our chart into. With the script tags underneath this div, we are creating a standard Titanium event listener, which is going to execute whenever an event called renderChart is fired from somewhere within Titanium. This function will take any passed data and pull that into Raphael for rendering. The r.g.barchart() function takes the following list of parameters in order to create the chart (in order):
Left, Top, Width, Height, Data (an array of single-value arrays), Style Attributes. The hover function at the end of this method tells Raphael to render a fade-in, fade-out, and show column values when a bar line is tapped.

Step 8: Obtaining YQL Historical Data And Passing It to chart.html

It is now time for the final step in our tutorial: rendering the chart! Go into your searchYQL function, and after your previous code for obtaining the stock data, type in the following:

// Get today's date and break that up into month, day, and year values
    var currentTime = new Date();
    var month = currentTime.getMonth() + 1;
    var day = currentTime.getDate();
    var year = currentTime.getFullYear();
    //now create the two dates formatted in yyyy-mm-dd format for YQL query
    var today = year + '-' + month + '-' + day; //today
    //get the date 12 weeks ago.. 1000 milliseconds * seconds in minute * minutes in hour * 2016 hours (12 weeks, 12 * 7 days)
    var currentTimeMinus12Weeks = new Date((new Date()).getTime() - (1000 * 60 * 60 * 2016));
    var month2 = currentTimeMinus12Weeks.getMonth() + 1;
    var day2 = currentTimeMinus12Weeks.getDate();
    var year2 = currentTimeMinus12Weeks.getFullYear();
    var todayMinus12Weeks = year2 + '-' + month2 + '-' + day2; //today - 12 weeks
    //perform a historical query for the stock code for our chart
    var query2 = 'select * from yahoo.finance.historicaldata where symbol = "' + txtStockCode.value + '" and startDate = "' + todayMinus12Weeks + '" and endDate = "' + today + '"';
    //execute the query and get the results
    Titanium.Yahoo.yql(query2, function(e) {
        var data = e.data;
        var chartData = [];
        //loop our returned json data for the last 12 weeks
        for(var i = (data.quote.length -1); i >= 0; i--)
        {
            //push this timeframes close value into our chartData array
            chartData.push(parseFloat(data.quote[i].Close));
            if(i == (data.quote.length - 1)) {
              twelveWeekStartLabel.text = data.quote[i].Close;
            }
            if(i == 0) {
              twelveWeekEndLabel.text = data.quote[i].Close;
            }
        }
        //raphael expects an array of arrays so lets do that
        var formattedChartData = [chartData];
        //fire an event that will pass the chart data across to the chart.html file
        //where it will be rendered by the Raphael JS chart engine
        Ti.App.fireEvent('renderChart', { data: formattedChartData, startDate:  todayMinus12Weeks, endDate: today } );
    });

The final block of code is doing another YQL call, but this time the call is to the service data table called yahoo.finance.historicaldata which is going to return to us a JSON array of historical data values. In our case, we are searching on the last twelve weeks of data for the selected stock code. Once we have this data, it is simply a case of iterating through it backwards (the oldest item is last in the JSON array), and pushing the Close property value into our new array called chartData. Raphael will use the float values to render the values on the bar chart. Finally, we use Ti.App.fireEvent to fire the renderChart event that we created in the previous step, passing our values through to the chart.html file as we do so!

Run the application in your simulator now and you should end up with a chart being presented in our third box!

Conclusion

Well, as Porky says, that’s all folks! We have covered a lot in this tutorial, including querying and utilising data from Yahoo YQL, implementing a third party library in Raphael JS Charts, and building a useful, nicely designed app with Titanium Mobile while we were at it. I hope you’ve enjoyed following along and I’d love to see what else you do with Appcelerator Titanium. It really is a great mobile platform. Have fun coding!

Series Navigation«Make a Stock Quote App: Search Stock Data with YQL

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Klian

    Nice tutorial.

    Thanks!

  • Eric

    I just downloaded Titanium Developer last week so this tutorial came at the perfect time! It answered a lot of the questions that came up as I have been exploring the software – thanks for a thorough and well explained lesson!

    • http://boydlee.com Boydlee Pollentine
      Author

      I’m glad it helped you out!

  • han

    Really appreciated for perfect tutorials. Thanks!

  • Steve

    Thanks for the tutorial but I have a problem running it.

    The program works fine getting the initial stock quote but fails getting the historical data.

    It seems that the yql historical data table is not available from yahoo but is available at datatables.org.

    The titanium documentation is not very good and I cant find much on yql on their site.

    I looked on the yahoo page for yql and tried adding a USE statement onto the start of my query as they suggest but that didnt work either.

    USE “http://myserver.com/mytables.xml” AS mytable;
    SELECT * FROM mytable WHERE…

    Am I doing something wrong?

    Is it possible to use datatables.org data sources?

    Any help would be gratefully received.

    • http://boydlee.com Boydlee Pollentine
      Author

      Hi,

      Try going to the YQL console online at http://developer.yahoo.com/yql/console/?env=http://datatables.org/alltables.env, and on the right hand side make sure you click “show community tables” link under the Data Tables header section. You should be able to run a query in the console then the same as in the code above, for example:

      select * from yahoo.finance.historicaldata where symbol = “AAPL”

      If that is working then there’s no reason it shouldn’t work in the Titanium app.

      You also might have picked a bad day to try, because I read yesterday that YQL (Yahoo) was having problems with their datatables API. It is worth following @yql on twitter for updates.

  • Karthika

    Thanks for this useful tutorial Boydlee. I used it successfully to incorporate charts in my Titanium app for iPhone. However, I have been facing an issue while trying to use it on android. I am using the “raphael-min.lib”, “g.raphael-min.js” and g.bar-min.js.

    I keep getting a Reference error that says : “Can’t find variable: Raphael at file:///android_asset/Resources/g.raphael-min.js”. The same code works fine for iPhone. Would you have any suggestions on this. Are there any known issues with this for android? Any thoughts would help.

    Thank You!!

    • miki

      Hi,
      i’m facing the same problem as Karthika. is there any solution?

    • http://boydlee.com Boydlee Pollentine
      Author

      I’m not 100% but I think it doesn’t work on Android because droid doesn’t implement WebKit (and all the features inherently necessary to therefore run Raphael JS).

  • Jeff

    The g.raphael lib works for the basics, but has zero documentation.

    Check out graphico and even google charts api for easier libs to work with.

  • http://www.littlebigtomatoes.com gyurisc

    I managed to finished the tutorial but the chart drawing part does not work for me. Is it possible to downloading the final code to find out where I made the mistake?

  • http://www.illumemobile.com Michael Stelly

    I’m new to Titanium as well. I ran step by step through this tutorial. First, thanks for the effort. Since documentation is sparse to non-existent for TS, something is better than nothing.

    However, I get an error when trying to run the final piece with the web chart. The app bombs at this code piece.

    //perform a historical query for the stock code for our chart
    var query2 = ‘select * from yahoo.finance.historicaldata where symbol = ‘
    + txtStockCode.value + ‘ and startDate = ‘ + todayMinus12Weeks
    + ‘ and endDate = ‘ + today + ”;

    The Red Screen of Death reads:
    Result of expression ‘txtStockCode’ [undefined] is not an object. at app.js (line 65).

    One note, I removed what I thought were extraneous double-quotes from the query string but I got the same error.

    • http://boydlee.com Boydlee
      Author

      Hi Joe/Michael,

      First of all, sorry for such a late response on this, but I don’t get notifications of when someone posts a comment and it’s been awhile since I checked this page.

      I just downloaded and ran the code under the latest framework (1.7.5) and it ran fine on both Android and iOS (apart from the graphs used don’t work under Android as stated).

      If you guys can throw your code into a pastie (pastie.org) and either post back here or email it through to me from my website (http://boydlee.com) I’ll do my best to see what the problem is and help work it out for you.

  • Joe

    Did this tutorial myself, and then since my files were not working, I then downloaded and ran the demo files. Both crashed if I entered anything in for a stock symbol. If I leave the field empty I get the proper alert, so it seems like when the function is called something is killing the app. Any ideas?

  • mahendra sharma

    is there any solution to draw chart in a android titanium apps