/* Automated form validation using a set of basic validation checks.              */
/* Copyright © 2006 Frontmedia Studio Ltd.                                        */
/*                                                                                */
/* Version 1.1 (4/1/07)                                                           */
/*    Added validateFileExtensions()                                              */
/*                                                                                */
/* Version 1.0 (25/12/06)                                                         */
/*    Initial version                                                             */
/*                                                                                */
/* The following code must appear in <script> tags after your form:               */
/*                                                                                */
/* <script language="javascript" type="text/javascript">                          */          
/* <!--                                                                           */
/* var formValidator = new FormValidator("customerForm");                         */
/* formValidator.addValidation("fieldName","validation type","An error message"); */
/* formValidator.addValidation("fieldName","validation type","An error message"); */
/* ...                                                                            */
/* ...                                                                            */
/* -->                                                                            */
/* </script>                                                                      */
/*                                                                                */
/* You can also add an additional more complicated validation function adding the */
/* following:                                                                     */
/*                                                                                */
/* ...                                                                            */
/* formValidator.addExtraValidation("functionName('fieldName', argument1, ...)"); */
/* ...                                                                            */
/*                                                                                */
/* You should format the rows of your form layout in the following way:           */
/*                                                                                */
/* <tr id="fieldNameError" class="error" style="display: none;">                  */
/*   <td class="label">&nbsp;</td>                                                */
/*   <td><span id="fieldNameMessage">&nbsp;</span></td>   */
/* </tr>                                                                          */
/* <tr id="fieldNameRow">                                                         */
/*   <td class="label">Field Label</td>                                           */
/*   <td><input name="fieldName" id="fieldName" type="text" maxlength="50" /></td>*/
/* </tr>                                                                          */
/*                                                                                */
/* If you choose not to use this layout method, the validation will still work,   */
/* but will default to individual Javascript alert boxes for each error.          */
/*                                                                                */
/* You may also optionally present a global error message, alerting the user to   */
/* the fact that there were errors somewhere in the form, by including this row   */
/* at the top of your form table:                                                 */
/*                                                                                */
/* <tr id="globalError" class="error" style="display: none;">                     */
/*   <td class="label"><img src="error.gif" /> Error</td>                         */
/*   <td>There was a problem.</td>                                                */
/* </tr>                                                                          */
/*                                                                                */
/*                                                                                */
/* Current validation types:                                                      */
/*                                                                                */
/* required: Use for required text, textarea and password fields                  */
/* maxlength=n: Limit the length of input in a field to n characters              */
/* minlength=n: Ensure that the length of input in a field is at least n chars    */
/* maxvalue=n: Limit the value entered into a field to n                          */
/* minvalue=n: Ensure that a value entered into a field is at least n             */
/* alpha: Value must be alphabetic only (A-Z,a-z)                                 */
/* alphauc: Value must be upper-case alphabetic only (A-Z)                        */
/* alphalc: Value must be lower-case alphabetic only (a-z)                        */
/* alphanumeric: Value must be alpha-numeric only (A-Z,a-z,0-9)                   */
/* alnumspace: Value must be alpha-numeric, but may contain spaces                */
/* alnumhyphen: Value must be alpha-numeric, but may contain hyphens              */
/* alnumhyphenspace: As alnumhyphen, but may also contain spaces                  */
/* alnumdash: Value must be alpha-numeric, but may contain dashes (-_/)           */
/* alnumdashspace: As alnumdash, but may also contain spaces                      */
/* numeric: Value must be numeric only (0-9)                                      */
/* decimal: Value must be numeric, with optional decimal part (eg. 10, 10.1, -10) */
/* positivedecimal: Value must be a positive decimal                              */
/* money: Value must be in money format. Can contain commas and 2 decimal places. */
/* username: Value must be alpha-numeric, but may also contain: .-_               */
/* email: Value must be a valid e-mail address                                    */
/* telephone: Value must be numeric, but may also contain spaces and: +-()        */
/* uktelephone: Value must be a valid UK telephone number                         */
/* postcode: Value must be a valid UK postcode                                    */
/* datetime: Value must be a valid date/time in UK format                         */
/* usdatetime: Value must be a valid date/time in US format                       */
/* eq=n: Value must be equal to n                                                 */
/* lt=n: Value must be less than n (same as maxvalue)                             */
/* gt=n: Value must be greater than n (same as minvalue)                          */
/* regexp: Validates value against a valid regular expression                     */
/* select=n: Used for 'please select' select boxes to prevent option n being pick */
/*                                                                                */
/* Current extra validation functions:                                            */
/*                                                                                */
/* validateMultiSelect(inputItem, errorString, minS, maxS)                        */
/* Checks a multi-select input to make sure that a minimum of minS and optionally */
/* a maximum of maxS selections have been made                                    */
/*                                                                                */
/* validateCheckboxes(inputList, errorString, minC, maxC)                         */
/* Examines a list of checkbox inputs to make sure that a minimum of minC and     */
/* optionally a maximum of maxC boxes have been checked                           */
/*                                                                                */
/* validateRadios(inputItem, errorString, itemIndex)                              */
/* Checks a named radio button group to see if a selection has been made.         */
/* You may also optionally specify an index number of a specific radio button     */
/* that must be selected.                                                         */
/*                                                                                */
/* compareFields(inputItem, inputCompare, comparison, errorString)                */
/* Compares the values of two input fields based on the specified comparison      */
/* (eg. eq, lt, gt, lte, gte)                                                     */
/*                                                                                */
/* validateDateSelect(daySelectItem, monthSelectItem, yearSelectItem,             */
/*                    errorString)                                                */
/* Checks the contents of a set of date select fields (eg. Day Month Year) for a  */
/* valid date. If the date is optional (ie. if there are more than 12 options for */
/* month), and no values have been selected, the check is bypassed.               */
/*                                                                                */
/* compareDateSelect(daySelectItem, monthSelectItem, yearSelectItem,              */
/*                   comparison, errorString,                                     */
/*                   daySelectCompare, monthSelectCompare, yearSelectCompare)     */
/* Compares the contents of two sets of date select fields (eg. Day Month Year)   */
/* based on the specified comparison (eg. lt, gt, eq). If the second set of date  */
/* select fields is not specified, the date is compared to the current date       */
/* instead.                                                                       */
/*                                                                                */
/* validateFileExtensions(inputItem, extList, errorString)                        */
/* Checks a file upload input to make sure that only those file extensions in the */
/* comma-delimited list (extList) are allowed eg. 'jpg,jpeg,gif'                  */
/*                                                                                */

