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);

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);
				// standard values
				c = (n.value != n.defaultValue);

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">

	<legend>Your profile</legend>

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

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

		<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>

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


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.

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 written more than 1,000 articles for SitePoint and you can find him @craigbuckler

Free Guide:

How to Choose the Right Charting Library for Your Application

How do you make sure that the charting library you choose has everything you need? Sign up to receive this detailed guide from FusionCharts, which explores all the factors you need to consider before making the decision.

  • Andy Parkhill

    Hi Craig,
    Thanks for providing this solution. I have just checked the function against some forms, and it appears to fail to detect changes made in textareas. I’m using IE7 as a browser.

    • Andy Parkhill


      Apologies, after a little further digging, it appears that this textarea is actually using an IFRAME under the covers (it is a SharePoint 2010 page). So your function above is probably valid for typical HTML pages. Sorry!


Learn JavaScript for free!
Free course: Introduction to JavaScript

Yours when you take up a free 14-day SitePoint Premium trial.