Login Register

Using Dojo Offline

Let's dive in and start using Dojo Offline.

Download Dojo Offline SDK

First download the Dojo SDK and unzip it.

SDK Layout

When you unzip the SDK, you will find the following directories:

  • dojo - The core of Dojo
  • dijit - The Dojo widget system, named Dijit
  • dojox - Optional Dojo extensions

Dojo Offline is an optional Dojo extension, and is therefore located in the dojox directory.

If you are looking to track down Dojo Offline's source code, most of it is in dojox/off/. The Dojo SQL layer is in dojox/_sql/, while Dojo Storage is in dojox/storage/. An autogenerated, JavaDoc-like API is available. When looking at the API docs or source code, many advanced options are available to deeply customize Dojo Offline; you can almost always safely ignore these unless you are an advanced user, and they usually say "For advanced usage; most developers can ignore this" in their documentation.

Demos

Dojo Offline has three main demos, a Hello World example, a more complicated web-based editor named Moxie that includes an example server-side written in Java, and a demo of Dojo Offline's SQL cryptography. You can play with hosted versions of the Hello World example here; a hosted version of the Moxie editor here; and the SQL cryptography demo here

If you want to study the demo examples' source code, the Hello World example is located in dojox/off/demos/helloworld/, while the Moxie editor is located in dojox/off/demos/editor/. You can see the SQL cryptography demo source in dojox/_sql/demos/customers/customers.html.

The Hello World example has no server-side requirement; Moxie, however, includes a full Java server-side that you can use as a template and scaffolding. Running the server-side of Moxie is simple. Make sure you have Java 1.5+ installed, and then just type: java -jar editor.jar
while inside the directory dojox/off/demos/editor/server/, and the Moxie server-side will start running, with an embedded web-server (Jetty) and relational database (Derby) already set up for you.

In a web-browser, you can now go to the following URL:

http://localhost:8000/dojox/off/demos/editor/editor.html
to run Moxie against the local server you just started.

For more details on the server-side portion of Moxie and how to build see the README file at dojox/off/demos/editor/server/README.

Creating an Offline Application

Now that you have awareness of the SDK, it's file layout, and the provided demos, let's get down to illustrating what you need to do to create an offline-aware application using Dojo Offline.

Bring in Dojo and Dojo Offline

For our example source code we will pretend that you are creating your application with the Dojo Offline SDK in a subdirectory named offline-sdk.

First, bring in Dojo and Dojo Offline:

<script type="text/javascript" src="offline-sdk/dojo/dojo.js" djConfig="isDebug: true"></script>
<script type="text/javascript" src="offline-sdk/dojox/off/offline.js"></script>
isDebug is a useful flag that when set to true will print out debug messages, and when set to false will hide them. In your own code you can add console.debug("some message"); to have these printed out to help with debugging. If you are using Firefox in conjunction with Firebug then these messages will print out to the Firebug console; otherwise they will print on to the web page itself, such as in Internet Explorer.

Notice that we do not bring in Dijit; Dojo Offline has no dependencies on Dijit, the Dojo Widget system, helping to keep your code size smaller. We only include it in the SDK because Moxie, the example editor, uses the Dijit rich text editor.

Next, bring in Dojo and Dojo Offline's style sheets:

<style type="text/css">
        @import "offline-sdk/dojo/resources/dojo.css";
                       
        /* Bring in the CSS for the default Dojo Offline UI widget */
        @import "offline-sdk/dojox/off/resources/offline-widget.css";
</style>

Dojo Offline Widget

Dojo Offline includes a default offline widget that does much of the hard work of providing a good offline UI to your end-users. It updates the user with online and offline feedback; provides sync messages; and delivers help and instructions on using your application offline. If Dojo Offline did not provide these you would have to roll them yourself, so providing a default UI makes developing offline applications easier.

Getting this widget is as easy as adding a bit of HTML to your page, with a special, predefined ID:

<!--
        Place the Dojo Offline widget here; it will be automagically
        filled into any element with ID "dot-widget".
-->

<div id="dot-widget"></div>
When the page loads, Dojo Offline will automatically find an element with the ID dot-widget and automagically embed the offline widget.

The offline widget is a small, self-contained unit that provides feedback to the user, giving you a bunch of great functionality for free.

Here is a screenshot of Moxie, with the offline widget circled:

For more screenshots of the offline widget and a full description of what it gives you for free, see here. It is recommended that you use the offline widget in your own offline applications unless you are an advanced developer; information on customizing its look and feel, including dropping it, can be found here.

JavaScript

