		var dates = new Array;
		var dateassociations = new Array;
		var datecount = 1;
		function checkrequired(event) {
			// Checks that required fields are filled in.
			// Required fields are those with class="required"
			if(event) {
				if(event.srcElement) {
					var formobj = event.srcElement;
				} else {
					var formobj = event.target;
				}
			} else {
				var formobj = this;
			}
		
			var error = checkrequirednode(formobj);
			// Check date fields
			for(var count = 1; count < datecount; count++) {
				if(dates[count]['day'] != '' || dates[count]['month'] != '' || dates[count]['year'] != '') {
					var name = dates[count]['prefix'];
					if(dates[count]['id'] != '') {
						var labels = document.getElementsByTagName('label');
						for(var labelcount = 0; labelcount < labels.length; labelcount++) {
							var label = labels[labelcount];
							if(label.htmlFor == dates[count]['id']) {
								name = gettextcontents(label);
							}
						}
					}
					if(dates[count]['day'] == '' || dates[count]['month'] == '' || dates[count]['year'] == '') {
						// Incomplete date. Error.
						error += '• Date in "'+name+'" is incomplete.\n';
					} else {
						// Check date validity
						var valid = true;
						var day = dates[count]['day'];
						var month = dates[count]['month'];
						var year = dates[count]['year'];
						var pattern = /^[0-9]{1,2}$/;
						if(!pattern.test(day)) {
							error += '• Day in "'+name+'" is invalid.\n';
							valid = false;
						}
						var pattern = /^[0-9]{1,2}$/;
						if(!pattern.test(month)) {
							error += '• Month in "'+name+'" is invalid.\n';
							valid = false;
						}
						var pattern = /^([0-9]{1,2}|[0-9]{4})$/;
						if(!pattern.test(year)) {
							error += '• Year in "'+name+'" is invalid.\n';
							valid = false;
						}
						if(valid) {
							if(year.length == 1) year = '200' + year;
							if(year.length == 2) year = '20' + year;
							day = parseInt(day, 10);
							month = parseInt(month, 10);
							year = parseInt(year, 10);
							if(year < 1970) {
								error += '• Year in "'+name+'" is too low.\n';
								valid = false;
							}
							if(valid) {
								if(month < 1) {
									error += '• Month in "'+name+'" is too low.\n';
									valid = false;
								} else if(month > 12) {
									error += '• Month in "'+name+'" is too high.\n';
									valid = false;
								} else if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
									var daysinmonth = 31;
								} else if(month == 2) {
									if(year % 4 == 0 && (year % 10 != 0 || year % 100 == 0)) { 
										var daysinmonth = 29;
									} else {
										var daysinmonth = 28;
									}
								} else { 
									var daysinmonth = 30;
								}
								if(valid) {
									if(day < 1) {
										error += '• Day in "'+name+'" is too low.\n';
										valid = false;
									} else if(day > daysinmonth) {
										error += '• Day in "'+name+'" is too high.\n';
										valid = false;
									}
								}
							}
						}
					}
				} else {
					// Empty. Nothing needs to be done here (if this is a required field it is dealt with in the
					// required field check).
				}
			}
			if(error != '') {
				alert('Unable to proceed:\n'+error);
				if(event.target) {
					event.preventDefault();
				}
				return false;
			} else {
				return true;
			}
		}
		function checkrequirednode(obj) {
			var error = '';
			for(var count = 0; count < obj.childNodes.length; count++) {
				var node = obj.childNodes[count];
				var tag = new String(node.tagName);
				tag = tag.toLowerCase();
				if((tag == 'input' || tag == 'select' || tag == 'textarea') && node.disabled == false) {
					var objclasses = ' ' + node.className + ' ';
					// Check required fields
					if(objclasses.indexOf(' required ') != -1) {
						if(node.value == '') {
							error += '• Required field "'+getnodename(node)+'" not filled in.\n';
						}
					}
					// Check numeric fields
					if(objclasses.indexOf(' numeric ') != -1 && node.value.length > 0) {
						var pattern = /^\-?[0-9,]*\.?[0-9,]*$/;
						if(!pattern.test(node.value)) {
							error += '• Field "'+getnodename(node)+'" must be a number.\n';
						}
					}
					// Check password fields
					if(objclasses.indexOf(' password ') != -1 && node.value.length > 0) {
						if(node.value.length > 0 && node.value.length < 5) {
							error += '• Field "'+getnodename(node)+'" must be at least 5 characters long.\n';
						}
					}
					// Check e-mail fields
					if(objclasses.indexOf(' email ') != -1 && node.value.length > 0) {
						var pattern = /^[^ @]+@[a-z0-9\-\.]+\.[a-z0-9]+$/
						if(!pattern.test(node.value)) {
							error += '• Field "'+getnodename(node)+'" must be a valid e-mail address.\n';
						}
					}
					// Check creditcard numbers
					if(objclasses.indexOf(' creditcard ') != -1 && node.value.length > 0) {
						var number = new String(node.value);
						number = number.replace(/[^0-9]*/g, '');
						var numlen = number.length;
						var sum = 0;
						for(var charno = numlen - 2; charno >= 0; charno -= 2) {
							var value = parseInt(number.substr(charno, 1), 10) * 2;
							if(value > 9) {
								value = Math.floor(value / 10) + (value % 10);
							}
							sum += value;
						}
						for(charno = numlen - 1; charno >= 0; charno -= 2) {
							sum += parseInt(number.substr(charno, 1), 10);
						}
						if(!(sum % 10 == 0)) error += '• "'+getnodename(node)+'" does not appear to be a valid credit card number.\n';
					}
					// Get date fields into array
					if(objclasses.indexOf(' date ') != -1) {
						if(node.name.indexOf('day') == node.name.length - 3) {
							var prefix = node.name.substr(0, node.name.length - 3);
							if(dateassociations[prefix]) {
								var number = dateassociations[prefix];
							} else {
								var number = datecount;
								dateassociations[prefix] = number;
								//alert('1: '+node.name+' '+prefix+' '+dateassociations[prefix]);
								dates[number] = new Array;
								datecount++;
							}
							dates[number]['day'] = node.value;
							dates[number]['id'] = node.id;
							dates[number]['prefix'] = prefix;
						}
						if(node.name.indexOf('month') == node.name.length - 5) {
							var prefix = node.name.substr(0, node.name.length - 5);
							if(dateassociations[prefix]) {
								var number = dateassociations[prefix];
							} else {
								var number = datecount;
								dateassociations[prefix] = number;
								//alert('2: '+node.name+' '+prefix+' '+dateassociations[prefix]);
								dates[number] = new Array;
								datecount++;
							}
							dates[number]['month'] = node.value;
						}
						if(node.name.indexOf('year') == node.name.length - 4) {
							var prefix = node.name.substr(0, node.name.length - 4);
							if(dateassociations[prefix]) {
								var number = dateassociations[prefix];
							} else {
								var number = datecount;
								dateassociations[prefix] = number;
								//alert('3: '+node.name+' '+prefix+' '+dateassociations[prefix]);
								dates[number] = new Array;
								datecount++;
							}
							dates[number]['year'] = node.value;
						}
					}
				} else {
					// Check all child nodes
					error += checkrequirednode(node);
				}
			}
			return error;
		}
		function getnodename(node) {
			var name = node.name;
			if(node.id != '') {
				var labels = document.getElementsByTagName('label');
				for(var labelcount = 0; labelcount < labels.length; labelcount++) {
					var label = labels[labelcount];
					if(label.htmlFor == node.id) {
						name = gettextcontents(label);
					}
				}
			}
			return name;
		}
		function gettextcontents(node) {
			var textcontents = '';
			for(var childcount = 0; childcount < node.childNodes.length; childcount++) {
				if(node.childNodes[childcount].nodeType == 3) {
					// TEXT_NODE
					textcontents += node.childNodes[childcount].data;
				} else {
					textcontents += gettextcontents(node.childNodes[childcount]);
				}
			}
			return textcontents;
		}
		
		// Add onsubmit handlers to any <form>s
		addevent(window, "load", addformchecks);
		function addformchecks() {
			var forms = document.getElementsByTagName('form');
			for(var count = 0; count < forms.length; count++) {
				var form = forms[count];
				addevent(form, "submit", checkrequired);
			}
		}
		
		function addevent(elm, evType, fn, useCapture)
		// cross-browser event handling for IE5+,  NS6 and Mozilla
		// By Scott Andrew
		{
			if(elm.attachEvent) {
				var r = elm.attachEvent("on"+evType, fn);
				return r;
			} else if(elm.addEventListener) {
				elm.addEventListener(evType, fn, useCapture);
				return true;
			} else {
				//alert("Handler could not be removed");
			}
		} 
		
