Adding a Custom “Page Load Failed” Behavior to A jQuery Mobile Application

In this tutorial you will create a simple jQuery Mobile app with features that can be used without an active connection with a remote server, and features that require an active connection. If the app is offline and the user tries to access an online-only feature, you will pop up a message letting the user know that the feature will become available when the app is back online. To achieve this you will override the default “page load failed” behavior in jQuery Mobile.

online-offline-5

This example is based on one of my recent projects; a service calls app where features such as creation of estimates and updating of job statuses are used on the field and without an active connection to the server in the office, while backoffice features that handle sensitive information – clients, users, and roles administration – require an active connection.

The mobile app you will build in this tutorial is a hypothetical service calls app that consists of four html files and a manifest file:

  • index.html: This file will contain a jQuery Mobile page that will function as the homepage of the app, consisting of a menu pointing to the different features.
  • jobs.html: This file will contain a jQuery Mobile page for a hypothetical “my jobs” feature. The page will be available even if the app is offline.
  • users.html: This file will contain a jQuery Mobile page for a hypothetical “users management” feature. This feature will only be available if the app is online.
  • roles.html: This file will contain a jQuery Mobile page for a hypothetical “roles management” feature. This feature will only be available if the app is online.
  • cache.manifest: This is the HTML5 offline manifest file where you will define which application resources will be available offline.

Requirements

Your goal is to design the app so it meets the following requirements:

  • The homepage and the “my jobs” page are available when the app is online or offline.
  • If the app is offline and the user tries to access the “users management” or “roles management” pages, a message should pop up, stating that the requested page is only available when the app is online.
online-offline-2online-offline-5

Creating the offline-capable pages

Let’s get started with the index.html file. Go ahead and pick a directory for this project and in it, create the index.html file. Add the following code to the file:

<!DOCTYPE html>
<html manifest="cache.manifest">
<head>
    <title>Offline/Online Demo</title>
    <meta name="description" content="This is an example of an offline capable app that alerts the user when the requested page requires the app to be online" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.css" rel="stylesheet" />
    <script src="../../Lib/jQ/jquery-1.8.2.min.js"></script>
    <script src="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.js"></script>
</head>
<body>
    <div id="main-menu-page" data-role="page">
        <div data-role="header" data-theme="b">
            <h1>Service Calls</h1>
        </div>
        <div data-role="content">
            <h2>Main Menu</h2>
            <ul data-role="listview" data-inset="true">
                <li><a href="jobs.html">My jobs</a></li>
                <li><a href="users.html">Users Management</a></li>
                <li><a href="roles.html">Roles Management</a></li>
            </ul>
        </div>
    </div>
    <div id="requires-online-dlg" data-role="dialog" data-transition="pop">
        <div data-role="header" data-theme="e">
            <h1>Wait!</h1>
        </div>
        <div data-role="content">
            <p>The feature you are trying to use requires that the app is online.</p>
        </div>
    </div>
</body>
</html>

Index.html contains two jQuery Mobile pages (remember that jQuery Mobile pages and html pages are not the same thing). One is the main page of the application. You can identify it in the code by the id “main-menu-page”. This is a very simple mobile page with a header and a content area. In the content area you placed a jQuery Mobile listview with links to the app’s remaining pages: jobs, users and roles.

The second jQuery Mobile in the index.html file contains the message that will pop up when the user tries to access the online-only pages while the app is offline. On this mobile page, identified with the id “requires-online-dlg”, you will use the jQuery Mobile attributes data-role=”dialog” and data-transition=”pop” to instruct jQuery Mobile to render the page as a dialog using a pop transition. This will show the alert as depicted in the screenshot below:

online-offline-5

One last detail about the index.html file. Note that the html tag contains a reference to the cache.manifest file, which is the offline manifest you will use to declare the resources the browser should cache for offline access. You will create this file in a few minutes.

If you open the index.html in your favorite Webkit browser, you should see a page similar to this:

online-offline-2

Next you will create the html file that will represent the app’s “My Jobs” feature. You will name this file jobs.html, and in it you will write the following code:

<!DOCTYPE html>
<html>
<head>
    <title>My Jobs</title>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <link href="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.css" rel="stylesheet" />
    <script src="../../Lib/jQ/jquery-1.8.2.min.js"></script>
    <script>

    </script>
    <script src="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.js"></script>
   
</head>
<body>
    <div id="online-page" data-role="page">
        <div data-role="header" data-theme="b">
            <a href="#" data-rel="back" data-icon="arrow-l">Back</a>
            <h1>Jobs</h1>
        </div>
        <div data-role="content">
          <p>This page is available online and offline.</p>           
        </div>
    </div>
</body>
</html>

The jobs.html file contains a single jQuery Mobile page. For the purposes of this tutorial, this page will only display a message to the user. As you want this page to be available when the application is online or offline, you need to declare the jobs.html file in the CACHE section of the cache.manifest file.

Go ahead and create the cache.manifest file in the project’s directory. Then, add the code below:

CACHE MANIFEST
# v1

CACHE:

# jqm assets
../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.css
../../Lib/jQM/1.3.2/images/ajax-loader.gif
../../Lib/jQM/1.3.2/images/icons-18-white.png
../../Lib/jQ/jquery-1.8.2.min.js
../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.js

