Data-driven interactive applications with HTML5 and Ajax

Cross-platform Web apps for online or offline use

HTML5 is a general term for a number of emerging web technologies, including standardized rich media and interactivity. HTML5 can also be the basis for developing robust offline applications. For experienced web developers, using HTML5 is more attractive than learning a new compiled language, such as Objective-C or the Java™ language, but HTML5 applications have their own learning curve. This article describes how to successfully mix online content while providing a rich experience for users not connected to a network.

The sample application

This sample application is designed for use on a wide range of desktop and mobile devices. It provides a set of food and drink recipes. Three recipes are static and will be available to users when they're offline. When online, the application will be able to display a "recipe of the day," provided via a web service delivering content via Ajax.

Technology reuse is key to agile web development. This sample application uses two popular open source libraries:

jQuery — Robust cross-platform access to JavaScript and the DOM

— Robust cross-platform access to JavaScript and the DOM jQTouch— Framework for HTML5 mobile applications using WebKit browsers

See Related topics for more information about jQuery and jQTouch.

For best results, develop HTML5 applications using Apple Safari V4 or later, although Google Chrome may also work.

Using jQTouch

You can best manage jQTouch applications as single HTML documents. Each "page" in the application is a different HTML <div> with a unique id attribute. The basic outline of a jQTouch application looks like this:

HTML header and imports Starting <div> Zero or more additional pages as <div> s with unique IDs

Setting up imports

The top of the sample application imports the CSS and JavaScript for the application. It also configures the HTML5 offline cache. Listing 1 provides the necessary code.

Listing 1. Headers necessary for jQTouch and HTML5 offline

<!DOCTYPE html> <html manifest="sample.manifest"> <head> <meta charset="utf-8" /> <title>Sample recipe application</title> <style type="text/css">@import "jqtouch/jqtouch/jqtouch.min.css";</style> <style type="text/css">@import "jqtouch/themes/jqt/theme.min.css";</style> <style type="text/css">@import "sample.css";</style> <script src="jqtouch/jqtouch/jquery.1.3.2.min.js" type="text/javascript"></script> <script src="jqtouch/jqtouch/jqtouch.min.js" type="text/javascript"></script> <script src="sample.js" type="text/javascript"></script> </head>

Enabling HTML5

About the HTML5 markup The simplified DOCTYPE may look strange to programmers familiar with DTDs and XML: Its only purpose is to trigger "standards mode" in web browsers. Because browsers never used DTD-based validation (due to the proliferation of "tag soup" HTML), there is no particular benefit to providing a rigorous DOCTYPE . If you build Web applications with XML-aware tools, you can still use the HTML V4.01 or XHTML V1.0 DOCTYPE s, but the document will not completely validate because of the HTML5 extensions. Similarly, <meta charset="utf-8"> may look unfamiliar, but it is also valid HTML5. See Related topics for a discussion about the simplified syntax in HTML5.

This sample application includes the ability to remain accessible while offline. That ability is enabled by including the manifest attribute. The value of this attribute must be the path to the cache manifest file, as demonstrated below:

<html manifest="sample.manifest">

The cache manifest typically contains two sets of resources:

A list of resources required to be cached for offline use

A list of resources that may only be available when the document is online

The syntax of the cache manifest is quite simple, as shown in Listing 2.

Listing 2. The cache manifest file for the sample application

CACHE MANIFEST # This is a comment and will be ignored # Files specific to this application: sample.js sample.css # Files that are a part of jQTouch: # (See the sample code for a complete list) jqtouch/jqtouch/jqtouch.min.css NETWORK: # These resources will be available only when online: sample.json

The first line is always CACHE MANIFEST . Each resource that may be offline — HTML pages, CSS, JavaScript, images, or any other kind of file — is listed on a new line. When the application is first accessed, the browser inspects the cache manifest, downloads all resources, and stores them for offline use.

Resources following the NETWORK: line are not cached and can be accessed only when the network is available. Although a file is listed here, you can use partial path names. For example, you could include /online/ here and set up the application such that all online-only resources fall under that path.

Forgetting to list all of the resources in the application as offline or online usually results in the whole application failing to be marked as offline-enabled. Other subtleties in the current implementations that can cause confusion include:

The web server must serve the manifest file as type text/cache-manifest .

. The file pointing to the cache manifest (sample.html in this example) does not need to be listed.

Items listed in the manifest will only be reloaded when you modify the manifest itself, not when those resources change.

The web server should serve the manifest file with no-cache response headers.