function trim(str) {
  return str.replace(/^\s+|\s+$/g, '');
}

function FormValidator(formName) {
	/* Form validator object */
  this.formObject=document.forms[formName];
	this.formObject.extraValidationSet = new Array();
	this.formObject.oldSubmit = this.formObject.onsubmit;
	this.formObject.onsubmit = onSubmitHandler;
	this.addValidation = addValidation;
	this.addExtraValidation = addExtraValidation;
	this.clearAllValidations = clearAllValidations;
	this.formObject.initGlobalError = initGlobalError;
	this.formObject.showGlobalError = showGlobalError;
	this.formObject.initError = initError;
	this.formObject.showError = showError;
	this.formObject.showErrorRow = showErrorRow;
	this.formObject.addError = addError;
}

function addExtraValidation(functionString) {
	/* Add an extra validation function to the form */
  this.formObject.extraValidationSet[this.formObject.extraValidationSet.length] = functionString;
	var functionName = functionString.substring(0,functionString.indexOf('('));
	this.formObject[functionName] = eval(functionName);
}

function clearAllValidations() {
	/* Removes all validation checks */
	for(var i=0; i < this.formObject.elements.length; i++) {
		this.formObject.elements[i].validationSet = null;
	}
}

function onSubmitHandler() {
	var validated = true;
	var focusField = '';
	initGlobalError();
	for(var i=0; i < this.elements.length; i++) {
		/* Run the validation set for each form element */
		initError(this.elements[i]);
		if(this.elements[i].validationSet && !this.elements[i].validationSet.validateSet()) {
			if(focusField == '') {
				focusField = this.elements[i].name;
			}
			validated = false;
		}
	}
	/* Run any additional validation functions for this form */
	if(this.extraValidationSet.length > 0) {
	  for(var i=0; i < this.extraValidationSet.length; i++) {
      if(!eval('this.' + this.extraValidationSet[i])) {
		   validated = false;
		  }
		}
	}
	if(!validated) {
		showGlobalError();
		if(focusField != '') {
		  this[focusField].focus();
		}
		return false;
	}
	/* If onsubmit already set for the form, run that function now */
	if(typeof this.oldSubmit == 'function'){
		return this.oldSubmit();
	}
	return true;
}