# other images, styles and assets that need to be cached

# offline-capable pages
index.html
jobs.html

# assets that require the app to be online
NETWORK:
*

You need to declare the jQuery and jQuery Mobile assets as cacheable by adding them to the CACHE section of the manifest file. Note that the path in the file is the one I use for my jQuery Mobile tutorials. You will need to enter the correct path to these files based on your directories structure.

The index.html and the jobs.html files are also cacheable, as you want the jQuery Mobile pages that they host to be available when the app is offline.

Any other resources, including the users.html and roles.html files, fall under the NETWORK section of the manifest file. This indicates that they require a network connection.

If you need more details on the topic of offline manifest files, you can find more information in this tutorial.

Create the online-only pages

Next you will create the Users page. Create the users.html file, and add the following code to it:

<!DOCTYPE html>
<html>
<head>
    <title>Users</title>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <link href="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.css" rel="stylesheet" />
    <script src="../../Lib/jQ/jquery-1.8.2.min.js"></script>
    <script src="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.js"></script>   
</head>
<body>
    <div id="users-page" data-role="page">
        <div data-role="header" data-theme="b">
            <a href="#" data-rel="back" data-icon="arrow-l">Back</a>
            <h1>Manage Users</h1>
        </div>
        <div data-role="content">
          <p>This page is only available when the app is online.</p>           
        </div>
    </div>
</body>
</html>

The users.html file contains a single jQuery Mobile page that will only display a message to the user for the purposes of this tutorial. This is one of the pages that will only be available when the application is online.

The roles.html file is very similar:

<!DOCTYPE html>
<html>
<head>
    <title>Roles</title>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <link href="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.css" rel="stylesheet" />
    <script src="../../Lib/jQ/jquery-1.8.2.min.js"></script>
    <script src="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.js"></script>   
</head>
<body>
    <div id="roles-page" data-role="page">
        <div data-role="header" data-theme="b">
            <a href="#" data-rel="back" data-icon="arrow-l">Back</a>
            <h1>Manage Roles</h1>
        </div>
        <div data-role="content">
          <p>This page is only available when the app is online.</p>           
        </div>
    </div>
</body>
</html>

The roles page will also be available only when the app is online.

Let’s now work on the logic that will make this happen. As you want to inform the user that the application’s feature contained in the “users” and “roles” jQuery Mobile pages are only available when the application is online, you need a way to detect when the user is requesting these online-only pages while the application is offline.

There are multiple ways to accomplish this, but probably the easiest one is to use the pageloadfailed event of the jQuery Mobile API. Let’s open the index.html file and modify its head section like so:

<head>
    <title>Offline/Online Demo</title>
    <meta name="description" content="This is an example of an offline capable app that alerts the user when the requested page requires the app to be online" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.css" rel="stylesheet" />
    <script src="../../Lib/jQ/jquery-1.8.2.min.js"></script>
    <script>
        $(document).on("pageloadfailed", function (e, data) {
            // Check if the requested page is one that requires the app to be online.
            if (data.url.indexOf("/users") > -1 || data.url.indexOf("/roles") > -1) {
                // Stop the page processing flow.
                e.preventDefault();
                // Redirect to the alert page.
                var $page = $("#requires-online-dlg");
                data.options.pageContainer.append($page);
                data.deferred.resolve(data.absUrl, data.options, $page);
            }
        });
    </script>
    <script src="../../Lib/jQM/1.3.2/jquery.mobile-1.3.2.min.js"></script>
</head>

What you just did was to add an event handler for the pageloadfailed jQuery Mobile event. In the handler, you inspect the url of the page that failed to load, which is passed as a property of the data argument. If the url of the requested page coincides with the url of the “users” or “roles” pages, you need to alert the user:

// Stop the page processing flow.
e.preventDefault();
// Redirect to the alert page.
var $page = $("#requires-online-dlg");
data.options.pageContainer.append($page);
data.deferred.resolve(data.absUrl, data.options, $page);

To alert the user you first need to call preventDefault on the event object. This will stop jQuery Mobile’s default “page load failed” message from showing. Then, you acquire a reference to the jQuery Mobile page that contains the message that you want to display, and activate this page by appending it to the pageContainer passed to the handler.

Finally, you call resolve on the deferred object passed to the event handler. This step allows the changePage request (triggered when the user clicked on the main menu) to resume its normal flow and execute any callbacks attached to it.

Now you can test your app following these steps:

  1. Open the index.html file in your favorite WebKit browser.
  2. Disconnect the browser from the server hosting the page. This might be your development server, or a remote server where you deployed the app. If you are testing on a mobile device, put the device on Airplane Mode.
  3. Click or tap the “Users Management” or “Roles Management” links on the app’s main menu. After you do this, the message alerting that the feature is only available when the app is online should come up.

Want to learn more?

My Sencha Touch and jQuery Mobile books will guide you, step by step, through the process of building Sencha Touch and jQuery Mobile applications. If you like to learn by doing, these books are for you.

Get Free Articles and News

Sign up for MiamiCoder’s Newsletter and get free articles and news:



MiamiCoder will never sell your email address.

Leave a Reply

Your email address will not be published. Required fields are marked *