RSS feed
<< My first Android coding experience | Home | SAP Mobile Timesheet sucks??? >>

Hoa: Offline applications with HTML 5

A quantum leap for mobile software development

After seeing the video that shows the offline Gmail solution (http://www.mobilecrunch.com/2009/02/18/video-offline-gmail-web-app-for-webkit-browser-phones-demoed/) I wanted to look into the technology behind it myself. After reading through different sources, I wrote this short tutorial to describe the new html 5 features for html offline applications (let’s call these type of applications Hoa (that’s Moari for "friend")). After reading the article you will see what this means for the development of mobile offline applications: A quantum leap!

The goal of this tutorial is to write a browser based "to-do list" application that works on the iPhone, Android and Palm Pre in six steps. The application should even work when the device has no network connection. (Synchronisation of data from the device to the server is beyond the scope of this article. This can be implemented using AJAX and there are numerous examples and books available on this topic.).

Android compatibility: After I finished this article I tested the application on the Android emulator release 1.1 - it did not work. So it looks like the current version of Android does not support the offline features of html 5 - but Google promises to add these features with the next release.

iPhone compatibility: The application works fine on the iPhone, however, when you start it in offline mode, you will first get a popup saying that the page can not be displayed. Just ignore it, it works anyway.

Step 1: The basic html page

So let’s start with the basic html page. For development, I suggest you use your preferred text editor (TextPad in my case) and the Safari 4 browser. In my opinion a html 5 offline application should be always built dynamically. In our case, I will create a page with three areas: Menu, Content and Message area.

The code looks like this:

<html>
<head>
<title>hoa to-do-list</title>
</head>
<body>
<div class="menu" id="menu"></div>
<div class="content" id="content"></div>
<div class="message" id="message"></div> </body>
</html>


Please note that all "div" tags are empty and that's because we populate them dynamically when we start the application.

Now we need to add the stylesheet definition for the "div" tags:
<style type="text/css" media="screen">@import "hoa.css";</style>


The menu should be 25 pixels from the top, the message area should be 15 pixels from the bottom and the content should be placed in between. The styles are added to a file called hoa.css and they look like this:

.menu {
width:100%;
height:25;
background-color:#e0ecff;
}

.content {
width:100%;
color:black;
font-family:Verdana, Arial,Helvetica;
font-size:10pt;
background-color:white;
}

.message {
width:100%;
height:15;
color:white;
font-family:Verdana, Arial,Helvetica;
font-size:10pt;
font-weight:bold;
background-color:#6694e3;
}


I know, they could optimized and I would welcome any suggestions, but for now I want to keep it as simple as possible. We also need to add the following styles to our html page:
<style type="text/css" media="screen">@import "hoa.css";</style>


If we want to test your page, it's best to do this with Apple's Safari as this is the only desktop browser that supports html 5 to date. The result looks like this:



The next thing we need to do is add a button to create a new to-do item:

<div class="menu"><button onClick="showForm();">New</button></div>


The styles we need to add are:

button {
height:20px;
color:black;
font-family:Verdana, Arial,Helvetica;
font-size:8pt;
}


Of course we omit the createItem(); JavaScript for now.

Step 2: Create the database and the database tables

Now the real fun begins ;-)

With Hoa we are able to store data in the browser using a database and SQL. This is a quantum leap for web developers and will change the web forever. I only hope that Mozilla, Microsoft and all the other browser suppliers will implement the Hoa standards as well in the near future.

What we need next is the database definition in form of a SQL create statement. For our to-do list, we will create the table as follows:

create table todos (id integer primary key autoincrement,
headline text not null,
longtext text not null,
status text not null);


Now let’s create a JavaScript file called hoa.js and add the following:

var mydb;


