After Thought

Track changes if form fields are changed on a web page

leave a comment »

A very useful feature to have on a web page is to remind the user of unsaved changes when he/she navigates away from the page without saving. A easy way to implement this is to set a global flag when a form is changed. Based on the flag value, pop a dialog when the user tries to navigate away from the web page without saving. This approach has several flaws, the obvious one being the usage of a global variable. It also fails if the user reverts his changes.

A better solution is to keep track of all the fields on the page and display the dialog only when there is a change. If we were to implement such a tracker, it  has to do the following.

Step 1: Scan all the form fields like textbox, textarea, checkbox etc to and store the existing values when the page loads.

Step 2: When the user makes a change, attach an event on all the links to pop a dialog when the user clicks on it without saving.

Step 3: Remove the attached events, if the user reverts those changes.

Here is an example web page.

If the user edits Name field and clicks on My Blog link without saving, it should pop a dialog as shown below:

Dialog in the example is dialog from jqueryui .

track.js keeps track of changes on the form and makes it possible to hook before change and after change events.  Assuming the form id is editForm, call trackchanges (with events you want to associate with) in your document ready function. Hook a dialog open event in the afterChangeAction and remove it in beforeChangeAction.

Below is the code listing.

jQuery(document).ready(function($) {
	var beforeChangeAction = function () {
        $("a[id^='lnk']").each(function() {
            $("#" + this.id).die('click');
        });

    };

    var afterChangeAction = function () {
        $("a[id^='lnk']").each(function() {
            var id = this.id;
            $("#" + id).live('click', function (e) {
                bindModalConfirmationDialogFor(id, redirectAction);
                openConfirmationDialog(e, "Any changes made will be lost. Are you sure you want to continue?");
            });
        });
    };

	$("#editForm").trackchanges({events: "change blur keyup mousedown", exclude: "exclude", beforeChangeAction: beforeChangeAction, afterChangeAction: afterChangeAction});
});

function bindModalConfirmationDialogFor(fld, action) {
    var dialogOpts = {
        modal: true,
        autoOpen: false,
        buttons: {
            'No': function() {
                $(this).dialog('close');
            },
            'Yes': function() {
                action(fld);
                $(this).dialog('close');
            }
        }
    };
    $("#dialog-confirm").dialog(dialogOpts);
}

function openConfirmationDialog(e, message) {
    e.preventDefault();
    $("#dialog-confirm").html("<p><span class='ui-icon ui-icon-alert' style='float:left; margin: 0 7px 20px 0;'></span>" + message + "</p>");
    $("#dialog-confirm").dialog("open");
}

function redirectAction(fld) {
    window.location.href = $("#"+fld).attr("href");
}

The problem with this approach is, it is obtrusive. The user is forced to click twice to navigate without saving. What would be really cool is if we can change the color of the banner on the page as the user edits any form field. Further, we can change the color back to the original state when the user reverts those changes without ever refreshing the page. It would be a seamless unobtrusive experience to users reminding them to save the page before navigating to a different page (Some of the websites out there already have this nifty feature). As an example let us change the color of the Banner shown below from blue to yellow when a user edits any form field.

If we were to implement such a tracker, it  has to do the following.

Step 1: Scan all the form fields like textbox, textarea, checkbox etc to and store the existing values when the page loads.

Step 2: When the user edits any field check if the new value of that field is different from the old value; change the color of the Banner from blue to yellow.

Step 3: Revert the color back to blue, if the user reverts those changes.

Below is the code listing:

jQuery(document).ready(function($) {
	var beforeChangeAction = function () {
        $("#buttons").css("background-color", "#bcd3e9");
        if ($("#changed-text").length > 0) {
            $("#changed-text").remove();
        }
    };

    var afterChangeAction = function () {
        $("#buttons").css("background-color", "#fbec88");
        if ($("#changed-text").length === 0) {
            $("#buttons").prepend("<span id='changed-text'>Changes not saved</span>");
        }
    };

	$("#editForm").trackchanges({events: "change blur keyup mousedown", exclude: "exclude", beforeChangeAction: beforeChangeAction, afterChangeAction: afterChangeAction});
});

You can choose to exclude a field or a form with a class. In the example above we excluded Exclude Changes field by adding class “exclude”.

<input type='text' id='exclude_changes' name='exclude_changes' class='exclude' value=''/>

FormChangeTracker project is available on github. You can find code for both the above examples along with track.js.

About these ads

Written by shashankshetty

November 4, 2011 at 5:16 pm

Posted in javascript, Uncategorized

Tagged with ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.