How to Write a Generic Form Update Detection Function in JavaScript

Share this article

Key Takeaways

  • The FormChanges() function in JavaScript can be used to detect updates to any form by accepting a single overloaded form argument, either the form’s DOM node or the string ID, and returning an array of form element nodes which the user has changed.
  • The function will return NULL if no form could be found and is designed to be compatible with all JavaScript libraries and work in all modern browsers, including IE6 and IE7.
  • Practical applications of the FormChanges() function include alerting users to the number of field updates they’ve made or updating a hidden value to indicate no changes have been made, allowing server-side code to skip field validation and database updates.
In my last post we discovered how to check whether individual form elements had been changed by the user. Today, we’ll use that information to write JavaScript code which can detect updates to any form. Here are the examples and code links:

Our Prerequisites

Since we’re all good developers, we’ll define our requirements before cutting any code:
  • We’ll write a function, FormChanges(), which accepts a single overloaded form argument — either the form’s DOM node or the string ID.
  • The function will return an array of form element nodes which the user has changed. This allows us to determine which fields have changed or, if the array is empty, that no fields have changed.
  • The function will return NULL if no form could be found.
  • We won’t depend on any specific JavaScript library so the function remains compatible with all of them.
  • It must work in all modern browsers — and IE6 or IE7.

The FormChanges() Function

To ease you in gently, here’s the start of our function:

function FormChanges(form) {
We’re overloading the form argument — it can be a DOM element but, if it’s an ID string, we need to locate that element in the DOM:

if (typeof form == "string") form = document.getElementById(form);
If we don’t have a form node, the function will return null without doing any further work:

if (!form || !form.nodeName || form.nodeName.toLowerCase() != "form") return null;
We’ll now declare variables which we’ll use throughout the function:
  • ‘changed’ is the returned array of form elements which have been updated by the user
  • ‘n’ is a form element node
  • ‘c’ is set to true if an element has been changed
  • ‘def’ is the default option for select boxes
  • ‘o’, ‘ol’, and ‘opt’ are temporary variables used within loops

var changed = [], n, c, def, o, ol, opt;
We can now start our main loop which examines every form element in turn. c is initially set to false indicating that no changes have been made to the element we’re inspecting:

for (var e = 0, el = form.elements.length; e < el; e++) {
	n = form.elements[e];
	c = false;
Next, we’ll extract the node name (input, textarea, select) and examine it within a switch statement. We’re only looking for select and non-select nodes, so a switch statement isn’t strictly necessary. However, it is easier to read and allows us to add further node types when they are introduced. Note that most browsers return the node name in uppercase but we’re playing it safe and always converting the string to lowercase.

switch (n.nodeName.toLowerCase()) {
The first case statement evaluates select drop-downs. This is the most complex check since we must loop through all child option elements to compare the selected and defaultSelected properties. The loop also sets def to the last option with a ‘selected’ attribute. If we have a single-choice box, def is then compared against that node’s selectedIndex property to ensure we’re handling situations where no option or more than one option element has a ‘selected’ attribute (refer to the previous article for a full explanation).

// select boxes
case "select":
	def = 0;
	for (o = 0, ol = n.options.length; o < ol; o++) {
		opt = n.options[o];
		c = c || (opt.selected != opt.defaultSelected);
		if (opt.defaultSelected) def = o;
	}
	if (c && !n.multiple) c = (def != n.selectedIndex);
	break;
We now need to handle input and textarea elements. Note that our case "textarea": statement does not use a break so it falls through into the case "input": code. Checkboxes and radio elements have their checked and defaultChecked properties compared while all other types have their value compared with the defaultValue:

	// input / textarea
	case "textarea":
	case "input":

		switch (n.type.toLowerCase()) {
			case "checkbox":
			case "radio":
				// checkbox / radio
				c = (n.checked != n.defaultChecked);
				break;
			default:
				// standard values
				c = (n.value != n.defaultValue);
				break;
		}
		break;
}
If the value of c is true, the element has changed so we append it to the changed array. The loop is now complete:

	if (c) changed.push(n);
}
We just need to return the changed array and end the function:

	return changed;
}