try {
if (!window.openDatabase) {
alert('not supported');
} else {
var shortName = 'com.mscmobile.todos';
var version = '1.0';
var displayName = 'Offline Hoa database for to dos';
var maxSize = 65536; // in bytes
mydb = openDatabase(shortName, version, displayName, maxSize);

// You should have a database instance in mydb.
}
} catch(e) {
// Error handling code goes here.
if (e == 2) {
// Version number mismatch.
alert("Invalid database version.");
} else {
alert("Unknown error "+e+".");
}
return;
}


This code will be executed when the browser loads the JavaScript. It is creating a new database called com.mscmobile.todos. We can also specify a human readable name for the db, a version number and a maximum size.

To load the hoa.js file, we need to add the following line to the header of our html file:

<script type="application/x-javascript" src="hoa.js"></script>


If you now reload the content of your browser window and go to "Edit -> Preferences -> Security" and press on the "Show Databases" button, you will see that the database was created:



The next thing to do is to create the database table. This can be done via the following code:

function createTables()
{
mydb.transaction(
function (transaction) {
transaction.executeSql("create table todos (id integer primary key autoincrement, "
+ "headline text not null, "
+ "longtext text not null, "
+ "status text not null);");
}
);
}


We will call the createTables() function via the onLoad of the body:

<body onLoad="createTables();">


Step 3: Insert new records into the database table

The next thing to do is to create the form which allows to enter new items into the to-do list.

This is done via JavaScript with the following code:

function showForm() {
var formString = '<form name="createTodo"><table width="100%">';
formString = formString + addInputField('headline', 'Headline', '');
formString = formString + addInputField('longtext', 'Text', '');
formString = formString + addInputField('status', 'Status','Open');
formString = formString + '</table></form>';
var content = document.getElementById("content");
content.innerHTML = formString;
var menu = document.getElementById("menu");
menu.innerHTML = '<button onClick="saveForm();" ' +
'id="mainButton">Save</button><button onClick="cancelForm();"' +
'id="mainButton">Cancel</button>';
}

function addInputField(fieldName, labelText, defaultText) {
return '<tr><td>' + labelText + ':</td><td><input type="text" id="' +
fieldName + '" name="' + fieldName + '" value="' +
defaultText + '"/></td></tr>';
}


Now we have our missing showForm() method and we can display the form. When the user clicks the save button, the method saveForm() is called. In this method we need to create a new record in the database:

function saveForm() {
var headline = window.createform.headline.value;
var longtext = window.createform.longtext.value;
var status = window.createform.status.value;

mydb.transaction(
function (transaction) {
transaction.executeSql('insert into todos (headline, longtext, status) ' +
'VALUES (?, ?, ?);', [headline, longtext, status],
insertDataHandler, errorHandler);
}
);

}

function insertDataHandler(transaction, results) {
var message = document.getElementById("message");
message.innerHTML = 'New To Do created';
//showList();
}
function errorHandler(transaction, error)
{
// Error is a human-readable string.
var message = document.getElementById("message");
message.innerHTML = error.message + '(' + error.code + ')';

// Handle errors here
var we_think_this_error_is_fatal = true;
if (we_think_this_error_is_fatal) return true;
return false;
}


When a SQL statement is executed, we have to provide two callback methods: one to handle success and one to handle errors. In the case of the insert statement, we want to display a success message in the message area, in the case of an error, an error message.



Step 4: Query for data via SQL

Now we are able to create entries, but we can’t display them. For that we need to uncomment the showList() line in the "insertDataHandler" function.

And of course we need to implement the code inside the showList() function:

function showList() {
mydb.transaction(
function (transaction) {
transaction.executeSql("SELECT * from todos;",
[],
selectdataHandler, errorHandler);
}
);
}

function selectdataHandler(transaction, results)
{
// Handle the results
var htmlList = '<table width="100%">';
for (var i=0; i<results.rows.length; i++) {
var row = results.rows.item(i);
htmlList = htmlList + addTableRow(row);

}
htmlList = htmlList + "</table>";
var content = document.getElementById("content");
content.innerHTML = htmlList;

var menu = document.getElementById("menu");
menu.innerHTML = '<button onClick="showForm();" id="mainButton">New</button>';

}

