I've only made three posts here so far and already I've lost a bunch of posts due to my session timing out, or me accidentally brining the server down mid post. Needless to say I think it's time I did something about this because there are few things worse than doing a whole bunch of work and then having it deleted in an instant. So here goes!

The solution could involve submitting to the server every so often to update an unpublished temporary post, but that relies on the internet connection. So I guess we could utilize local storage? How about using good old cookies? It was a great idea. I had this working too until I tried saving a fairly large post and the cookies would refuse to update the cookie. There has to be something else... 

After a quick searching around I discovered localStorage. This stuff is amazing! You just use it as a javascript object to save strings:

// Save the subject
localStorage.savedSubject = "How to not lose your blog post";

// Later on - recover the subject
$('#Subject').val(localStorage.savedSubject);

It appears you can only save strings in the objects. But lucky for JavaScript you can serialize and deserialize objects at will:

// Save the post
var savedBlogPost = {
 Subject: "How not to lose your blog post",
 Body: "I've only made about..."
};
localStorage.savedPost = JSON.stringify(savedBlogPost);

// Later on - recover the post
var recoveredBlogPost = JSON.parse(localStorage.savedPost);
$('#Subject').val(recoveredBlogPost.Subject);
$('#Body').val(recoveredBlogPost.Body);

So what's the down side? It's not in a cookie so it isn't sent to the server at all. That's fine though, we can get around that.

What we do is when you submit your form to add or update the blog post, we create a cookie that says "there is temporary data saved" and at that point we store the post data into a localStorage variable.

$('form').submit(function () { 
    utils.createCookieAndLocalStorage('postTempData', { 
        Subject: $('#Subject').val(), 
        Body: $('#Body').val()
    }); 
    return true; 
});

On the server side, after the changes are saved successfully we remove the cookie postTempData that indicates the temporary saved data. This completes the success scenario.

For the fail scenario, we imagine the server never gets the call to save the post, or there is an error saving the post. When we recover from the error (by logging out, restarting browser or whatever) we go back to the "make a blog post page" and a check is performed to see if the temporary saved data indicator cookie exists. If it does then we pull the data out of the cookie and place it into the form. If it doesn't then we just ignore whatever may be in the localStorage variable.

$(function() {
    var data = utils.getLocalStorageIfCookie('postTempData');
    if (data) {
        $('#Subject').val(data.Subject); 
        $('#Body').text(data.Body); 

        // Notify user that the post was restored
        $('#restoreWarning').show().click(function () {
            // Clear cookie and local storage data when restore is cancelled
            utils.removeCookie('postTempData'); 
        });
    }
});

The cookie utils code looks like this:

var utils = (function() { 
    this.cookieLocalStorageIndicator = "__localStorage"; 

    this.createCookieAndLocalStorage = function (name, value, days) { 
        if (value != null) {
            value = JSON.stringify(value); 
            localStorage.setItem(name, value); 
            value = utils.cookieLocalStorageIndicator;
        }

        var exdate = new Date(); 
        exdate.setDate(exdate.getDate() + days);
        document.cookie = name + "=" + escape(value) + "; path=/" + ((days == null) ? "" : "; expires=" + exdate.toUTCString()); 
    };

    this.getLocalStorageIfCookie = function (name) {
        // ridiculous looking code to get the cookie value
        var c_value = document.cookie;
        var c_start = c_value.indexOf(" " + name + "="); 
        c_start = c_start == -1 ? c_value.indexOf(name + "=") : c_start; 
        if (c_start == -1) c_value = null; 
        else { 
            c_start = c_value.indexOf("=", c_start) + 1; 
            var c_end = c_value.indexOf(";", c_start);
            c_value = unescape(c_value.substring(c_start, c_end == -1 ? c_value.length : c_end)); 
        }

        // if the cookie is in local storage, grab it from there
        if (c_value == utils.cookieLocalStorageIndicator) {
            c_value = localStorage.getItem(name);
        } else { 
            // otherwise, remove the item from local storage
            localStorage.removeItem(name); 
        } 

        try {  c_value = JSON.parse(c_value);  } catch (err) {   } 
        return c_value; 
    };
    return this; 
})();

So that's it. I should never lose a blog post again... in theory. I have so much faith in this system I am going to hit "Submit" now without copying this post...

I lied, I totally copied it.

Cheers, Rich
By Richard Rout
Feed
0 Comments
Only used for Gravatar avatar.