SiteKickr Web Development

HTML 5 Storage is better, but cookies aren’t gone yet

HTML 5 Storage is a promising addition to the web developers arsenal. However, it's name is confusing to many novices because it implies a connection with HTML markup itself. HTML 5 Storage may be part of the HTML 5 specification, but we don't use HTML tags to access it. Instead, we use JavaScript.

The idea of using JavaScript to access data may scare a few people off, especially those comfortable with and used to accessing cookies from a server-side language (PHP, ColdFusion, ASP, etc). Cookies are still the right choice for storing "user-browser-specific" data for use within server-side scripts. However, when the need arises to permanently store data, and retrieve it from JavaScript code, cookies present some issues; issues that have been solved in HTML 5 Storage.

The Good Stuff

 

I said promising, not perfect

The points above might make you believe that HTML 5 Storage is a no-brainer. But, let's

 

Hey browser, do you have what it takes?

Before we get too excited and start writing code that's heavily dependent on HTML 5 Storage, we want to be sure that the user's browser supports it. JavaScript makes easy work of this, by using the built-in typeof keyword:

if(typeof Storage !== 'undefined') {
	// use HTML 5 Storage
}
else {
	// use good 'ol cookies
}

I've seen code lurking around that checks for browser versions, instead of directly checking for the existence of the Storage object as shown above.

if ($.browser.msie && $.browser.version <= 7) {
     // use cookies
}
else {
     // use HTML 5 storage
}

This is a bad practice, it introduces too many variables into your code, and makes too many predictions about future web browser capabilities.

 

But my thing ain't a string

The one area that HTML 5 Storage didn't break any new ground in is the type of data that can be stored. We're still stuck with string data. So, what happens when we want to store an object that's not a string?

Enter JavaScript Object Notation, or JSON. JSON sounds a lot fancier than it is. It's really just a way to convert, or serialize, an object to a string; in our case, a string that can be stored in an HTML 5 Storage database.

Modern browsers provide the JSON.stringify() and JSON.parse() methods to serialize objects to strings and deserialize strings to objects respectively. Older browsers can be brought up to speed with Douglas Crockford's JSON-js library.

For simpler data types, like integers and floats, you can assign them directly, knowing that JavaScript will cast them to string data automatically. This will get you into trouble when you need to retrieve the data later though (see pitfalls below). You're best bet is to explicitly cast the number to string before storing it:

x = 1;
x.toString();

JSON serialization isn't the only way to fit data into a string type. Base 64 encoding is another method. This capability is not built into JavaScript, but there are libraries out there to help: http://www.webtoolkit.info/javascript-base64.html. Be wary of Base 64 encoding though, it can consume a good amount of space (see Base 64 encoding the web).

 

Sounds like a hassle, where's the best place to use HTML Storage

The quick answer is, on mobile web sites. Mobile devices are modern and hence use modern browsers. Modern browsers support HTML 5 Web Storage. People are also a little less concerned about the "dangers" of JavaScript on their mobile device.

HTML 5 Storage on mobile devices also provides a more noticeable performance gain over cookies. Cookies use bandwidth, HTML 5 Storage doesn't. Since bandwidth is at more of a premium on mobile, it makes even more sense.

If you've dabbled in PhoneGap (Cordova) at all, you know how indispensable HTML 5 Storage is.

 

Just tell me how to use it!

I've left the syntax and usage part alone until now, mainly because it's easy. The dependencies, limitations and concepts that surround the usage deserved more attention. The example below demonstrates how to set and retrieve a value, check for the HTML 5 Storage capability, determine whether a key has been created.

if (typeof Storage !== 'undefined') {
    if (localStorage.firstVisit === undefined) {
        localStorage.firstVisit = (new Date()).toString();
    }

    document.write('A loyal visitor since ' + localStorage.firstVisit);
}

 

Common Pitfalls

I've tossed out a lot of nonsense about specifications, limitations, dependencies and data types. But that's all academic. What happens in the real world when we introduce HTML 5 Storage into our applications? I have personally been victim of the following pitfalls and would like to spare you the same!

 

 

Real-world Examples

var webstorageExample = {
    banners: [
        '<img src="/img/banner1.jpg" alt="" />',
        '<img src="/img/banner2.jpg" alt="" />'
    ],
    getBannerIndexLocation: function() {
        if (typeof Storage !== 'undefined') /* must use typeof for IE 7 support */ {
            if (sessionStorage.gutterBannerIndex !== undefined) {
                var bannerIndex = parseInt(sessionStorage.gutterBannerIndex);
                var bannerUpperBounds = webstorageExample.banners.length - 1;
               
                if (bannerIndex < bannerUpperBounds)
                    sessionStorage.gutterBannerIndex = bannerIndex + 1;
                else
                    sessionStorage.gutterBannerIndex = 0;
               
                return bannerIndex;
            }
            else {
                sessionStorage.gutterBannerIndex = 1;
                return 0;
            }
        }
        else {
            /* no web storage support, so just return a random index */
            return (Math.floor(Math.random() * webstorageExample.banners.length));
        }
    },
    getContent: function() {
        var bannerIndex = webstorageExample.getBannerIndexLocation();
        return webstorageExample.banners[bannerIndex];
    }
}

 

This next example was pulled from a Mortgage Calculator app I created. It demonstrates how to fall back on cookies when HTML 5 Storage is unavailable:

function storeJSON(jsonString) {
	if(typeof Storage !== 'undefined') {
		localStorage.loans = jsonString;
	}
	else {
		var date = new Date();
        date.setTime(date.getTime()+(7776000000));
        var expires = "; expires="+date.toGMTString();
		document.cookie = 'loans=' + jsonString + expires;
	}
}