Mozilla

Using client-side storage, today.

I recently tried to store locally the content of a form to make it resilient to inadvertent tab closing and crashes. Here is what I learned about the different ways to achieve client-side storage.

Cookies can crumble

Cookies are not a valid storage mean, as their size is limited to roughly 4000 characters (4KB) and act as a ball and chain, slowing down the responsiveness of websites. localStorage on the other hand, has been designed for that exact purpose, but is not available in IE6, IE7 and Firefox3.

store.js to the rescue

The first task was thus to search for a fallback solution (or shim or polyfill) available in those older browsers. It turns out that store.js, by Marcus Westin (@marcuswestin), wraps localStorage and fallbacks together in a concise API, with a light file-size (2KB once minified and gzipped along with json2.js). Here is a short usage example:

How does it work?

On Firefox2 and Firefox 3, it uses the globalStorage API, and on IE6 and IE7 it falls back to userData behavior, which has two important limitations you should be aware of:

  • storage is limited to 128KB (vs. 5-10MB for localStorage), that’s still a lot of text,
  • storage is subject to a same folder policy, meaning that pages in different folders should not be able to access the same stored items.

The second limitation can be really annoying, but it is possible to work around it by loading the code in an iframe. This trick will likely be integrated into Marcus’ own code.

Although localStorage can only store strings, store.js uses the JSON API to make it possible to store Javascript objects and arrays as well.

Crash proof forms

With this script, I was able to build Persival, a simple jQuery plugin that can watch a form for changes and persist the values immediately:

A more complex demonstration page features the form people face when they want to report a bug affecting Firefox (you’ll see that it’s actually not as hard as it seems). If you start to fill the form, then close the tab and click on the same link again you should see the magic happening. A simple but welcome improvement to the user experience, isn’t it?

Chris Heilmann also demonstrated how client-side storage can be used to cache Web services data and maintain the state of a User Interface: localStorage and how to use it.

Your turn

Persival is young but already yours, feel free to use it, learn from it and improve it.

Maybe there is a similar topic you would like to see covered in a next blog post? Let us know!

Posted by on at

20 comments

Comments are now closed.

  1. Mathias wrote on April 5th, 2011 at 08:04:

    You could make Persival even more “immediate” and responsive by using the oninput event if it’s available.

  2. louisremi wrote on April 5th, 2011 at 08:19:

    @Mathias: good idea. Do you know in which browsers is this event not available?

  3. Mathias wrote on April 5th, 2011 at 08:31:

    @louisremi: See http://blog.danielfriesen.name/2010/02/16/html5-browser-maze-oninput-support/

  4. Dextro wrote on April 5th, 2011 at 08:51:

    I’ve been using jstorage for that task my self and it’s working mostly fine from what I could gather so far ( http://www.jstorage.info/ )

  5. Hemilton wrote on April 5th, 2011 at 13:58:

    Mmmh, Iframes

  6. Mohamed Jama wrote on April 5th, 2011 at 16:02:

    Hi,

    LocalStorage is quite cool We currently beta testing a project that uses LocalStorage to store user trips at expedia.co.uk on the third column search Expedia Map.

    At the moment its working on modern browsers only but hopefully we planning to fully implement it soon.

  7. Joss Crowcroft wrote on April 5th, 2011 at 23:28:

    Awesome work dude – Persival is great. Doesn’t seem to retain state for checkboxes for me (Chrome on Mac) but everything else is awesome!

  8. louisremi wrote on April 6th, 2011 at 02:13:

    @Joss: Indeed, I haven’t implemented “state persistence” for checkbox and radion-button yet. I’d love to see one of our reader giving it a try.

  9. Jaz wrote on April 6th, 2011 at 07:06:

    If you want some seriously robust client-side storage options, check out http://persistencejs.org/ This is a true data object abstraction layer that works with various methods of client-side storage and, if you so desired, can synchronize with a server-side database through nodejs.

  10. louisremi wrote on April 6th, 2011 at 07:25:

    @Jaz: the focus of this post was on cross-browser client-side storage. What persistance.js offers is more of a relational database API.

    Although it would be conceivable to cover this polyfill in a future post, it appears to scale only on browsers supporting the WebSQL API. As browser vendors are moving away from this API, I guess we should settle for key/value storage right now.

  11. Jaz wrote on April 6th, 2011 at 07:49:

    @louisremi: currently persistence.js supports in-memory storage, google gears and websql, but the goal is to support whatever standard emerges, focusing on the need for robust local databasing. It would depend on your needs. For mobile development, iOS and Android currently use webkit, so websql is a great solution there. And persistence can use window.localStorage if it needs to, so it should be just as useful as anything else.

    1. louisremi wrote on April 7th, 2011 at 01:20:

      @Jaz: persistence.js is indeed a valuable solution. I’d love to see an indexedDB adapter.

  12. iLama wrote on April 6th, 2011 at 09:14:

    The only thing I have to say is that your implementation of this “solution” is horrible. I’m not sure exactly how the script does it, but it allows for “brute force” access (so to speak) of Opera’s local storage (it doesn’t even trigger the Opera to ask me if it’s okay). Until this bug is fixed, I’ll handle “store.js” as malicious code.

    1. louisremi wrote on April 7th, 2011 at 01:16:

      @iLama: as localStorage is a very limited client-side storage (size limited to 5MB, no access to your file system), it doesn’t need to ask you for permission, unlike the file or geolocation APIs.
      This is not a bug, and if you think the implementation of store.js could be improved, feel free to fork it on Github.

  13. lobo_tuerto wrote on April 6th, 2011 at 09:28:

    Have a look at the comments on Hacker News for this article, it must be worth something:

    http://news.ycombinator.com/item?id=2414662

  14. Jonatan Littke wrote on April 7th, 2011 at 05:50:

    From a UX perspective, it’s a slippery slope using this on an edit form, where the value of the input field represents what’s currently stored in the database, and not what was lastly input.

    Imagine you edit something without saving, closing the page and coming back. if you then see your own text in one field you may get the impression the db has saved your edits, when in fact it hasn’t.

    1. louisremi wrote on April 7th, 2011 at 06:00:

      Persival is probably not appropriate for every form out there, but it’s supposed to save the content of the form as the user type. What is restored should be you last entered.

  15. Ryan wrote on April 8th, 2011 at 10:25:

    Is there any support for storing json objects as the namespace in IE? IE does not allow certain characters in “setAttribute” function.

    1. louisremi wrote on April 8th, 2011 at 10:30:

      @Ryan: store.js stores every object as JSON.
      Have you got example of strings that are not accepted?

      1. Ryan wrote on April 8th, 2011 at 10:35:

        Sure!

        Using the following value as the “key” will throw an error in IE6 and 7:

        {“Session”:”42.1″}

Comments are closed for this article.