function addValidation(itemName,descriptor,errorString) {
  /* Adds a validation check to a form field */
	var itemObject = this.formObject[itemName];
	if(!itemObject.validationSet) {
	  itemObject.validationSet = new ValidationSet(itemObject);
	}
  itemObject.validationSet.addValidationCheck(descriptor,errorString);
}

function ValidationCheck(inputItem,descriptor,errorString) {
	/* Validation check object */
  this.descriptor = descriptor;
	this.errorString = errorString;
	this.itemObject = inputItem;
	this.validate = validate;
}

function validate() {
	/* Run an individual validation check */
	var fieldError = this.itemObject.name + 'Error';
	var fieldMessage = this.itemObject.name + 'Message';
	var fieldRow = this.itemObject.name + 'Row';
	if(!validateData(this.descriptor,this.itemObject)) {
		addError(this.itemObject, this.errorString);
		return false;
	}
	return true;
}

function ValidationSet(inputItem) {
	/* Validation object set object */
  this.validationSet = new Array();
	this.addValidationCheck = addValidationCheck;
	this.validateSet = validateSet;
	this.itemObject = inputItem;
}

function addValidationCheck(descriptor,errorString) {
	/* Add a validation check to the set */
  this.validationSet[this.validationSet.length] = new ValidationCheck(this.itemObject,descriptor,errorString);
}

function validateSet() {
	/* Run all validation checks in the set */
	var fieldValidated = true;
	for(var i=0; i < this.validationSet.length; i++) {
	  if(!this.validationSet[i].validate()) {
		  fieldValidated = false;
			break;
	  }
	}
	if(!fieldValidated) {
		showError(this.itemObject);
		return false;
	}
	return true;
}

function initGlobalError() {
	if(document.getElementById('globalError')) {
		document.getElementById('globalError').style.display = 'none';
	}
}

function showGlobalError() {
	if(document.getElementById('globalError')) {
		document.getElementById('globalError').style.display = '';
	}
}

function initError(inputItem) {
	var fieldError = inputItem.name + 'Error';
	var fieldMessage = inputItem.name + 'Message';
	var fieldRow = inputItem.name + 'Row';
	if(document.getElementById(fieldError)) {
		document.getElementById(fieldError).style.display = 'none';
	}
	if(document.getElementById(fieldMessage)) {
	  document.getElementById(fieldMessage).innerHTML = '&nbsp;';
	}
	if(document.getElementById(fieldRow)) {
		document.getElementById(fieldRow).className = '';
	}
}

function showError(inputItem) {
	var fieldError = inputItem.name + 'Error';
	if(document.getElementById(fieldError)) {
		document.getElementById(fieldError).style.display = '';
		showErrorRow(inputItem);
	}
}

function showErrorRow(inputItem) {
	var fieldRow = inputItem.name + 'Row';
	if(document.getElementById(fieldRow)) {
		document.getElementById(fieldRow).className = 'error';
	}
}

function addError(inputItem, errorString) {
	var fieldMessage = inputItem.name + 'Message';
	if(document.getElementById(fieldMessage)) {
		if(document.getElementById(fieldMessage).innerHTML == '&nbsp;' || trim(document.getElementById(fieldMessage).innerHTML) == ''){
	    document.getElementById(fieldMessage).innerHTML = errorString;
			return true;
		} else {
			return false;
		}
	} else {
		alert(errorString);
		return true;
	}
}

function validateDecimal(decimalValue) {
	/* Validates decimal numbers */
  if(trim(decimalValue).length <= 0) {
	  return true;
	}
  return decimalValue.match(/^(\+|-)?[0-9][0-9]*(\.[0-9]*)?$/) != null;
}