function addTableRow(row) {
return '<tr><td class="listentry">' + row['headline'] + '
<font size="-1">' + row['longtext'] + '(' + row['status'] + ')</font></td></tr>';
}


Again we have a callback function, this time I called it "selectdataHandler". In it we run through all rows returned and we create our html table.

We also need to add the showList method to the body tag:

<body onLoad="createTables();showList();">




Step 5: Offline caching of files

We are still missing some important features like deleting entries, but we can already run our application. When you restart your browser, you will see that the data is still there. Amazing! If we would deploy the three Hoa files on to a web server, while we could run it, it would not work offline. To make this possible, we need to add another feature of HTML 5: Offline application caching.

HTML 5 introduces a new attribute for the html tag:

<html manifest="hoa.manifest">


The attribute references a manifest file, which contains the information on which files need to be cached offline on the device. In our case the file looks like this:

CACHE MANIFEST
Index.html
hoa.css
hoa.js


If you have other resources in your web applicatio which are required to run the application offline, include them here as well. These can be pictures, pdfs and others resources.

The application caching does not work if you execute this locally (the files are already on your harddisk anyway), so you need to deploy them from your web server. And it is very important that the manifest file is delivered with the right content type (text/cache-manifest)!

As I use Tomcat, I will explain how to add the new content type here. You need to open the file web.xml in the /conf/ folder and add the following to the list of content types:

    <mime-mapping>
<extension>manifest</extension>
<mime-type>text/cache-manifest</mime-type>
</mime-mapping>


Step 6: Optimizing the application for the iPhone

That’s it, you are now ready to go! But there are two more thing I want to show you - they are not part of html 5, but instead functions Apple introduced for the iPhone.

First we will specify a customer icon for your web application, to be used on the homescreen when you add your application there.

To do this, we need to add the following line to the header of our html page:

<link rel="apple-touch-icon" href="todo.png"/>


Second, we will make sure that the application is sized correctly in the Safari on the iPhone:

<meta name = "viewport" content = "width = device-width">


With the viewport you can specify how the iPhone will resize your application in the browser. You can find more information at http://developer.apple.com/.



Conclusion

Please remember that this technology so far only works on the iPhone, on Android, most probably on the Palm Pre and in Safari 4 (Windows and Mac).

You can download the source code of the application here: http://www.msc-mobile.com/hoa_download.jsp or you can access the live demo on: http://hoa.msc-mobile.com

There is information from Apple on this topic which can be found in the Apple developer channel, but you need a Apple ID to access it. Another resource is the official spec from W3C: http://dev.w3.org/html5/spec/Overview.html

So? Where does this lead us?

When I first saw the GMail demo, I didn't realize what it meant. It meant we can now create mobile applications, that will work online and offline without the need for any software deployment. We can create one application, that will run on all devices, that support the html 5 standard. However, we can not access the underlying hardware device, for instance we cannot read the battery status or get values from a RFID reader. We can also not push data to the device when the browser is closed. We also don't know how the web browser would perform once we have 10,000 records in a DB table. Something I will test ...

But still, this is more than just the next version of html - this is a quantum leap for the development of mobile applications. No more issues with deployment of fat clients. Just call a webpage once and your done - use it online, offline, whenever you want!

Let me know what you think about this!


Re: Hoa: Offline applications with HTML 5

Hi

great article - this not the sort of thing I usually develop but the step by step guide makes it looks quite easy to do. I'm gonna give it a go!

Re: Hoa: Offline applications with HTML 5

Hi,

This really helpful, thank you!!

I have one question would like to ask you, for caching files, are they updated  automatically when online and cached when off-line?
Dose we need any mechanism to determine if it's online and then take care if we have to update cache files?<span style="font-weight: bold;">
</span>
Thanks!!
Neal<span style="font-weight: bold;" />

Re: Hoa: Offline applications with HTML 5

I agree. This is big :)

Add a comment Send a TrackBack