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.

Friday, May 25, 2012

Cordova (PhoneGap) and AdMob Together: iOS Version

Ads are one the easiest ways for a developer to get paid for an app. Apache Cordova, the new name for PhoneGap, is one of the easiest ways to develop apps for the iOS and other platforms. The problem is how to combine the two of them? Nothing in the official documentation of either says how to do it. After a long evening of hacking, I have gotten it to work for me and here is how I did it.


Some assumptions before we begin: 

  • XCode version 4.3.2
  • Apache Cordova version 1.7.0
  • AdMob version 6.0.3 (6.0.4 uses the device's UDID, which creeps me out)


1. Get Your App Working


The first step is to get your Cordova app working. In my case I am using my calculator example that I introduced a few tutorials ago. You can use whatever app you have just keep in mind that AdMob will need 320x50 pixels, so be sure to leave it some room. 


2. Copy the AdMob Files


Now we copy the AdMob files into the project. Right-click on your project name in Xcode, choose Add Files to "your project name"... Select all of the files except "README.txt" and the "Mediation" folder. 


3. Add Some Missing Frameworks


The following frameworks need to be added to your project:

  1. AudioToolbox
  2. MessageUI
  3. SystemConfiguration
  4. CoreGraphics
Double click the project name to show the settings page. Click the tab marked, "Build Phases". Click the accordion marked, "Link Binary With Libraries". Click the plus sign in the lower left corner, in the dialog box that appears select all of the missing frameworks, then click the "Add" button. 

4. Add the Code

In the file, MainViewController.h, add the import statement:

#import "GADBannerView.h"

Add the banner view declaration:

@interface MainViewController: CDVViewController {
  GADBannerView *bannerView_;
}
@end


Added and define the MY_BANNER_UNIT_ID near the top of MainViewController.m.

#define MY_BANNER_UNIT_ID @"YourPublisherId"

5. Modify the viewDidLoad
After the [super viewDidLoad] add the following code:


6. Modify the viewDidUnload

Release the bannerView_ in the viewDidUnload method:

[bannerView_ release];

7. Modify the Cordova.plist

In order for AdMob to get ads from its server, you need to permit it. Expand the "Supporting Files" folder. Then click the "Cordova.plist". Open the ExternalHost, click the plus sign, and the type "*". The asterisk says to permit all outside connections to go through. You can make this list as exclusive as you'd like. If you don't do this you will see the following error in Xcode's console output section:

ERROR whitelist rejection: url='http://media.admob.com/sdk-core-v40.js

8. Try It Out

Try launching your app and you should see the Google banner ad at the bottom of the page. If you click it, it will take you to another page. 

If you need a bit more help I have include the full source code to the Cordova calculator with the AdMob ad. Don't freak out, the name of the project is DelMe3, not calculator. It is a huge project though at 10.6 MB. I wasn't too sure what I could safely leave out of the project, so I included it all.
  

Full Source Code, 10.6 MB


Tuesday, May 22, 2012

Responsive Design in jQuery Mobile using CSS3

Wouldn't it be nice to have one set of code which supports both smart phones and tablets. I don't mean a stretched implementation of the smart phone UI, which looks awkward and awful on a tablet. No, I mean a smart UI which dynamically shows and hides parts of itself in response to the amount of available screen real estate. This is the definition of one of the hottest internet catch phrases, "responsive design".

Responsive design is a troubling topic for me. Everyone has seen those magical websites which scale to fit whatever device they are running on. They usually work by sending all of the markup for the largest possible screen down to even the smallest device and letting CSS position everything so it look right. When non-engineers see those sites they get that glazed look of love in their eyes. I see those sites and the first thing I do is proxy up my iPhone and watch in disgust as my phone is choked by all of the data being jammed down its binary throat. Don't get me wrong, this style of responsive design has a place, it just isn't on a portable device, especially not over a 3G connection.

Examples of Responsive Design

For this week's tutorial, I have made my first in-depth pass at responsive design in jQuery Mobile. In it I will use CSS3 media queries to enable/disable parts of the UI. And please don't call me a hypocrite yet. Since only a few classes will be tweaked   

The App

The application, like all of the apps in my tutorials, is simple. It is a squirrel viewer program. You select from one of three types of squirrels, and the viewer shows you a picture of the squirrel. 

Above is how the UI looks on a smart phone. It consist of two pages, the first allows the user to select a squirrel, the second to see the squirrel. But what happens when we have more room, like when the user is using a tablet? 


With the increased real estate, we allow the user to see their squirrel as they select it. Also, since there is no need for a second screen, we remove the "See Your Squirrel" button. And if the user should put their tablet in portrait mode, we change the UI again.


Now instead of elements being side-by-side, the UI is stacked. Now that you have seen the app, let see how it is done.

CSS3 Media Queries and HTML (that's right no JavaScript)

The main keys to a dynamic UI are CSS3 media queries. They allow us to define classes based upon the metrics of the current device. If we keep in mind that the 'C' in CSS stands for cascading, we will realize that what we can do is define a base set of classes at the beginning of our style sheet and then redefine some classes in response to the metrics of the device. 

Two classes are the star of this application with a third in a supporting role. The star classes are 'content-primary' and 'content-secondary'. 'content-secondary' is a class for the div which surronds the radio buttons and the 'See Your Squirrel' button. 'content-primary' wraps the image of the squirrel on page one. 

Normally both of the star classes are on and they divide the width the screen between them. When the screen is in tablet, portrait mode, we tweak the width of both class to 100%. This cause them to stack on top of each other. Finally when the screen is in smart phone dimensions, we turn off 'content-primary' and keep 'content-secondary' at 100% width. The results of this is that the user only sees the radio buttons and the image of the squirrel is gone.

The class in the supporting role is, 'show-page-button'. Normally is set to 'display: none;' which turns it off. But when we are in smart phone, two page mode, we set it to 'display: block;', which turns it on and reveals the 'See Your Squirrel' button.

A little bit of JavaScript

OK, there is a little bit of JavaScript. In the code for page one, we hook the change event for the input type radios. Each of these inputs holds a value which is the path to its image. The handler for the event copies the new image path into src property of the img tag, all of them. That is the final trick of application, whether the app is in single or two page mode, it always updates the images on both pages. Don't worry, the extra update has almost no affect on performance and no extra code. It is important to note that not all jQuery manipulators will modify all of the elements in a collection, but the attr() manipulator does.

Is it possible to read media queries with JavaScript? Yes, it is possible, but it is more efficient to let CSS do it. Plus it also makes your code cleaner. If you insist to do it in code, media queries are access through the styleMedia property of the window object. 


If you omit the "@media" element, the string passed to the matchMedium element matches that of the media query in the style sheet and not accidentally.

Summary

Cellphone displays continue to increase in size. The code is vulnerable to these changes. There are already super phones whose dimension's match those of tablets, only there orientations are different. So be prepared to have to tweak the dimensions in the media queries. 
There are more files in the project which I haven't mention since they are part of my standard bag of tricks. Be sure to download the complete project to check them out.

Download the Source






Thursday, May 17, 2012

jQuery Mobile Skeleton App

The skeleton on Windows Phone 7, iOS, and Android
Most modern IDEs include templates, a way to begin a new project without having to write all of the code from scratch. In order to speed up and standardize my jQuery Mobile development, I created a skeleton. The skeleton serves the same purpose as a template for my own projects.

There isn't anything difficult going on with the skeleton, but I will walk you through the application anyways to make sure that you understand everything.

The Files

First, I should explain the files which are included in the project. At the base of things are jQuery and jQuery Mobile core files. In a production app, I would normally get these files from a content delivery network CDN, but during development it helps to have the files local. 

Next, we have the app.js file. This is my application's core file. It contains the Kernel, which sends page events to their handler. And Events, which hooks all of the page events and feeds them to the Kernel. The last part of the file are the two page handler functions. 
The skeleton app's files

The final JavaScript file is the hideAddressBar.js. I am not completely in love with this solution the Android address bar problem, but it mostly works. Every time we receive a "pageinit" event we call the hideAddressBar function.

The HTML files should be nothing surprising so there is no real need to explain them except for the attribute, data-rockncoder-jspage="page2". This attribute is used to join the HTML to its corresponding JavaScript object. The Kernel uses it to determine the name of the JavaScript object and call the appropriate page event handler if it exists.

I hope this code helps you to write something cool. If it does drop me a line and an URL. 




Tuesday, May 15, 2012

jQuery Mobile Calculator

Click here for a PhoneGap Calculator

WORKING DEMO

Here is an easy to get your head around jQuery Mobile (JQM) project, a simple calculator. I like this project because it helps to break want-to-be web app program out of the web site mentality. The entire app consist of a single page and about 200 lines of code. Let's begin our explanation with the Kernel which is near the beginning of the file app.js.

The Kernel

The Kernel's function is to tie HTML and JavaScript files together. We map all of JQM's page events to the Kernel. First we assign the event name to the variable eventType. Then we pull the page's JavaScript file name from the psuedo-attribute, "data-rockncoder-jspage" and assign it to the variable pageName. The final lines of the Kernel call the event's handler in its page code, only if the handler exists. The long if statement simply makes sure that there is a handler before it is called. Rockncoder.App follows the Kernel. Its only function is to hook all of the page events and direct them to the Kernel.

The Page Code

Next comes the page's code in RocknCoder.Pages.calculator. We use an object literal to hold all of the pages code. At some point in the future I will be changing this code to use a function not an object literal, but I have been doing for so long like this the habit is hard to break. A better implementation would be to do something like a "Revealing Module Pattern", which would also give us the ability to hide our local variables.

In the page's code we handle three events: pageinit, pageshow, and pagehide. Any event which is not  defined is not called by the Kernel. The first event handler, pageinit, is the JQM's equivalent to jQuery's document ready event. This is the place to do any page level initialization code. Here we initialize our Android address bar hider. The second event, pageshow, is called after JQM  has rendered the page. In this handler we initialize the calculator, the poorly named RocknCoder.Display and hook all of the calculator's keys. The final event is pagehide, which we use to unhook the events. Truth be told, this event will probably never be called since  there is only one page and JQM will have no page to switch to  and therefore no need to hide the current page.

The Calculator 

The meat of the calculator is in RocknCoder.Display. I am not going to explain its function other than to say it is a very simple calculator. We could have created a more robust calculator by using the Command Pattern. Then we could have been able to have features like undo and a much cleaner separation of concerns.  But then it would not have been so light in code. 

Summary

Although this is a very simple project, it has the ability to grow. By following the example of RocknCoder.Pages.calculator, you can add other pages, just remember to add HTML markup along with JavaScript. For each use of the psuedo-attribute "data-rockncoder-jspages='xxx'" be sure to create a match JavaScript literal with the name "RocknCoder.Pages.xxx.

Next week I will turn the calculator into a PhoneGap project and show how to get it to run on iPhone, Android, and Windows Phone 7.

Complete Source Code

Tuesday, May 8, 2012

Here is the starter code for session 2 of jQuery Mobile - Project Based 4 Week Training.

JQMCalculator Start

Monday, May 7, 2012

Mobile Web Development with Tunnlr


If you are into mobile web development, you may want to check out Tunnlr. What is Tunnlr? If you are into Rails or Facebook development, you may already be hipped to Tunnlr. But for those of us who weren’t, it is a port forwarding service. Why would you want to use it for mobile web development? Well, Tunnlr allows you to make your unpublished website visible publicly temporarily. Why would you want to do that? Here are a few reasons why:


  1. To test show your site to someone who is remote
  2. To test your site at 3G speed
  3. To interactively debug your site from a phone

Tunnlr will assign you a publicly visible URL, which points to your dev box. This can be a great way to allow others to see it. Simply send your Tunnlr URL to people you would like to see your site.  Tunnlr isn’t free, but it is available at the reasonable fee of $5 a month after a 90 day trial.

How Does It Work?

To quote the Tunnlr website:

Tunnlr uses SSH remote tunneling. It securely connects a port on your local machine to an open port on our public server. Once you start your Tunnlr client, the web server on your local machine will be available to the rest of the world through your special Tunnlr URL.

Tunnlr uses public-key cryptography to secure the communication between their server and your machine. So you will need to generate a public/private key pair. I recommend creating it before getting started.

Create a Public/Private Key Pair
  • Check the ssh directory of your machine to be sure that you don’t already have a key pair
    • from Terminal, ls ~/.ssh
    • You will be looking for two identically named files, one without an extension and the other with a .pub extension, for example: identity and identity.pub
    • In the above example, identity.pub would be your public key - this is the key that you will give to Tunnlr. The other is your private key. NEVER GIVE IT OUT.
  • If you need to create a key pair:
    • ssh-keygen -t dsa
    • You will be prompted for a key name, if you don’t enter one, it will use, id_dsa, by default. You also be asked for a passphrase, you can simply press enter and skip entering. Two files will be created: id_dsa and id_dsa.pub. Your public key will be id_dsa.pub.
  • Copy the public key to the clipboard:
    • cat id_dsa.pub | pbcopy

Sign Up
  • Go to http://tunnlr.com and click the “Sign Up” tab
  • Click the “Single” link and fill out the form
  • You will be sent a verification email, once you respond you will have access to Tunnlr via your own URL. Be sure to use this URL when you login.
  • Go to your Tunnlr URL address and log in
  • Your home page will show your Tunnlr URL
  • Copy your public key into the text area labelled, “Authorized Keys”
  • Click the “Save” button
  • Near the bottom of the web page, click the link “How do I manually start a tunnel? (+)”
  • The ssh command line will be displayed, copy it for the next part

Start the Tunnel


ssh is the Mac’s built-in implementation of OpenSSH. There is no graphical interface for ssh, so you will have to use terminal to configure it. The exact command line for your tunnel may be different than mine, so be sure to copy the command line exactly as it appeared on screen from the previous section. In my case, I want Tunnlr to talk to my Mac’s web server, so I use port 80.




Working with a PC Virtual Machine

Most of my backend servers use Microsoft’s ASP.NET MVC framework. On my Mac, I use Parallels 7 to create a PC virtual machine. In order to talk to the PC virtual machine, you just need to use its ip address instead of the four zeros above. My test website is running on port 8200 on ip address 192.168.1.91, so the command line is:

When you are through testing your website just stop ssh by typing ctrl-C. If you would like to be more secure you can kill the tunnel on Tunnlr by simply clicking the “Kill Old Tunnels” button below Tools on the right hand side.

Summary

If everything worked-out right you should be able to hit your website from any device connected to the Internet. Remember the tunnel is only open while ssh is running on your Mac. If you close the terminal or control-C the program, the connection is terminated.


References

http://tunnlr.com

Wednesday, May 2, 2012

jQuery Mobile Project Based Training: Session 1

I would like to thank everyone who attended last night's session either live or via the webcast. It was great to meet all of you and thanks for all of the great questions. Here is the link to all of the code presented last night:

Session 1 Source Code

Having learned from last night, I will post Session 2's source code Monday evening. In Session 2, I will show you how to built a calculator.