function validateDecimalNonNeg(decimalValue) {
	/* Validates non-negative decimals */
  if(trim(decimalValue).length <= 0) {
	  return true;
	}
  return decimalValue.match(/^[0-9][0-9]*(\.[0-9]*)?$/) != null;
}

function validateMoney(moneyValue) {
	/* Validates a decimal money value with optional decimal point values up to 2 characters */
  if(trim(moneyValue).length <= 0) {
	  return true;
	}
  return moneyValue.match(/^(\+|-)?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/) != null;
}

function validateTelephone(telephone) {
	/* Simple validation for allowed characters in telephone numbers */
  if(trim(telephone).length <= 0) {
	  return true;
	}
	return telephone.match(/^[0-9\s\(\)\+\-]+$/) != null;
}

function validateUKTelephone(telephone) {
	/* Validates UK-specific telephone numbers */
  if(trim(telephone).length <= 0) {
	  return true;
	}
	return telephone.match(/(^0[1-9]\d{1}\s\d{4}\s?\d{4}$)|(^0[1-9]\d{2}\s\d{3}\s?\d{4}$)|(^0[1-9]\d{2}\s\d{4}\s?\d{3}$)|(^0[1-9]\d{3}\s\d{3}\s?\d{2}$)|(^0[1-9]\d{3}\s\d{3}\s?\d{3}$)|(^0[1-9]\d{4}\s\d{3}\s?\d{2}$)|(^0[1-9]\d{4}\s\d{2}\s?\d{3}$)|(^0[1-9]\d{4}\s\d{2}\s?\d{2}$)/) != null;
}

function validatePostcode(postcode) {
	/* Validates UK postcodes */
  if(trim(postcode).length <= 0) {
	  return true;
	}
	return postcode.match(/^[A-Za-z]{1,2}[0-9A-Za-z]{1,2}[ ]?[0-9]{0,1}[A-Za-z]{2}$/) != null;
}

function validateEmail(email) {
	/* Simple validation for an e-mail address */
  if(trim(email).length <= 0) {
	  return true;
	}
	var splitted = email.match(/^(.+)@(.+)$/);
	if(splitted == null) return false;
	if(splitted[1] != null ) {
		var regexp_user=/^\"?[\w-_\.]*\"?$/;
		if(splitted[1].match(regexp_user) == null) return false;
	}
	if(splitted[2] != null) {
		var regexp_domain=/^[\w-\.]*\.[A-Za-z]{2,4}$/;
		if(splitted[2].match(regexp_domain) == null) 
		{
		var regexp_ip =/^\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]$/;
		if(splitted[2].match(regexp_ip) == null) return false;
		}// if
		return true;
	}
  return false;
}

function validateUSDateTime(datetimeString) {
	/* Validates US format dates and/or times (eg. mm/dd/yy hh:mm:ss)*/
  return datetimeString.match(/(?=\d)^(?:(?!(?:10\D(?:0?[5-9]|1[0-4])\D(?:1582))|(?:0?9\D(?:0?[3-9]|1[0-3])\D(?:1752)))((?:0?[13578]|1[02])|(?:0?[469]|11)(?!\/31)(?!-31)(?!\.31)|(?:0?2(?=.?(?:(?:29.(?!000[04]|(?:(?:1[^0-6]|[2468][^048]|[3579][^26])00))(?:(?:(?:\d\d)(?:[02468][048]|[13579][26])(?!\x20BC))|(?:00(?:42|3[0369]|2[147]|1[258]|09)\x20BC))))))|(?:0?2(?=.(?:(?:\d\D)|(?:[01]\d)|(?:2[0-8])))))([-.\/])(0?[1-9]|[12]\d|3[01])\2(?!0000)((?=(?:00(?:4[0-5]|[0-3]?\d)\x20BC)|(?:\d{4}(?!\x20BC)))\d{4}(?:\x20BC)?)(?:$|(?=\x20\d)\x20))?((?:(?:0?[1-9]|1[012])(?::[0-5]\d){0,2}(?:\x20[aApP][mM]))|(?:[01]\d|2[0-3])(?::[0-5]\d){1,2})?$/) != null;	
}

