HTML5 - HTML5 Offline Applications: 'Donut Hole' Caching

HTML Offline Applications allow you to create applications that work without an Internet connection using technologies native to the Web browser. Pages included in an offline application are listed in the application manifest and thus are served from the application cache whether a connection to the Internet is present or not. Sometimes, however, if an Internet connection is available, you may want to display some data from the server without requiring the user to change pages.

Scott Guthrie introduced the concept of “donut hole” caching in ASP.NET, where a cached page may include small windows of content that are updated independently of the cached page. This tutorial demonstrates how to implement an offline page that makes an AJAX call when connected to the Web in order to display live data to the user. When offline, the page simply renders default data in the page.

There are a number of practical reasons to implement an offline application. While most developers first think of the mobile context when considering who might use an offline application, almost any Web site can benefit from having some availability regardless of connection status. A site’s Home and Contact Us pages are excellent candidates for offline availability so users can get some basic information about the organization, even when disconnected.

Building the Application

The example in this tutorial demonstrates how to cache a “Contact Us” page that displays notifications of upcoming events to users. When a user is connected to the Web, live event listings are displayed; otherwise, a telephone number prompts the user to call for event information. This approach keeps the user informed and connected with or without access to the public Web.

Figure 1 depicts how the page is rendered for offline viewing, while Figure 2 shows how the page looks when served from the application cache but the computer is connected to the Web.

Figure 1 When the User Is Working Offline, the Application Prompts Him to Call for Event Information

Figure 2 When the User Is Connected to the Internet, the Application Shows Event Information from the Server

The Manifest

The application manifest acts as the master list of resources included in the offline application. Figure 3 shows the full manifest file for this example.

The file begins with the requisite CACHE MANIFEST header and includes a versioning comment to allow changes in listed files to propagate to the client.

Next, the CACHE section references the contact page intended to be available to users regardless of connection status. The contact page references a style sheet, jQuery and a map image indicating the physical office location.

Finally, the NETWORK section is needed in this instance to ensure access to the events.htm page (shown in Figure 4). The reason this page isn’t included in the CACHE section is because in the real world the events page would be built dynamically as a server-generated page. Caching a page like this would defeat the purpose of making live event data available to the user when connected to the Web. With the events page listed in the NETWORK section rather than the CACHE section, the Application Cache API won’t attempt to cancel the request to the page. Ultimately, the page’s inclusion in the NETWORK section tells the browser to always attempt to fetch the page from the Web regardless of connection state.

Note that the manifest is implemented as an ASPX file in order to disable browser caching of the file. You may prefer to disable caching on the Web server via configuration settings, but this approach is used here to make the sample code more portable for demonstration purposes.

The Contact Us Page

The contact page HTML, shown in Figure 5, is implemented as you might expect regardless of whether the page is being optimized for offline access. The most important detail to note in the HTML for the page is the contents of the paragraph with the ID of localMessage. This container holds the content that’s displayed when the user is working offline; that content is replaced on-the-fly when a connection to the Internet is available.

The first order of business is to process any updates to the page loaded in the application cache by handling the updateready events. If the application manifest changes, all the files listed in its CACHE section are copied to the client. When new versions of the files are available, the updateready event fires and the page can load the latest version of the contact page from the cache by calling applicationCache.swapCache. Finally, once the latest version is loaded into memory, the page is reloaded in order to display the changes to the user:

Next, the page needs a mechanism to detect whether the computer is working in a connected or disconnected state. The isOnLine function simply wraps up a call to the read-only navigator.onLine Boolean property. This encapsulation is handy because, should you want to override the value for testing purposes, you can un-comment the return false line and test the page’s offline behavior without having to actually disconnect from the Web:

By the way, using navigator.onLine as the sole mechanism for detecting online status is a bit rudimentary. For a more robust way to detect online status, please read the tutorial, “Working Off the Grid with HTML5 Offline,” by Paul Kinlan.

The showEvent function is responsible for implementing the “donut hole caching” functionality for the HTML offline application. The function first detects the connection status of the computer and then either fetches and renders live event data or just shows the event information that already exists in the page.

If the isOnLine function returns true, the local message is hidden from the user and an AJAX call to the events page is initiated. When a response from the asynchronous call is recognized, the resulting HTML is fed to the eventList container and the table is styled with zebra striping.

If, on the other hand, the computer is working offline, the local message is displayed to the user like so:

Wrapping Up

Even though pages loaded into the application cache are served from the cache whether the computer is connected to the Internet or not, you can construct your pages to take advantage of online resources when they’re available. “Donut hole caching” works by making an AJAX call to the server when a connection is available and then rendering the results to the user. If the page is in a disconnected state, the application quietly renders data already available on the page—it’s the best of both worlds!

Craig Shoemakeris a software developer, podcaster, blogger and product guidance manager for Infragistics. As host of the Polymorphic Podcast and Pixel8, Shoemaker does what he loves most—making contributions to the community and drawing the best out of industry luminaries. Shoemaker is a Microsoft ASP.NET MVP, ASP Insider and guest speaker at various developer user groups and tradeshows. He’s coauthor of “Beginning ASP.NET 2.0 AJAX” (Wrox, 2007) and “Beginning ASP.NET AJAX” (Wrox, 2006), and a contributing author to Pluralsight, TekPub and CODE Magazine. In his spare time Shoemaker enjoys looking for a haystack in which to hide his prize needle collection. You can contact him on Twitter @craigshoemaker or by e-mail CShoemaker@infragistics.com.