Feb 1 2010

Check for unsaved data on your web forms using jQuery

Category: NovoGeek @ 08:55
One of the most important Usability requirements in business applications is, to periodically inform the users when there is any unsaved data on their web pages. This can be seen in email apps like Live mail/Gmail (compose a new mail and try to navigate to Inbox, without saving or sending the mail. An alert will pop out asking to save the mail).

To meet this requirement, one page load, one should loop through all the controls of the page, store the initial values of the controls, bind blur event handlers to all the controls, on blur event compare the final value with the initially stored values. If there is any change in the value, mark the form as dirty (unsaved data), else mark it as clean (saved data).

jQuery Dirty Form plug-in:

I started writing my own code, but found the beautiful dirty form plug-in. Thanks to the author Wilson for the plug-in, which does exactly the same as my pseudo-code. To check for a dirty form, all you need to do is:

$(document).ready(function(){
   $("#YourFormId")
     .dirty_form()
     .dirty(function(event, data){
       //The dirty event fires when you blur from a control after changing its value.
     })
 });

The plug-in is not well documented, hence you should spend time walking through the code. The plug-in will set a flag to the form’s data, to indicate if it is dirty or not, like this:

form.data("dirty", true) 

The dirty() event in snippet 1 will set the dirty flag to true. So at a later stage if you need to check the form’s status, you should use the form’s data. To a good extent I could leverage the the plug-in, but to meet my project specifications, I had to tweak it a lot.

Bug in Dirty Form plug-in and fix for the bug:

The plug-in has a function called “input_checker”, which will check for form status on each control’s blur. As said earlier, it will compare the initially stored values with final ones, which is fine. However, if you switch between forms, the data of one form will be compared with data of latest form, which spoils the show. I’m not sure why others haven’t raised the bug, but I’m very sure of it. Hence publishing the below fix:

In the “input_checker” function, replace the below code

input_checker : function(event){
    var npt... ... ...
    inputs = event.data.inputs, settings = event.data.settings

with this one:

input_checker : function(event){
    var npt ... ... ...
    inputs = $(':input:not(:hidden,:submit,:password,:button)', form), settings = event.data.settings

What is happening is, the plug-in is caching all the inputs to be checked in data parameter of the form. When we navigate to a new form, the controls of old form(from cache) are being checked, instead of the controls from new form. Hence I am querying the controls of new form again and using it for comparison. This would solve the problem :)

Here are some of the functionalities which I could leverage using the plug-in:

(1) On page load you can disable save buttons and enable them only in the dirty() event.

(2) You can check for form dirty flag and decide to extend user’s session accordingly.

(3) You can give a warning when user navigates to another page without saving data (similar to Gmail/Live mail).

Thanks to Wilson once again for the plug-in. Hope the fix would help some of the folks who are facing similar issues. 

Happy coding :)

Tags:

blog comments powered by Disqus