function validateDateTime(datetimeString) {
	/* Validates UK format dates and/or times (eg. dd/mm/yy hh:mm:ss)*/
  return datetimeString.match(/^(?=\d)(?:(?!(?:(?:0?[5-9]|1[0-4])(?:\.|-|\/)10(?:\.|-|\/)(?:1582))|(?:(?:0?[3-9]|1[0-3])(?:\.|-|\/)0?9(?:\.|-|\/)(?:1752)))(31(?!(?:\.|-|\/)(?:0?[2469]|11))|30(?!(?:\.|-|\/)0?2)|(?:29(?:(?!(?:\.|-|\/)0?2(?:\.|-|\/))|(?=\D0?2\D(?:(?!000[04]|(?:(?:1[^0-6]|[2468][^048]|[3579][^26])00))(?:(?:(?:\d\d)(?:[02468][048]|[13579][26])(?!\x20BC))|(?:00(?:42|3[0369]|2[147]|1[258]|09)\x20BC))))))|2[0-8]|1\d|0?[1-9])([-.\/])(1[012]|(?:0?[1-9]))\2((?=(?:00(?:4[0-5]|[0-3]?\d)\x20BC)|(?:\d{4}(?:$|(?=\x20\d)\x20)))\d{4}(?:\x20BC)?)(?:$|(?=\x20\d)\x20))?((?:(?:0?[1-9]|1[012])(?::[0-5]\d){0,2}(?:\x20[aApP][mM]))|(?:[01]\d|2[0-3])(?::[0-5]\d){1,2})?$/) != null;	
}