If the web page references an unmanifested file, the application may not be cached for offline use. Often, this error is silent. In Safari V4 and later, check the Activity panel for any warnings.

If an HTML5 offline application is set up properly, it should be possible to access the application using a browser and server once, then turn off the server or local network access, refresh, and still be able to interact with the content. If the browser says the site cannot be reached, recheck the above list for configuration problems.

Developing with jQTouch

The jQTouch library requires several imports:

jqtouch.min.css. — The CSS for jQTouch itself

— The CSS for jQTouch itself theme.min.css. — The CSS for the current theme (this example uses the default theme)

— The CSS for the current theme (this example uses the default theme) jquery.1.3.2.min.js or later — jQuery itself

— jQuery itself jqtouch.min.js. — The jQTouch main script

— The jQTouch main script samples.js.— Your custom JavaScript, which defines the unique functionality of this application

Mobile web performance tips Following general web best practices, put JavaScript imports at the bottom of the HTML document, just before the close of the <body> tag. For clarity, this example puts them in the <head> . Because mobile devices have high HTTP transactional overhead due to slow wireless connections, it is recommended that you combine multiple JavaScript files into a single library. You do this via an automated build/deployment; it is much easier for humans to develop using small, well-defined, discrete libraries. Similarly, consider the use of CSS sprites in place of multiple images. Also, collapse stylesheets into single documents for deployment.

jQTouch content pages

Each page in a jQTouch application is actually just an HTML <div> that follows some conventions:

It must have a unique id attribute.

attribute. That ID should be linked somewhere in the application using a normal HTML anchor element.

The home page of the jQTouch application is the <div> that has the class value current .

The jQTouch library provides a number of methods to animate transitions from page to page. By default, it uses an attractive "swipe" transition using CSS3. On many WebKit implementations, these transitions are hardware-accelerated, which provides a naturalistic application-like feel. You can find links to these pages on the home page of the jQTouch application, as shown in Listing 3.

Listing 3. The home page, designated by the class named "current"

<div id="home" class="current"> <div class="toolbar"> <h1>HTML5 Sample</h1> </div> <ul class="rounded"> <li class="arrow"><a href="#recipe1">Breakfast Circles</a></li> <li class="arrow"><a href="#recipe2">Slowhand Jackson</a></li> <li class="arrow"><a href="#recipe3">Potato Chip Cookies</a></li> <li class="arrow online-required"><a href="#recipe4">Recipe of the Day</a></li> </ul> </div>

Most jQTouch pages consist of an outer <div> with its unique ID followed by a <div> with the attribute toolbar that contains the page title. Subsequent content is in the form of a list or additional paragraphs.

The rounded and arrow classes are all defined in the main jQTouch style. Depending on the theme installed, their appearance may change. This example uses the default black and gray theme, as shown in Figure 1.

Figure 1. The home page of the sample application

The first three recipes are all static content defined in the same HTML5 page. They each have unique IDs — for example, recipe1 . These IDs are used to target the new page from the home page, as shown here:

<a href="#recipe1">Breakfast Circles</a></li>

Listing 4 contains the source code for this first recipe. Figure 2 illustrates the HTML rendering.

Listing 4. Static content in a jQTouch application

<div id="recipe1" class="recipe"> <div class="toolbar"> <h1>Breakfast Circles</h1> <a class="back" href="#">Back</a> </div> <ul class="rounded"> <li>2C flour</li> <li>1/2C sugar</li> <li>1/2C confectioners sugar</li> <li>2T Earl Grey tea leaves (about 6 bags)</li> <li>1/2t salt</li> <li>1t vanilla</li> <li>1/2C butter</li> <li>Cold water</li> </ul> <p> Pulse dry ingredients in food processor to pulverize tea leaves. Add vanilla, butter and pulse, adding as little water as necessary to form loose dough. Divide into two 2" logs and roll with parchment paper. Chill 30 min.</p> <p> Cut into 1/4"-thick wafers and bake at 375 degrees on parchment until edges start to brown, about 12 min. </p> </div>

Note that this <div> contains one new class value: recipe . The default jQTouch stylesheets do not provide good style control over nested <p> elements, which are being used here for the recipe instructions. Because jQTouch is just a web application, you are free to add custom styling however you like using normal CSS.

In this case, the sample.css contains a few simple customizations, including div.recipe p { margin: 1em; } to provide an attractive margin for recipe instructions.

Figure 2. The home page of the sample application

All three static recipes will be available to offline users because their content is contained inside the HTML page. The next part of this article demonstrates how to mix online and offline content to create a flexible, extensible Web application that provides good offline capability.