Example Uses

Assume we’ve created the following form:

<form id="myform" action="index.html" method="post">
<fieldset>

	<legend>Your profile</legend>

	<input type="hidden" id="changed" name="changed" value="yes" />

	<div>
		<label for="name">name:</label>
		<input type="text" id="name" name="name" value="Jonny Dough" />
	</div>

	<div>
		<label for="job">job title:</label>
		<select id="job" name="job">
			<option>web designer</option>
			<option selected="selected">web developer</option>
			<option>graphic artist</option>
			<option>IT professional</option>
			<option>other</option>
		</select>
	</div>

	<div>
		<button type="submit">Update Profile</button>
	</div>

</fieldset>
</form>
We can check whether the user has changed any form fields using code such as:

var changed = FormChanges("myform");
alert(changed.length + " field(s) have been updated.");
Or, if no changes have occurred, we could update the hidden “changed” value to “no” when the form is submitted. This would allow the server-side code to skip field validation and database updates:

var form = document.getElementById("myform");
form.onsubmit = function() {
	if (FormChanges(form).length == 0) {
		document.getElementById("changed").value = "no";
	}
	return true;
}
(Note: changing “yes” to “no” degrades gracefully since, if JavaScript isn’t available, the server will always process the incoming data.) I hope you find it useful.

Frequently Asked Questions (FAQs) about JavaScript Form Change Checker

How does JavaScript Form Change Checker work?

JavaScript Form Change Checker is a script that checks if any changes have been made to a form. It works by comparing the initial state of the form when the page is loaded to the current state of the form. If any changes are detected, it triggers an event or a function. This is particularly useful in scenarios where you want to alert the user about unsaved changes before they navigate away from the page.

How can I implement JavaScript Form Change Checker in my code?

To implement the JavaScript Form Change Checker, you need to include the script in your HTML file. Then, you can call the function on any form you want to monitor for changes. The function will then keep track of the initial state of the form and compare it to the current state whenever a change is made.

Can I use JavaScript Form Change Checker with multiple forms on the same page?

Yes, you can use the JavaScript Form Change Checker with multiple forms on the same page. Each form will be tracked independently, and changes to one form will not affect the tracking of other forms.

What happens if a user navigates away from the page without saving changes?

If a user navigates away from the page without saving changes, the JavaScript Form Change Checker can trigger an alert to the user. This alert can inform the user that they have unsaved changes and give them the option to stay on the page and save their changes.

Can I customize the alert message that is displayed when unsaved changes are detected?

Yes, you can customize the alert message that is displayed when unsaved changes are detected. You can do this by modifying the script to include your custom message.

Is JavaScript Form Change Checker compatible with all browsers?

JavaScript Form Change Checker is compatible with all modern browsers that support JavaScript. However, it may not work correctly in older browsers that do not fully support JavaScript.

Can I use JavaScript Form Change Checker with forms that use AJAX?

Yes, you can use JavaScript Form Change Checker with forms that use AJAX. The script will still be able to detect changes made to the form, even if the form is submitted using AJAX.

How can I disable the JavaScript Form Change Checker for a specific form?

To disable the JavaScript Form Change Checker for a specific form, you can modify the script to exclude that form from being tracked. This can be done by adding a condition in the script that checks the ID or class of the form before tracking changes.

Can I use JavaScript Form Change Checker with forms that have dynamically added fields?

Yes, you can use JavaScript Form Change Checker with forms that have dynamically added fields. The script will be able to detect changes made to these fields as well.

How can I test if the JavaScript Form Change Checker is working correctly?

To test if the JavaScript Form Change Checker is working correctly, you can make changes to a form that is being tracked and then attempt to navigate away from the page. If the script is working correctly, you should see an alert informing you of unsaved changes.

Craig BucklerCraig Buckler
View Author

Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.

formhtmlinputjavascript
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week