function validateData(strValidateStr,objValue) {
	/* Run the specified validation on the specified value */
	var epos = strValidateStr.search("="); 
	var command  = ""; 
	var cmdvalue = ""; 
	if(epos >= 0) { 
	 command  = strValidateStr.substring(0,epos); 
	 cmdvalue = strValidateStr.substr(epos+1); 
	} else { 
	 command = strValidateStr; 
	} 
	switch(command) 
	{ 
		case "req": 
		case "required": 
		{ 
			if(eval(trim(objValue.value).length) == 0) {
				objValue.value = '';
				return false; 
			}
			break;             
		}
		case "maxlen": 
		case "maxlength": 
		{ 
			 if(eval(objValue.value.length) > eval(cmdvalue)) { 
				 return false; 
			 }
			 break; 
		}
		case "minlen": 
		case "minlength": 
		{ 
			if(eval(objValue.value.length) < eval(cmdvalue)) { 
			 return false;                 
			}
			break; 
		}
		case "alnum": 
		case "alphanumeric": 
		{ 
			var charpos = objValue.value.search("[^A-Za-z0-9]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
			break; 
		}
		case "num": 
		case "numeric": 
		{ 
			var charpos = objValue.value.search("[^0-9]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
			break;               
		}
		case "maxval": 
		case "maxvalue": 
		{ 
			 if(trim(objValue.value).length > 0 && eval(objValue.value) > eval(cmdvalue)) { 
				 return false; 
			 }
			 break; 
		}
		case "minval": 
		case "minvalue": 
		{ 
			 if(trim(objValue.value).length > 0 && eval(objValue.value) < eval(cmdvalue)) { 
				 return false; 
			 }
			 break; 
		}
		case "dec":
		case "decimal":
		{ 
			return validateDecimal(objValue.value); 
			break; 
		}
		case "pdec":
		case "posdec":
		case "posdecimal":
		case "positivedecimal":
		{
			return validateDecimalNonNeg(objValue.value);
			break;
		}
		case "money":
		{ 
			return validateMoney(objValue.value); 
			break; 
		}
		case "alpha": 
		case "alphabetic": 
		{ 
			var charpos = objValue.value.search("[^A-Za-z]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
			break; 
		}
		case "alphauc":
		case "alphauppercase":
		case "alphabeticuc":
		case "alphabeticuppercase":
		{ 
			var charpos = objValue.value.search("[^A-Z]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
			break; 
		}
		case "alphalc":
		case "alphalowercase":
		case "alphabeticlc":
		case "alphabeticlowercase":
		{ 
			var charpos = objValue.value.search("[^a-z]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
			break; 
		}
		case "alnumhyphen":
		{
			var charpos = objValue.value.search("[^A-Za-z0-9-]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
		  break;
		}
		case "alnumhyphenspace":
		{
			var charpos = objValue.value.search("[^A-Za-z0-9- ]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
		  break;
		}
		case "alnumdash":
		{
			var charpos = objValue.value.search("[^A-Za-z0-9\-_]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
		  break;
		}
		case "alnumdashspace":
		{
			var charpos = objValue.value.search("[^A-Za-z0-9\-_ ]"); 
			if(trim(objValue.value.length) > 0 && charpos >= 0) { 
				return false; 
			}
		  break;
		}
		case "alnumspace":
		{
			var charpos = objValue.value.search("[^A-Za-z0-9 ]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
		  break;
		}
		case "username":
		{
			var charpos = objValue.value.search("[^A-Za-z0-9.-_]"); 
			if(trim(objValue.value).length > 0 && charpos >= 0) { 
				return false; 
			}
		  break;
		}
		case "email": 
		{ 
			return validateEmail(objValue.value); 
			break; 
		}
		case "tel":
		case "telephone":
		{ 
			return validateTelephone(objValue.value); 
			break; 
		}
		case "uktel":
		case "uktelephone":
		{ 
			return validateUKTelephone(objValue.value); 
			break; 
		}
		case "pc":
		case "postcode":
		{ 
			return validatePostcode(objValue.value); 
			break; 
		}
		case "dt":
		case "datetime":
		{ 
			return validateDateTime(objValue.value); 
			break; 
		}
		case "usdt":
		case "usdatetime":
		{ 
			return validateUSDateTime(objValue.value); 
			break; 
		}
		case "eq": 
		case "eqto": 
		case "equal": 
		case "equalto": 
		{ 
			if(eval(objValue.value) !=  eval(cmdvalue)) { 
				return false;                 
			}            
			break; 
		}
		case "lt": 
		case "lessthan": 
		{ 
			if(trim(objValue.value).length > 0 && eval(objValue.value) >=  eval(cmdvalue)) { 
				return false;                 
			}            
			break; 
		}
		case "gt": 
		case "greaterthan": 
		{ 
			if(trim(objValue.value).length > 0 && eval(objValue.value) <=  eval(cmdvalue)) 
			{ 
			 return false;                 
			}           
			break; 
		}
		case "regexp": 
		{ 
			if(trim(objValue.value).length > 0) {
				if(!objValue.value.match(cmdvalue)) { 
					return false;                   
				}
			}
			break; 
		}
		case "select": 
		{ 
			if(objValue.selectedIndex == 0) { 
				return false;                                   
			} 
			break; 
		}
	} 
	return true; 
}

function validateFileExtensions(inputItem, extList, errorString) {
	/* Checks a file upload input to make sure that only those file extensions in the comma-delimited
	   list (extList) are allowed eg. 'jpg,jpeg,gif' */
  if(typeof inputItem == 'undefined' || typeof errorString == 'undefined' || typeof extList == 'undefined') {
		alert('validateFileExtensions(inputItem, errorString, extList): Required parameter missing');
	  return false;
	}
	var itemObject = this[inputItem];
	if (trim(itemObject.value) == '') {
		return true;
	}
	var extArray = extList.split(',');
	var valid = false;
	for ( var i = 0; i < extArray.length; i++ ) {
		if (itemObject.value.indexOf('.' + extArray[i]) != -1) {
			valid = true;
		}
	}
	if (!valid) {
		if(addError(itemObject, errorString)){
		  showError(itemObject);
		}
		return false;
	} else {
		return true;
	}
}

function validateMultiSelect(inputItem, errorString, minS, maxS) {
	/* Checks a multi-select input to make sure that a minimum of minS and optionally a maximum of maxS selections
	   have been made */
  if(typeof inputItem == 'undefined' || typeof errorString == 'undefined' || typeof minS == 'undefined') {
		alert('validateMultiSelect(inputItem, errorString, minS, maxS): Required parameter missing');
	  return false;
	}
	var itemObject = this[inputItem];
	if(maxS == 999 || maxS == "*" || typeof maxS == 'undefined' || maxS > itemObject.length ) {
		maxS = itemObject.length;
	}
	var count = 0;
	for ( var opt, i = 0; ( opt = itemObject.options[i] ); i++ ) {
		if ( opt.selected ) count ++;
	}
	if ( count < minS || count > maxS ){
		if(addError(itemObject, errorString)){
		  showError(itemObject);
		}
		return false;
	}
	return true;
}

function validateCheckboxes(inputList, errorString, minC, maxC) {
	/* Examines a list of checkbox inputs to make sure that a minimum of minC and optionally a maximum of maxC boxes
	   have been checked */
  if(typeof inputList == 'undefined' || typeof errorString == 'undefined' || typeof minC == 'undefined') {
		alert('validateCheckboxes(inputList, errorString, minC, maxC): Required parameter missing');
	  return false;
	}
	var inputArray = inputList.split(',');
	if(maxC == 999 || maxC == "*" || typeof maxC == 'undefined' || maxC > inputArray.length ) {
		maxC = inputArray.length;
	}
	var count = 0;
	for(var i=0; i < inputArray.length; i++){
	  var itemObject = this[inputArray[i]];
		if(itemObject.checked) count++;
	}
	if(count < minC || count > maxC){
	  var itemObject = this[inputArray[0]];
		if(addError(itemObject, errorString)){
		  showError(itemObject);
			for(var i=0; i < inputArray.length; i++){
	      var itemObject = this[inputArray[i]];
				showErrorRow(itemObject);
			}
		}
		return false;
	}
	return true;
}

function validateRadios(inputItem, errorString, itemIndex) {
	/* Checks a named radio button group to see if a selection has been made. You may also optionally
	   specify an index number of a specific radio button that must be selected. */
  if(typeof inputItem == 'undefined' || typeof errorString == 'undefined') {
		alert('validateRadios(inputItem, errorString, itemIndex): Required parameter missing');
	  return false;
	}
	var itemObject = this[inputItem];
	var count = 0;
	for(var i=0; i < itemObject.length; i++){
		if(itemObject[i].checked){
		  if(typeof itemIndex != 'undefined'){
				if(i == itemIndex){
					count++;
				}
			} else {
			  count++;
			}
		}
	}
	if(count == 0){
		if(addError(itemObject[0], errorString)){
		  showError(itemObject[0]);
		}
		return false;
	}
	return true;
}

function compareFields(inputItem, inputCompare, comparison, errorString) {
	/* Compares the contents of two input fields based on the specified comparison (eg. lt, gt, eq) */
  if(typeof inputItem == 'undefined' || typeof inputCompare == 'undefined' || typeof errorString == 'undefined' || typeof comparison == 'undefined') {
		alert('compareFields(inputItem, inputCompare, comparison, errorString): Required parameter missing');
	  return false;
	}
	var itemObject = this[inputItem];
	var itemValue = itemObject.value;
	var compareObject = this[inputCompare];
	var compareValue = compareObject.value;
	var passedCheck = false;
	switch(comparison) {
		case "eq":
		case "equal":
		case "equalto":
		case "=":
		case "==":
		{
			if(itemValue == compareValue) {passedCheck = true;}
			break;
		}
		case "lt":
		case "lessthan":
		case "<":
		{
			if(itemValue < compareValue) {passedCheck = true;}
			break;
		}
		case "gt":
		case "greaterthan":
		case ">":
		{
			if(itemValue > compareValue) {passedCheck = true;}
			break;
		}
		case "lte":
		case "<=":
		{
			if(itemValue <= compareValue) {passedCheck = true;}
			break;
		}
		case "gte":
		case ">=":
		{
			if(itemValue <= compareValue) {passedCheck = true;}
			break;
		}
		default:
		{
			alert('compareFields(): Unknown comparison string.');
			return false;
		}
	}
	if(!passedCheck){
		if(addError(itemObject, errorString)){
			showError(itemObject);
			showErrorRow(compareObject);
		}
		return false;
	}
	return true;
}

function validateDateSelect(daySelectItem, monthSelectItem, yearSelectItem, errorString) {
	/* Checks the contents of a set of date select fields (eg. Day Month Year) for a valid date. */
	/* If the date is optional (ie. if there are more than 12 options for month), and no values  */
	/* have been selected, the check is bypassed. */
	if(typeof daySelectItem == 'undefined' || typeof monthSelectItem == 'undefined' || typeof yearSelectItem == 'undefined' || typeof errorString == 'undefined') {
		alert('validDateSelect(daySelectItem, monthSelectItem, yearSelectItem, errorString): Required parameter missing');
	  return false;
	}
	daySelectObject = this[daySelectItem];
	dayValue = daySelectObject[daySelectObject.selectedIndex].value;
	monthSelectObject = this[monthSelectItem];
	monthValue = monthSelectObject[monthSelectObject.selectedIndex].value;
	yearSelectObject = this[yearSelectItem];
	yearValue = yearSelectObject[yearSelectObject.selectedIndex].value;
	if(monthSelectObject.length > 12 && daySelectObject.selectedIndex == 0 && monthSelectObject.selectedIndex == 0 && yearSelectObject.selectedIndex == 0){
		return true;
	}
	if(!validateDateTime(dayValue + '/' + monthValue + '/' + yearValue)){
		if(addError(daySelectObject, errorString)){
			showError(daySelectObject);
		}
		return false;
	}
	return true;
}

function compareDateSelect(daySelectItem, monthSelectItem, yearSelectItem, comparison, errorString, daySelectCompare, monthSelectCompare, yearSelectCompare){
	/* Compares the contents of two sets of date select fields (eg. Day Month Year) based on the
	   specified comparison (eg. lt, gt, eq). If the second set of date select fields is not specified,
		 the date is compared to the current date instead. */
	if(typeof daySelectItem == 'undefined' || typeof monthSelectItem == 'undefined' || typeof yearSelectItem == 'undefined' ||
		 typeof errorString == 'undefined' || typeof comparison == 'undefined') {
		alert('compareDateSelects(daySelectItem, monthSelectItem, yearSelectItem, comparison, errorString, daySelectCompare, monthSelectCompare, yearSelectCompare): Required parameter missing');
	  return false;
	}
	daySelectObject = this[daySelectItem];
	monthSelectObject = this[monthSelectItem];
	yearSelectObject = this[yearSelectItem];
	dateItem = new Date(yearSelectObject[yearSelectObject.selectedIndex].value, monthSelectObject[monthSelectObject.selectedIndex].value - 1, daySelectObject[daySelectObject.selectedIndex].value);
	if(typeof daySelectCompare != 'undefined' && typeof monthSelectCompare != 'undefined' && typeof yearSelectCompare != 'undefined'){
	  dayCompareObject = this[daySelectCompare];
	  monthCompareObject = this[monthSelectCompare];
	  yearCompareObject = this[yearSelectCompare];
	  dateCompare = new Date(yearCompareObject[yearCompareObject.selectedIndex].value, monthCompareObject[monthCompareObject.selectedIndex].value - 1, dayCompareObject[dayCompareObject.selectedIndex].value);
	} else {
		dateCompare = new Date();
	}
  var passedCheck = false;
	switch(comparison) {
		case "eq":
		case "equal":
		case "equalto":
		case "=":
		case "==":
		{
			if(Date.parse(dateItem) == Date.parse(dateCompare)) {passedCheck = true;}
			break;
		}
		case "lt":
		case "lessthan":
		case "<":
		{
			if(Date.parse(dateItem) < Date.parse(dateCompare)) {passedCheck = true;}
			break;
		}
		case "gt":
		case "greaterthan":
		case ">":
		{
			if(Date.parse(dateItem) > Date.parse(dateCompare)) {passedCheck = true;}
			break;
		}
		case "lte":
		case "<=":
		{
			if(Date.parse(dateItem) <= Date.parse(dateCompare)) {passedCheck = true;}
			break;
		}
		case "gte":
		case ">=":
		{
			if(Date.parse(dateItem) <= Date.parse(dateCompare)) {passedCheck = true;}
			break;
		}
		default:
		{
			alert('compareDateSelects(): Unknown comparison string.');
			return false;
		}
	}
	if(!passedCheck){
		if(addError(daySelectObject, errorString)){
			showError(daySelectObject);
			if(typeof dayCompareObject != 'undefined'){
			  showErrorRow(dayCompareObject);
			}
		}
		return false;
	}
	return true;
}