Tracking changes to a form

Jake Howlett, 16 March 2001

Category: JavaScript; Keywords: form change save

About a month ago I learnt of an IE specific event, called "onBeforeUnLoad", that allows you to capture the moment a user leaves a page. Using this, I wrote an article that described how to remind a user to save if they leave a page that happens to be a document in edit mode.

What this article overlooked was that even if a form is in edit mode it may not necessarily need saving as it may not have actually been altered. Wait though, Bob Mattler has come up with a solution. We can now loop through all the fields on the form and compare them to the original values. If any fields have changed then we can use the onBeforeUnload event to remind the user to save. Otherwise there is no need to confuse them with this method.

How did Bob do it? Well, his method makes use of the Document Object Model (DOM), with which we can check whether an input's current value is the same as its original value. Consider the following table. This shows us the way we can access the current and original value for each of the different inputs types:

Input Type Current Value Original Value
text obj.value obj.defaultValue
textarea obj.value obj.defaultValue
select-one obj.options[x].selected obj.options[x].defaultSelected
select-multiple obj.options[x].selected obj.options[x].defaultSelected
check-box obj.checked obj.defaultChecked
radio-button obj.checked obj.defaultChecked


Let's demonstrate using the form below. Click on the "Check" button first and see that is says "Unchanged". Now make some changes and press it again, it should say "Changed". Press the "Reset" button to send the values back to their defaults and you can do it again...

Type Field
text:
text:
radio-group: 1
2
3
check-box: Mail Me
Please Reply
select-one:
select-multi:
textarea:
 


"So!", you're saying "where's the code?". Well, it's here:

function isFormChanged() {
var rtnVal = false;
var frm = document.forms[0];
var ele = frm.elements;

for ( i=0; i < ele.length; i++ ) {
if ( ele[i].type.length > 0 ) {
if ( isElementChanged( ele, i ) ) {
rtnVal = true;
break;
}
}
}
return rtnVal;
}

function isElementChanged( ele, i ) {
var isEleChanged = false;

switch ( ele[i].type ) {

case "text" :
if ( ele[i].value != ele[i].defaultValue ) return true;
break;

case "textarea" :
if ( ele[i].value != ele[i].defaultValue ) return true;
break;

case "radio" :
val = "";
if ( ele[i].checked != ele[i].defaultChecked ) return true;
break;

case "select-one" :
for ( var x =0 ; x <ele[i].length; x++ ) {
if ( ele[i].options[ x ].selected
!= ele[i].options[ x ].defaultSelected )
return true;
}
break;

case "select-multiple" :
for ( var x =0 ; x <ele[i].length; x++ ) {
if ( ele[i].options[ x ].selected
!= ele[i].options[ x ].defaultSelected )
return true;
}
break;

case "checkbox" :
if ( ele[i].checked != ele[i].defaultChecked ) return true;

default:
return false;
break;
}
}

Basically this code does a loop through every element on the form and checks for a change. When it finds a change it returns true, otherwise it returns false.

The final step is to call the function. We did it here from a button using the following line of code in its onclick event:

alert( (isFormChanged()) ? 'Changed':'Unchanged');

You can download a sample html file from the "Document Detail" table on the left of this page. This demonstrates this method being used in conjunction with the onBeforeUnload event (IE Only!). This form contains all the source code you will need ;-)

About the author: Bob Mattler has been a Domino developer for 7 years and currently works for AngleBar.com



Note: This method checks EVERY field on the form. It will often be the case you don't want to do this. In that case modify the "isFormChanged()" function to accept an array of field objects and loop through these rather than "frm.elements".

Note: Any changes made to the form in the onLoad event using JavaScript will be considered a change as the value will no longer be the "default".