Let's take a look at our JavaScript now. All you have to do is set your application name:

// set our application name
dojox.off.ui.appName = "Example Application";

The Offline Widget will use your application name to customize it's user-interface; that is how the offline widget, for example, can insert "Learn How to Use Hello World Offline" into its instructions without you having to manually edit the offline widget's HTML.

Slurp! Bringing Your Application's Files Offline

For your application to be able to work offline, you must make sure that all of your JavaScript, HTML, CSS, etc. are available even when away from the network. While the browser may have these in its cache, you can't depend on this. The underlying Google Gears plugin that Dojo Offline uses makes it possible to specify what files you want to have available when offline, such as your JavaScript.

It can be tedious, however, to build up a full list of all your files, especially if you have many images and supporting libraries and are doing rapid development. Dojo Offline provides a single method, named slurp(), that will slurp the page and automatically figure out all of the resources you need to have available offline:
// automatically "slurp" the page and
// capture the resources we need offline
dojox.off.files.slurp();
The slurp() method is awesome; it will automatically scan your page and quickly figure out all your JavaScript and CSS files; grab any IMG tags in your source; and even grab any background URLs you might have in your attached CSS. The only thing it doesn't do is look at inline styles or scan your JavaScript for dynamic additions.

You can also manually add files if you want or need to; more information here.

slurp() has a nice debug method if you want to see all the files that have been slurped; make sure that Dojo's isDebug is true, and call dojox.off.files.printURLs() after the page and Dojo Offline are finished loading (more details on how to know when Dojo Offline is done loading in the next section).

During development, as you hit your offline application, it will always be pulled from the Google Gears file cache first, even if you are online. This can sometimes make development tricky and tedious. If you just made a change locally, hitting your web application, even if you are offline, will cause the older version to be pulled in first.

To make this process easier, I have created a bookmarklet that you can drag to your links toolbar in your browser. View this page to get the bookmarklets for Firefox and Internet Explorer.

