Programming the Mobile Web : HTML 5 (part 4) - Client Storage

1/24/2011 4:28:02 PM

7. Client Storage

Working offline is great, but there’s a problem: where should a web application store vital statistics and other information when the device is not connected to the Internet? And if the device is not connected to the Internet, how can our applications access helpful databases or information? Client storage solutions come to our assistance, in two flavors: key/value storage and SQL databases (yes, from JavaScript, without server interaction).

Of course, we also have cookies, but they are simpler (only string storage), and we know they are not guaranteed to survive in the browser.

7.1. Key/value storage

HTML 5 defines a key/value store through two objects: localStorage and sessionStorage. They are pretty much the same, but the scopes are different: while the local store is used for long-term storage, the session store doesn’t persist after the user closes the tab or window.


We should use try/catch blocks when saving items, in case problems occur with the storage or the maximum available space is exceeded.

Both stores are used in the same way:

// Save an object or variable in the store
localStorage.setItem("name_in_the_storage", object_to_store);

// Read an object from the store
var object = localStorage.getItem("name_in_the_storage");

We can also delete all the objects using clear or delete one key using removeItem. There is also a storage event that we can listen for with window.addEventListener that will be fired when the contents of the local or session stores have changed.

7.2. SQL database

Having a relational database available in JavaScript sounds powerful. The main method that defines the availability of the JavaScript SQL database is the window.openDatabase method. This method has the following signature:

var db = window.openDatabase(shortName, version, displayName, sizeExpectable);

If we use a try/catch, we can capture errors during the operation. This method opens the database if it exists and creates it if it is the first time we’ve used it. To execute non-recordset sentences (CREATE TABLE, INSERT, etc.) we can use a transaction using the transact method, which receives a function as parameter. As a transaction, if one sentence fails, the others will not execute:
db.transact(function(t)) {
AUTOINCREMENT, name TEXT NOT NULL)', [], function() {}, errorHandler);

The array parameter after the query string is an array of parameters to be replaced in the query (using ? inside), the next parameter is the data handler function (not used in a non-recordset query), and the last parameter is a function handler for errors in the query.


HTML 5 doesn’t define which database engine should be used. Mobile browsers use SQLite, the open source database engine, so check the SQLite documentation for data type and SQL syntax support.

To create a typical SELECT statement with recordset looping, we can use the following template:

db.transact(function(t)) {
t.executeSql('SELECT * FROM countries', [], countriesHandler, errorHandler);

function countriesHandler(transaction, data) {
var record;
var id;
var name;
for (var i=0; i<data.rows.length; i++) {
// We get the current record
record = data.rows[i];
id = record['id'];
name = record['name'];
// Do something with record information

function errorHandler(transaction, error) {
alert('Error getting results');


JavaScript databases support versioning, allowing us to change schema on newer versions of our applications and detect what the current version installed on the client is, to create a migration procedure.

If you were working offline you should implement a synchronization method, using Ajax to download changes from and upload them to the server.


Safari on iOS accepts up to 5 MB in offline storage without user intervention. If you try to save more than 5 MB, the user will need to approve it (an automatic alert will appear).

7.2.1. Gears storage

Google Gears ( is an open source project that enhances web browsers and JavaScript with more functionality, much of which is part of the HTML 5 draft. Android 1.X supports only Gears, and we can also use SQL databases with Gears. The normal usage is simple and synchronous, as the following sample demonstrates:

<script type="text/javascript" src="gears_init.js"></script>
<script type="text/javascript">
var db = google.gears.factory.create('beta.database');'countries');
name TEXT NOT NULL)');

var rs = db.execute('SELECT * FROM countries');

while (rs.isValidRow()) {
var id = rs.field(0);
var name = rs.field(1));
// Do something;

Fortunately, Google is working on an open source project that gives us an abstraction layer for both HTML 5 databases and Gears databases using the same code. The project is called the Web Storage Portability Layer and it is available at


Safari on iOS allows you to view stored databases and delete them from the device using SettingsSafariDatabases.

With this new layer, we can use the following code for select queries in both frameworks:

var database = google.wspl.DatabaseFactory.createDatabase('countries',
var statement = google.wspl.Statement('SELECT * FROM countries;');

database.createTransaction(function(tx) {
tx.executeAll([statement], {onSuccess: function(tx, resultSet) {
// Statement succeeded

for(; resultSet.isValidRow(); {
var id = resultSet.getRow()['id'];
var name = resultSet.getRow()['name'];
}, onFailure: function(error) {
// Statement failed
}, {onSuccess: function() {
// After transaction commits, before any other starts
}, onFailure: function(error) {
// After transaction fails, before any other starts

7.3. Client JSON store

Prepared for mobile devices, Lawnchair is a local client JSON store that uses HTML 5 features behind a very simple API. You can download the library from

To create a store, we just use code like this:

var countries = new Lawnhair('countries');

Then, we can save an object synchronously:{id: 5, name: 'Spain'});
// Object saved

or asynchronously:{id: 5, name: 'Spain'}, function() {
// Object saved

We can also save it using a key/value mechanism for easy retrieval:{key: 5, value: 'Spain'});

var spain = countries.get(5);

And we can easily get all the documents using:

countries.all(function(country) {
// We receive every country in this function

We can also remove documents, clear all the storage, and create iterators for easy filtering.

Web Compatibility Test

In 2010, the W3C created a test to score mobile browsers in terms of their RIA, Ajax, and HTML 5 support. The Web Compatibility Test for Mobile Browsers, available at, verifies compatibility with Ajax, the canvas HTML tag, the contenteditablevideo and audio HTML 5 tags, Web Workers, local storage, session storage, and @font-face. There are currently no mobile browsers that score 100%. attribute, geolocation, HTML 5 input forms, the offline AppCache, the

Some results are:

  • iPhone 3.0: 83%

  • Firefox 3.5 for Maemo: 83%

  • Bada Browser: 75%

  • Android 1.6–2.1: 67%

  • Opera: 33%

  • Symbian 5th edition: 17%

  • webOS: 17%

  • NetFront 3.5: 8.33%

  •  Windows Phone 7 : Submitting Your First Windows Phone Application to the Windows Phone Marketplace
  •  Windows Phone 7 : Packaging, Publishing, and Managing Applications
  •  Mobile Application Security : Windows Mobile Security - Development and Security Testing (part 3)
  •  Mobile Application Security : Windows Mobile Security - Development and Security Testing (part 2)
  •  Mobile Application Security : Windows Mobile Security - Development and Security Testing (part 1)
  •  Programming the Mobile Web : Mobile Rich Internet Applications (part 2) - JavaScript Mobile UI Patterns
  •  Programming the Mobile Web : Mobile Rich Internet Applications (part 1) - JavaScript UI Libraries
  •  Windows Mobile Security - Kernel Architecture
  •  Windows Mobile Security - Introduction to the Platform
  •  iPhone Programming : Table-View-Based Applications - Building a Model
    Most View
    Cooking Up A Killer Kaveri Rig (Part 1)
    AMD Radeon HD 7770 1GB vs. nVidia GeForce GTX 650 Ti 1GB
    Seasonic And Enhance Junior PSUs - Compact Power Supply (Part 3) : Seasonic SS-300TGW
    SQL Server 2012 : Exploring SQL CLR - SQL CLR Types
    DirectX 10 : The 2D Resurgence - Sprite Animation
    Asus Memo Pad Review – A Cheap 7in Tablet (Part 1)
    Most Favorite Creativity Apps For Your Smartphone – November 2012
    Windows Server 2012 : Active Directory Domain Services Primer - AD DS Structure - Describing AD DS Domain Trees
    Sql Server 2012 : Hierarchical Data and the Relational Database - The hierarchyid Data Type, Creating a Hierarchical Table
    Samsung NX210 – Snap N Share
    Top 10
    Using Exchange Server 2010 Antispam Tools (part 6) - Sender Reputation
    Using Exchange Server 2010 Antispam Tools (part 5) - Sender Filtering, Sender ID
    Using Exchange Server 2010 Antispam Tools (part 4) - IP Block and Allow Lists, Recipient Filtering , Tarpitting
    Using Exchange Server 2010 Antispam Tools (part 3) - IP Block and IP Allow Providers
    Using Exchange Server 2010 Antispam Tools (part 2) - Content Filtering
    Using Exchange Server 2010 Antispam Tools (part 1) - Enabling Antispam Agents for Hub Transport Servers , Enabling Automatic Updates for the Antispam Signatures
    Windows Server 2012 : Implementing Group Policy preferences (part 4) - Windows Settings extensions,Control Panel Settings extensions
    Windows Server 2012 : Implementing Group Policy preferences (part 3) - Understanding preferences - Item-level targeting, Configuring a preference item
    Windows Server 2012 : Implementing Group Policy preferences (part 2) - Understanding preferences - Common options, Using environment variables
    Windows Server 2012 : Implementing Group Policy preferences (part 1) - Understanding preferences - Preference categories, Configuring preferences