HTML Client-Side Storage

HTML
Apr
27

In HTML 5 developers now have access to datastore features to allow data from your site to be used in offline browsing - something particularly useful if you run a website that is driven by user-submitted data that they're likely to need access to whilst on the move. This is something more and more browsers, including mobile devices, are starting to support.

If you've ever been to Google Mail on your mobile device, especially on an iPhone, then you'll have likely used HTML 5 already - possibly without even realising it. With Google Mail it uses the client-side storage features of this relatively new standard to store basic information offline so that you can browse some email information offline. Companies and individuals are gradually moving more and more of their everyday files away from being stored on their desktop and now store it online instead. For example a document you once created in Microsoft Word you may now chose to create in Google Docs instead, or a photo you've taken you may decide that it can be stored on Flickr or Facebook and edited with Pixlr - it's possible to do almost anything in online applications that you can do in a desktop equivalent. The web is becoming more powerful, it is becoming your desktop. This does mean our reliance on persistent internet connections is growing, but you can often find yourself in a situation without a internet connection or may find you want access to a document you last viewed over Wi-Fi but then don't want to pay data charges for reading whilst you're out roaming. This is where the HTML 5 client-side storage comes in to play.

HTML 5 client-side storage can be categorised as session storage, local storage and database storage. The simplest of these is the session storage option whose nearest JavaScript accessible equivalent is the cookie though in behaviour it is more like the Session variable in PHP as they both end when the browser window is closed. The difference between these is that where in PHP the amount of memory you can use is defined by a setting in your PHP configuration, in HTML 5 it is defined by the browser. This means that you may need to develop conservatively with the least amount of data stored in session storage. The usage for this is quite simple and uses a "key-value" pair system which is easiest to think of as being a variable with a value, just with a different method for assignment and retrieval of values.

sessionStorage.setItem('my_key', 'my_value');

From the above example you can see that HTML 5 has made a special object available called sessionStorage which has a number of methods for manipulating the contents - these are setItem, getItem and removeItem - all used in a similar manner and do pretty much as you'd expect them to. If you're used to OO programming then you may find the following comparison quite useful.

sessionStorage.getItem('my_key');
sessionStorage.my_key

The above two functions will actually return the value of my_key so that it can be used in variable assignment or whatever you need to use it for. If you want to give this a go without writing any proper applications yet you could try playing about with it using Firebug in Mozilla Firefox or similar console. For example I tried the following code, and to my delight it displayed the expected value which proved the browser supports session storage.

sessionStorage.setItem('my_key', 'my_value');
alert(sessionStorage.my_key);

The next one I want to look at is the database storage - the one on the opposite end of the spectrum for storing larger amounts of data. Using this method is like using a database on the iPhone as they both use SQLite for storing data. If you're familiar with MySQL, MS-SQL or PostgreSQL then chances are you'll find yourself at home with SQLite but will notice it lacking in features (hence the lite part of it's name).

var db = openDatabase("notes", "", "The Example Notes App!", 1048576);

function renderNotes()
{
   db.transaction(function(tx) {
      tx.executeSql('CREATE TABLE IF NOT EXISTS Notes(title 
         TEXT, body TEXT)', []);
      tx.executeSql(‘SELECT * FROM Notes’, [], function(tx, rs) {
         for(var i = 0; i < rs.rows.length; i++) {
            // do something with data
         }
      });
   });
}

function insertNote(title, text)
{
   db.transaction(function(tx) {
      tx.executeSql('INSERT INTO Notes VALUES(?, ?)', [ title, text ],
         function(tx, rs) {
            // inserted okay
         },
         function(tx, error) {
            // reports an error
         });
   });
}

The above example is taken from the  W3C Offline Web Applications page as it's a good example to demonstrate the sort of thing you can achieve. What you see here are two examples of using SQLite transactions which can take one to three arguments: a transaction callback, an error callback, and a success callback. On the first line though it opens a connection to the database if it exists, or creates it if it doesn't. It takes four arguments: a database name, a database version, a display name, and an estimated size, in bytes, of the data to be stored in the database. If you're using an iPhone OS powered device you can actually find out how much space is being used by going to Settings -> Safari -> Databases to see these details.

The executeSQL statement is what does the actual work, it takes one to four arguments: a SQL statement, arguments, a SQL statement callback, and a SQL statement error callback. It is good practice to include CREATE statements in case your database does not exist as this means tables will be created as and when they are required. You'll also note that the INSERT SQL is actually a prepared statement which is good as it guards against SQL injection (not that you can really do anything about it when the JavaScript can be read anyway).

The problem with database storage at the minute is how this handled by different browsers and it's current lack of security. Of the sites I read when originally researching HTML 5 almost every one of them commented on this serious concern - hopefully this is something which will be addressed at some point in the very near future. This is especially important considering the sort of information you may chose to store offline.

This then brings us onto the final method - local storage. This type of storage is originally stemmed from the cross-domain storage method they named "global storage" but was later limited to being domain dependant. The reason I've left this one until last is that it's not really that different to session storage. If you can understand that one, and you can understand the more complicated database storage then you shouldn't have a problem with it. The main difference between this and session storage is that it will not be cleared when you close your browser and can also be used across different browser windows and/or tabs. The session storage example when using local storage would look like:

localStorage.setItem('my_key', 'my_value');
alert(localStorage.my_key);

So as you can see this type of storage really is simple to understand and use. Hopefully these explanations have been pretty straight forward, but if there's anything I've missed or you're unsure about please don't hesitate to ask me in the comments section.