These bookmarklets clear the Google Gears cache, removing all of the files that slurp() added offline. Press it during development when you have made a new change that you want to show up; you must press it when you are at your web application (i.e. it won't work if you just press it when you are at a different or blank page). Then, refresh the page to see your change.

Knowing When Dojo Offline Can Be Used

Dojo Offline can't be used until the page is finished loading and Dojo Offline itself is finished initializing (such as the offline widget finishing being placed into the page). You should wait until the page and Dojo Offline are finished loading, and then your application can start doing its own custom thing:

var myApp = {
        initialize: function(){
                alert("Dojo Offline and the page are finished loading!");
        }
}
// Wait until Dojo Offline is ready
// before we initialize ourselves. When this gets called the page
// is also finished loading.
dojo.connect(dojox.off.ui, "onLoad", myApp, "initialize");
                       
// tell Dojo Offline we are ready for it to initialize itself now
// that we have finished configuring it for our application
dojox.off.initialize();

myApp is some object that will hold all of the methods for our application; myApp.initialize() is the method in particular that would initialize our application on page and Dojo Offline load in some way. We use dojo.connect to connect to the dojox.off.ui.onLoad event; when this fires, myApp.initialize() is called. At this point we could begin to manipulate the DOM on the page, since it is loaded, or do further actions specific to your application; in this case we just print an alert message.

The final call to dojox.off.initialize() is there to tell Dojo Offline that we are done configuring it, and that it can now initialize itself; we don't want Dojo Offline to initialize itself before we have set our appName and called slurp(), for example, so this final call tells Dojo Offline that we are finished doing configuration.

Let's look at all of our code so far in this tutorial:

<html>
        <head>
                <script type="text/javascript" src="offline-sdk/dojo/dojo.js" djConfig="isDebug: true"></script>
                <script type="text/javascript" src="offline-sdk/dojox/off/offline.js"></script>
                <style type="text/css">
                        @import "offline-sdk/dojo/resources/dojo.css";
                       
                        /* Bring in the CSS for the default
                           Dojo Offline UI widget */
                        @import "offline-sdk/dojox/off/resources/offline-widget.css";
                </style>
                <script>
                        // set our application name
                        dojox.off.ui.appName = "Example Application";
                        // automatically "slurp" the page and
                        // capture the resources we need offline
                        dojox.off.files.slurp();
                        var myApp = {
                                initialize: function(){
                                        alert("Dojo Offline and the page are finished loading!");
                                }
                        }
                        // Wait until Dojo Offline is ready
                        // before we initialize ourselves. When this gets called the page
                        // is also finished loading.
                        dojo.connect(dojox.off.ui, "onLoad", myApp, "initialize");
                       
                        // tell Dojo Offline we are ready for it to initialize itself now
                        // that we have finished configuring it for our application
                        dojox.off.initialize();
                </script>
        </head>
       
        <body>
                <!--
                        Place the Dojo Offline widget here; it will be automagically
                        filled into any element with ID "dot-widget".
                -->

                <div id="dot-widget"></div>     
               
        </body>
</html>

Important: I've noticed over and over in the frameworks I have created, such as Dojo Storage and the Really Simple History library, that developers get confused about an important point. Notice that configuring Dojo Offline must be done before the page loads:

<script>
        // set our application name
        dojox.off.ui.appName = "Example Application";
        // automatically "slurp" the page and
        // capture the resources we need offline
        dojox.off.files.slurp();
        // ...
        // Wait until Dojo Offline is ready
        // before we initialize ourselves. When this gets called the page
        // is also finished loading.
        dojo.connect(dojox.off.ui, "onLoad", myApp, "initialize");
       
        // tell Dojo Offline we are ready for it to initialize itself now
        // that we have finished configuring it for our application
        dojox.off.initialize();
</script>

Notice that our calls to things like dojox.off.ui.appName and the dojo.connect to dojox.off.ui are at the top-level of the script tag done before the page loads; if you were to put these into a function and call that after the page has loaded, Dojo Offline will not work:

<script>
// this is wrong -- don't do this because it will not work
window.onload = function(){
// set our application name
	dojox.off.ui.appName = "Example Application";

	// automatically "slurp" the page and
	// capture the resources we need offline
	dojox.off.files.slurp();

	// etc.
}
</script>

At this point we have the shell of an offline application using Dojo Offline and Google Gears. Let's delve into common issues that come up with offline applications now, such as toggling your user-interface in different ways if you are on- or off-line; knowing the network status; syncing; and more.

Network Status

In the background Dojo Offline is checking to make sure that your web application is available on the network (for technical details on what it is doing see here). If your web application disappears or appears within a few seconds (five to thirty seconds), Dojo Offline will detect this and automatically inform your application so that you can move on- or offline, such as enabling or disabling UI elements that might not be available offline. Dojo Offline fires an event when the network status changes, which you can easily subscribe to using Dojo Connect:

dojo.connect(dojox.off, "onNetwork", function(status){
   if(status == "online"){
      alert("We are online!");
   }else if(status == "offline"){
      alert("We are offline!");
   }
});

By default, the Dojo Offline UI widget also subscribes to these events, handling most of the work of informing the user when they are on- or off-line so you don't have to:

As you will see in more detail when we get to syncing later on in this tutorial, Dojo Offline also does an automatic sync when the network reappears:

Another useful property is dojox.off.isOnline. At any time in your code you can check dojox.off.isOnline to see if you are on- or off-line and change your applications behavior appropriately. This will be true if we are online and the application is available on the network, and false otherwise.

A common pattern in offline applications is the need to have a UI element do different things when you are on- or off-line. For example, you could imagine a SEARCH button that when you are online will shoot off a network request to the server to do a search, while when offline will do a SQL search on the local Google Gears datastore. A common way to handle this is to use Dojo Connect and the dojox.off.isOnline property:

var searchButton = dojo.byId("searchButton");
dojox.connect(searchButton, "onclick", function(evt){
   if(dojox.off.isOnline){ searchOnline(); }
   else{ searchOffline(); }
});

This can be a nice pattern to separate on- and off-line code and easily toggle between them without littering lower level code with dojox.off.isOnline network checks; just do it at the dojo.connect level instead, which is cleaner.

Demos crash Firefox on Mac OSX

I just installed Google Gears and tried the demos on the google website and they worked fine. But on trying the hosted Hello World, Moxie & SQL demos on Firefox, they crashed. I have FF 2.0.0.7 + Gears 0.2.4.0.

thanks
Jayant

Dojo Offline problem

I agree: Dojo Offline crashes on Firefox 2.0 but is ok on IE 6
Bug on Firefox is a perpetual Synchronization UI

None of the demos work

I just installed Gears and tried the simple hello world app (http://codinginparadise.org/projects/dojo_offline/latest/offline-sdk/doj...), but I get errors:

[Exception... "'Name cannot exceed 64 characters: dot_store_http___codinginparadise_org_projects_dojo_offline_latest_offline_sdk_dojox_off_demos_helloworld_helloworld_html.' when calling method: [nsIDOMEventListener::handleEvent]"  nsresult: "0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)"  location: ""  data: no]

Line 0

thanks
Jayant