Going online

The last recipe item in the list, shown in Listing 5, contains an additional HTML class: online-required .

Listing 5. An item only displayed when the user is online

<li class="arrow online-required"> <a href="#recipe4">Recipe of the Day</a> </li>

In the CSS customization layer for this application, .online-required is set to display: none . This means that by default, the application is assumed to be offline, and no online resources are shown.

How then does the application know when you're online? That code is found in the JavaScript customization script sample.js, shown in Listing 6.

Listing 6. JavaScript to manage online resources

/* Initialize jQTouch on startup. [ See sample code for complete listing ] */ // Standard jQuery method to run code when the browser // has finished loading all resources jQuery(document).ready(function () { // If online, show all online-only resources if (window.navigator.onLine) { jQuery('.online-required').show(); } ...

HTML5 specifies a JavaScript API value window.navigator.onLine . When true, the browser is online and connected to a network. When offline, it can only access offline resources in the cache manifest. In this application, when the application is online, all DOM elements with the class online-required will be shown.

Testing window.navigator.onLine In desktop Web browsers that do not support HTML5, the value of window.navigator.onLine is invariably true , even if the computer does not have a network connection. You will have to introduce a testing framework that can emulate the offline state or test using a mobile device only.

Accepting online data

An efficient method to populate a jQTouch application with online data is to provide skeleton pages to hold that data in advance. Listing 7 shows the <div> for the online-only recipe.

Listing 7. Placeholder jQTouch page for the online-only recipe

<div id="recipe4" class="recipe"> <div class="toolbar"> <h1>Recipe of the Day</h1> <a class="back" href="#">Back</a> </div> <!-- The recipe will be populated here --> </div>

Now, in the custom JavaScript, you need an event handler to request the recipe and populate the HTML page with the results. The obvious approach would be to define an onclick handler for the #recipe4 ID.

However, jQTouch overrides the normal click behavior to accomplish its magic of moving from page to page. Instead, you can take advantage of the fact that CSS3 transitions fire start and end events. You can bind to these events using jQuery, even though the events are not native to jQuery. Following is the code:

jQuery('#recipe4').bind('pageAnimationStart', function () { ... });

Not seeing the sliding transition or Ajax load? As of this writing, only Safari versions 4 and 5 and Mobile Safari show the visual transition and fire the pageAnimationStart event. If you need to support other WebKit browsers, use a different event.

The pageAnimationStart event fires almost immediately after the click event. When the transition finishes, pageAnimationEnd fires. I prefer to associate most actions with the start event, as that gives the browser some time to collect the data while the user is watching the animation.

Populating data via Ajax

All that remains is some normal Ajax interaction. This example assumes that the result format will be JSON data. In this case, the data comes directly from a JSON file — sample.json, shown in Listing 8.

Listing 8. JSON data containing the recipe of the day

[ { "title" : "Doggie Delight", "ingredients" : \ ["1 cup dry kibble", "1 pound butter", "1 beef bouillon cube", \ "2 tbsp oregano" ], "instructions": "Combine all ingredients in bowl.\ Season to taste. Serve immediately." }]

Listing 9 contains the code to take this data and populate the placeholder <div> .

Listing 9. JSON data to populate the placeholder

jQuery.ajax({ url: "sample.json", success: function (data) { // Set the recipe title jQuery('#recipe4 h1').text(data[0].title); // Create a UL and add each recipe item to it var ul = jQuery('<ul class="rounded">'); jQuery.each(data[0].ingredients, function (index, item) { jQuery('<li>').text(item).appendTo(ul); }); // Add the ingredients list and the recipe instructions jQuery('#recipe4').append(ul).append( jQuery('<p>').text(data[0].instructions));

Figure 3 shows the final rendering of the dynamic data.

Figure 3. The dynamic recipe in a browser

Conclusion

More new mobile devices arrive on the market each day. While it's possible to develop custom native applications for each new platform and hardware, there's opportunity for small, agile teams to create cross-platform mobile web applications with similar performance characteristics. Whether as prototypes for larger native applications or as first-class sites themselves, mobile web applications are attractive for developers who already know HTML, JavaScript, and CSS.

The JavaScript APIs available in HTML5 mean that web apps have access to more hardware data than ever — not just network status but orientation, location, and other features. In many cases, these APIs already enjoy broad support in popular mobile browsers.

Web developers should not feel left behind in the rush to mobile application development. You may already have all the skills you need to develop for smartphones, netbooks, and tablets.

Downloadable resources

Related topics