// Form Validation Script
// Authors: Stafford Vaughan, Peter Watkins, Andrew Henry
// This file and all contents copyright the authors. Not to be used without express written permission.
//
// This is a form validation script used to generate an alert window box on form submission. This file
// may be included at any point on the page (including the header). Note that no form submission events are
// necessary for this script to work. The functionality includes disabling the form submission button to
// prevent form submissions more than once.
//
// Usage:
// In order to use this script, the initValidation method must be called in the onload event of the page.
// Array variables should be declared as hidden fields at the beginning of any form that needs to be validated.
// The arrRequiredFields hidden field should contain a string list of the field names for any text or select form elements
// that are mandatory on this page.
// The arrRequiredLists hidden field should contain a string list of the names of any checkbox lists which are mandatory.
// The arrValidIntegers hidden field should contain a string list of the names of any text fields which must contain a
// valid integer.
//
// Example:
// <input name="arrRequiredFields" type="hidden" value="strName,strPhone,strEmail" />
// <input name="arrRequiredLists" type="hidden" value="lstOptions" />
// <input name="arrValidIntegers" type="hidden" value="intPage,intCost" />
//
// Note:
// Lists of field named must contain no spaces, and be separated by a comma.
// Every checkbox in a checkbox list should have an identical "name" attribute, and a unique "id".
// Fields should include a brief field description in the "title" attribute, which is used to display a
// meaningful message in the alert window.

function initValidation()
{
	if (document.forms[0])
	{
		for (var i = 0; i < document.forms.length; i++)
		{
			var currentform = document.forms[i];
			currentform.old_onsubmit = currentform.onsubmit;

			currentform.onsubmit = function()
			{
				if (this.old_onsubmit)
				{
					var result = this.old_onsubmit();
					if (result != undefined && !result)
					{
						enableSubmit(this);
						return false;
					}
				}

				return validateFields(this);
			}

			for (var j = 0; j < currentform.elements.length; j++)
			{
				var button = currentform.elements[j];

				if (button.type == 'submit')
				{
					button.old_onclick = button.onclick;

					button.onclick = function()
					{
						if (this.old_onclick)
						{
							var result = this.old_onclick();
							if (result != undefined && !result)
							{
								enableSubmit(currentform); // pass the form as a parameter, not "this"
								return false;
							}
						}

						// "rel" must be checked here to ensure the scope is within the "onclick" method of the button
						var rel = this.form.getAttribute('rel'); // getAttribute('rel') is Firefox compatible

						if (!rel || rel != 'external')
							disableSubmit(this); // "this" refers to the button object
					}
				}
			}
		}
	}
}

function disableSubmit(button)
{
	button.style.visibility = 'hidden';
}

function enableSubmit(form)
{
	for (var i = 0; i < form.elements.length; i++)
	{
		if (form.elements[i].type == 'submit')
			form.elements[i].style.visibility = 'visible';
	}
}

function validateFields(form)
{
	var strMissingFields = '';
	var valid = true;
	var elements = form.elements;

	var arrRequiredFields = elements['arrRequiredFields'];
	if (typeof arrRequiredFields != 'undefined' && arrRequiredFields.value.length > 0)
	{
		arrRequiredFields = (arrRequiredFields.value).split(',');
		for (var i = 0; i < arrRequiredFields.length; i++)
		{
			var element = elements[arrRequiredFields[i]];

			// This allows for the situation where the form has more than one element with the same name.
			// This causes 'element' to return an array. The code will now loop through this array and check each of them individually.
			if (typeof element.tagName == 'undefined') // If the element object has no tagName defined it is an array of inputs, rather than a single input (like a Select, which can also be an array, but has this property defined.)
			{
				for (var j = 0; j < element.length; j++)
				{
					if (element[j].value == '')
					{
						if (valid) // this will ensure that only the first missing field receives focus
							element[j].focus();
						valid = false;

						strMissingFields += '- ' + (element.title ? element.title : element.name) + '\n';

						break; // break here because we only want to indicate the first field of this name is missing
					}
					
				}
			}
			else
			{
				if (element.value == '')
				{
					if (valid) // this will ensure that only the first missing field receives focus
						element.focus();
					valid = false;

					strMissingFields += '- ' + (element.title ? element.title : element.name) + '\n';
				}
			}

		}
	}

	var arrRequiredLists = elements['arrRequiredLists'];
	if (typeof arrRequiredLists != 'undefined' && arrRequiredLists.value.length > 0)
	{
		arrRequiredLists = (arrRequiredLists.value).split(',');
		for (var i = 0; i < arrRequiredLists.length; i++)
		{
			var blnChecked = false;
			var elements = elements[arrRequiredLists[i]];
			if (elements.length)
			{
				for (var j = 0; j < elements.length; j++)
				{
					if (elements[j].checked)
						blnChecked = true;
				}
				element = elements[0];
			}
			else
			{
				if (elements.checked)
					blnChecked = true;

				element = elements;
			}

			if (!blnChecked)
			{
				// the focus is not set because this is a checkbox
				valid = false;
				strMissingFields += '- ' + (element.title ? element.title : element.name) + '\n';
			}
		}
	}

	var arrValidIntegers = elements['arrValidIntegers'];
	if (typeof arrValidIntegers != 'undefined' && arrValidIntegers.value.length > 0)
	{
		arrValidIntegers = (arrValidIntegers.value).split(',');
		for (var i = 0; i < arrValidIntegers.length; i++)
		{
			var element = elements[arrValidIntegers[i]];

			// This allows for the situation where the form has more than one element with the same name.
			// This causes 'element' to return an array. The code will now loop through this array and check each of them individually.
			if (element.length)
			{
				for (var j = 0; j < element.length; j++)
				{
					var strInputString = element[j].value;
					var strIntegerString = parseInt(element[j].value).toString();
					if (strInputString != '' && (strInputString.length != strIntegerString.length || strIntegerString == 'NaN'))
					{
						if (valid && !element[j].disabled) // this will ensure that only the first missing field receives focus
							element[j].focus();
						valid = false;

						strMissingFields += '- ' + (element[j].title ? element[j].title : element[j].name) + '\n';

						break; // break here because we only want to indicate the first field of this name is missing
					}
				}
			}
			else
			{
				var strInputString = element.value;
				var strIntegerString = parseInt(element.value).toString();

				if (strInputString != '' && (strInputString.length != strIntegerString.length || strIntegerString == 'NaN'))
				{
					if (valid && !element.disabled) // this will ensure that only the first missing field receives focus
						element.focus();
					valid = false;

					strMissingFields += '- ' + (element.title ? element.title : element.name) + '\n';
				}
			}
			
		}
	}

	if (!valid)
	{
		if (strMissingFields == '')
			window.alert('Some fields are missing or contain invalid data, please enter correct values in all fields to continue.');
		else
			window.alert('The following fields are missing or contain invalid data:\n\n' + strMissingFields + '\nPlease enter correct values in all fields to continue.');

		enableSubmit(form);
	}

	return valid;
}

// used to reduce the size of a textarea, since HTML doesn't support this

// Example:
// <textarea name="description" onkeyup="limitTextArea(this,1500)"></textarea>

function limitTextArea(textarea, intMaxlength)
{
	if (textarea.value.length > intMaxlength)
	{
		textarea.value = textarea.value.substring(0, intMaxlength);
		alert('This text area has a limit of ' + intMaxlength + ' characters,\nsome text has been truncated.');
	}
}
