I've been working on a dashboard which provides a number of widgets, each of which can be expanded or collapsed to show/hide their contents. The goal was to save the "state" of the dashboard so when the user returns next time, the widgets are expanded or collapsed just as they were before.

This capability is nothing new, it's been done with AJAX for over a decade now. AJAX allowed the user to make changes to the state of an element, at which point the browser would fire up an AJAX request to the server to store the new element state.

This was awesome in every way except for three:

  • Shared preferences. We've come a long way, but a lot of people still share user accounts. A company, for instance, may have one "master" account that all user's log in with to manage their extranet. When storing user preferences on the server, tied to an account, all users of that "master" account will have to share the same UI settings.
  • Storage. Additional data, which is arguably of absolutely zero analytical value (UI preferences), must be stored within the database.
  • Performance. A UI that gets a good amount of traffic will send an exponentially higher amount of AJAX requests to the server.


Shifting it to the client side

We can overcome the above three issues by leveraging HTML 5's Storage module, which is available in all browsers, except IE 6/7. It's up to you whether or not to completely abandon your IE 6/7 users, or to "progressively enhance" their experience by offering an AJAX backup option. Personally, I'd say take a hike to IE 6/7 users!

To continue my example of the expanded or collapsed widgets, the code below essentially does the following:

  1. Stores a single JSON encoded variable in the browser's localStorage.
  2. This variable identifies which widgets should be collapsed when the page is rendered.
  3. When a user clicks the icon to collapse a widget, the localStorage variable is updated.


(function() {

    /* setup the expand / collapse event, which will
       store the preference in localStorage */

    $('.widget-actions .toggle').click(function() {
        if (typeof Storage !== 'undefined') {
            var collapsed = [];
            $('.widget').each(function() {
                if ($(this).hasClass('collapsed')) {

    /* when the page is loaded, check for the existence
       of the localStorage variable, then collapse the widgets */

    if (typeof Storage !== 'undefined') {
        var dashboard_collapsed = 
        if (dashboard_collapsed) {       
            dashboard_collapsed = JSON.parse(dashboard_collapsed);
            $.each(dashboard_collapsed, function(index, element) {
                $('#' + element).find('.toggle').click();

Leave a Reply

Your email address will not be published. Required fields are marked *