Summary: Writing applications for multiple operating systems and a wide range of mobile devices can be challenging. The high demand for sophisticated mobile applications requires significant hardware. One solution is to provide Web applications, because they can run cross-platform on mobile devices. You don't need to use proprietary technology (such as Objective-C with Cocoa on the iPhone); you can use common Web technology. In essence, just one version of the application is needed. The main hardware power is provided by servers. In this article, explore the use of Web development in the mobile application space with a simple example that taps into the HTML5 standard.
The use of Web development in mobile applications is an increasing trend. However, intermittent network availability is a big obstacle to using Web technology as part of a cloud infrastructure. A traditional Web application simply doesn't work without a network. One solution to this problem is to use two features of the HTML5 Standard (see Resources):
The user can use cloud functions on a mobile device, work offline with a locally deployed application on a local database, and share data with the rest of the cloud when going online again.
In this article, learn the technical details for a typical usage scenario. A prototype of a simple inventory management application demonstrates the HTML5 technology.
Download the source code for the example application in this article from the Download table below.
Figure 1 shows an overview of the major components of the sample application architecture.
Remarkably, this application consists of a single HTML page without the need for loading of further HTML pages through the request-response cycles. The whole action is on one page.
For mobile devices, there are various JavaScript/CSS libraries and frameworks to deliver a near native user experience with Web applications (for example, iUi for the iPhone). See Resources for more information. Though necessary to increase the user acceptance, this approach has the disadvantage of platform dependency.
This section provides an overview of the sample application, called MyHomeStuff. It is a simple inventory management application that lets you keep track of items you own. Figure 2 shows the application on the iPhone.
For simplicity, the synchronization of data with the server is omitted. Figure 3 shows the MyHomeStuff inventory management application in the Palm Pre Web browser.
The list in the upper part of the screen gives an overview of all entered items (books, computer, and so on).
When a user selects an item in the list, the details (Id, Quantity, Name) of the item are shown in the middle of the form. The details of the selected item can be changed using the Update button. The selected item can also be deleted from the application using the Delete button. New items can be created by entering the item's quantity and name in the form and selecting the Create button.
The application Status is displayed in the lower part of the screen.
The HTML page contains declarations, meta tags for a mobile-optimized display, references to external files (manifest, JavaScript, css), and essential HTML elements that form the basic structure of the application. Listing 1 shows the code.
<!DOCTYPE HTML> <html manifest="MyHomeStuff.manifest"> <head> <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> <title>MyHomeStuff</title> <script type="text/javascript" src="MyHomeStuff.js" ></script> </head> <body onload="onInit()"> <h3>Overview</h3> <ul id="itemData" ></ul> <h3>Details</h3> <form name="itemForm"> <label for="id">Id: </label> <input type="text" name="id" id="id" size=2 disabled="true"/> <label for="amount">Amount: </label> <input type="text" name="amount" id="amount" size = 3/> <label for="name">Name: </label> <input type="text" name="name" id="name" size=16 /> <br> <br> <input type="button" name="create" value="create" onclick="onCreate()" /> <input type="button" name="update" value="update" onclick="onUpdate()" /> <input type="button" name="delete" value="delete" </form> <h4>Status</h4> <div id="status"></div> </body> </html> |
Event handler attributes of the HTML elements specify which JavaScript functions are executed when the page is initially loaded (onload
) and button elements are clicked (onclick
).
The HTML page of an offline Web application starts with the tag <!DOCTYPE HTML>
. The manifest is referenced through the manifest attribute in the tag <html manifest="MyHomeStuff.manifest">
.
As mentioned, the manifest specifies the required files that need to be loaded into the cache. This application consists of an HTML file and a JavaScript file. The HTML file with the reference to the manifest is automatically included in the application cache. The manifest contains only the following:
CACHE MANIFEST MyHomeStuff.js |
The JavaScript code consists of three main blocks:
The first block contains the event handler to initialize the application (onload
) and the initialization of the database, as shown in Listing 3.
function onInit(){ try { if (!window.openDatabase) { updateStatus("Error: DB not supported"); } else { initDB(); createTables(); queryAndUpdateOverview(); } } catch (e) { if (e == 2) { updateStatus("Error: Invalid database version."); } else { updateStatus("Error: Unknown error " + e + "."); } return; } } function initDB(){ var shortName = 'stuffDB'; var version = '1.0'; var displayName = 'MyStuffDB'; var maxSize = 65536; // in bytes localDB = window.openDatabase(shortName, version, displayName, maxSize); } |
In the code above:
onInit
function first checks the existence of the mandatory openDatabase
function, whose absence signals that the browser doesn't support a local database.initDB
function opens the database of the HTML5 browser.Each function of the second JavaScript block has a part for DB access and presentation logic. This consolidation of logic is characteristic of a Model 1 architecture (see Resources), which is the easiest way to develop simple Web applications. For a real-world scenario, an architecture with a clear separation of the Model View Controller (MVC) parts would be appropriate.
To build the example overview list, the queryAndUpdate
function is called from the event handler functions. Listing 4 shows the code.
function queryAndUpdateOverview(){ //remove old table rows var dataRows = document.getElementById("itemData").getElementsByClassName("data"); while (dataRows.length > 0) { row = dataRows[0]; document.getElementById("itemData").removeChild(row); }; //read db data and create new table rows var query = "SELECT * FROM items;"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [], function(transaction, results){ for (var i = 0; i < results.rows.length; i++) { var row = results.rows.item(i); var li = document.createElement("li"); li.setAttribute("id", row['id']); li.setAttribute("class", "data"); li.setAttribute("onclick", "onSelect(this)"); var liText = document.createTextNode(row['amount'] + " x "+ row['name']); li.appendChild(liText); document.getElementById("itemData").appendChild(li); } }, function(transaction, error){ updateStatus("Error: " + error.code + "<br>Message: " + error.message); }); }); } catch (e) { updateStatus("Error: Unable to select data from the db " + e + "."); } } |
In the code above:
onSelect
, is added to every list element to respond on a click.The functions of this block also contain the event handler for the button bar and the list with onUpdate
, onDelete
, onCreate
, andonSelect
. Listing 5 shows the code for onUpdate
. (onCreate
and onDelete
have a similar structure, so aren't shown here; you candownload all the source code for the example application from the table below.)
function onUpdate(){ var id = document.itemForm.id.value; var amount = document.itemForm.amount.value; var name = document.itemForm.name.value; if (amount == "" || name == "") { updateStatus("'Amount' and 'Name' are required fields!"); } else { var query = "update items set amount=?, name=? where id=?;"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [amount, name, id], function(transaction, results){ if (!results.rowsAffected) { updateStatus("Error: No rows affected"); } else { updateForm("", "", ""); updateStatus("Updated rows:" + results.rowsAffected); queryAndUpdateOverview(); } }, errorHandler); }); } catch (e) { updateStatus("Error: Unable to perform an UPDATE " + e + "."); } } } |
In the above code:
The onSelect
function is executed when the user selects a list element. The details form will be filled with the data of this element using the code in Listing 6.
function onSelect(htmlLIElement){ var id = htmlLIElement.getAttribute("id"); query = "SELECT * FROM items where id=?;"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [id], function(transaction, results){ var row = results.rows.item(0); updateForm(row['id'], row['amount'], row['name']); }, function(transaction, error){ updateStatus("Error: " + error.code + "<br>Message: " + error.message); }); }); } catch (e) { updateStatus("Error: Unable to select data from the db " + e + "."); } } |
In the code above:
The last JavaScript block with utility functions starts with data handlers, which are needed as parameters for the queries.
errorHandler = function(transaction, error){ updateStatus("Error: " + error.message); return true; } nullDataHandler = function(transaction, results){ } |
To avoid redundancy, utility functions fill the fields of the detail form (updateForm
) and status message (updateStatus
), as shown below.
function updateForm(id, amount, name){ document.itemForm.id.value = id; document.itemForm.amount.value = amount; document.itemForm.name.value = name; } function updateStatus(status){ document.getElementById('status').innerHTML = status; } |
An iPhone 3GS and a Palm Pre were used to run the example on a real HTML5 mobile device. A current Safari browser on a computer also works.
You can download and deploy the files for the application in an HTTP server from the Download table below. The manifest file must be served by the HTTP server with the text/cache-manifest
Mime type. After opening the application on the iPhone, save the Bookmark and go in the offline airplane mode. The application will then be opened when the bookmark is selected, and it works without a network.
The focus of this article was the technical angle for offline Web applications. A prototype of a simple inventory management application demonstrated the HTML5 technology with a locally deployed application and a local database.
Description | Name | Size | Download method |
---|---|---|---|
Source code for this article | OfflineWebAppSrc.zip | 3KB | HTTP |
Information about download methods
Learn