// form.js (Website Framework) || Version: 1.20 || Last Updated: 2009-12-08 10:00 || Updated by: Hidde-Finne Peters || Created: 2008-12-08 by Hidde-Finne Peters
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------
//	1.04:	Added "required" condition (only ready for use input "radio" so far)
//	1.04:	Added comments
//	1.04:	Changed condition "emailFormat" to declare empty values as valid (in case email is not required)
//	1.05:	Added functionality that enables to add fields trough js (see below), and no longer requires adding event listeners in every field
//	1.06:	Added functionality that automatically adds fields to "check list" by reading out "conditions"
//	1.07:	Added auto insert tooltip-image script, so tooltip images do not have to be placed in contact view
//	1.08:	Changed insert tooltip-image script so image url can be set in contact view and thus easily changed per website
//	1.09:	Changed className management. Automatically changes last characters of className into _valid or _invalid. Now supports different classnames for for fields, no longer support _default. 
//	1.10:	Added className management for "support styling", for example a div that needs to change it's display based on valid or invalid value of a specific field
//	1.11:	Added initializeForm() function and added functionality for submitImage
//	1.12:	Adjusted script to work with imageButton.js (changed submitImage functionality)
//	1.13:	Added automatic "onload" handling (requires onLoad.js)
//	1.14:	Made changes to ensure script works without tooltips (might not function correctly anymore with presence of tooltips)
//	1.15:	Changed script to function correctly when added in head (main template)
//	1.16:	Added support within "required" "condition handling" to also function for select fields
//	1.17:	Changed the addEvent script in "addField()" so it does not replace but instead adds event listeners and handlers.
//	1.18:	Added support within "required" "condition handling" to also function for checkbox (might only work for single checkbox, not for groups).
//	1.19:	Removed mouse event functions related to imageButton (is being handled by imageButton.js anyway)
//	1.20:	Moved "required" handling forward within conditionValid so it does not need to get the field.
//	1.21:	Changed addField so it's also able to add event listeners to radio inputs
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------

var conditions = null;							//	1.15
var tooltipImageUrl = null;						//	1.14
var ToolTip = null;								//	1.14

//	----

//-------------------------------------------------------------------------------
//--- hasRequiredValue ----------------------------------------------------------	1.18
//-------------------------------------------------------------------------------
//	A value is required:
//	- radioButton: At least one option must be selected.
//	- select: The first option is selected by default: any option except for the first option must be selected.
//	- checkbox: Value of checkbox must be true (box must be checked).

function hasRequiredValue (condition) {
	if (condition[2]) {
		var form = document.getElementById(condition[2]);
	} else {
		var form = document.getElementById('form');
	}
	if (form) {
		var formField = eval('form.'+ condition[0]);
		if (formField) {
			switch (formField.type) {
				case 'select-one':
					//	Select
					//alert(formField.selectedIndex);
					if (formField.selectedIndex != 0) {
						//alert(formField.selectedIndex);
						return true;
					}
					break;
				case 'checkbox':
					//	checkbox
					if (formField.checked) {
						return true;
					}
					break;
				default:
					//	radio
					for (i = 0; i < formField.length; i++) {
						if (formField[i].checked) {
							return true;
						}
					}
					break;
			}
		}
	}
	return false;
}

function hasMinChars (value, chars) {
	if (value.length < chars) {
		return false;
	} else {
		return true;
	}
}

function numbersOnly (value) {
	if (!value.match(/^\d+$/))	{
		return false;
	} else {
		return true;
	}
}

function lettersOnly (value) {
	if (value.length > 0) {
		for (var i = 0; i < value.length; i++) {
			if (value[i]) {
				if (value[i].match(/^\d+$/)) {
					return false;	
				}
			}
		}
		return true;
	}
	return false;
}

function isEmailFormat (str) {
	//	Empty string is valid (ensures this condition can be applied to fields that do not require values)
	if (str.length < 1) {
		return true;	
	}
	//	If value has length the format needs to be valid
	if (str.length > 6) {
		//	Length is sufficient
		var atIndex = str.indexOf("@");
		if (atIndex > 0) {
			//	@ is valid
			var dotIndex = str.indexOf(".", atIndex);
			if (dotIndex - atIndex > 2) {
				//	Enough characters between @ and .
				if ((str.length - 2) > dotIndex) {
					//	Enough characters after .
					//	If it gets here the string must be good
					return true;
				}
			}
		}
	}
	return false;			
}

function conditionValid (condition) {
	//	1.20
	var conditionType = condition[1];
	if (conditionType == 'required') {
		//	Specially designed for "radio" & "select".					//	1.16 added support for select
		return hasRequiredValue(condition);
	}
	//	----
	var formField = document.getElementById(condition[0]);
	if (!formField) {
		alert('formField "'+ condition[0] +'" not found!');
	}
	var value = formField.value;
	if (value != null) {
		var conditionParam = condition[2];
		switch (conditionType) {
			case 'minChars':
				return hasMinChars(value, conditionParam);
			case 'emailFormat':
				return isEmailFormat(value);
			case 'numbersOnly':
				return numbersOnly(value);
			case 'lettersOnly':
				return lettersOnly(value);
			case 'isChecked':
				//	Specially designed for "checkfield".
				return formField.checked;
		}
	}
	//	Condition processing failed, return valid;
	return true;
}

//
//	1.09:	Changed className management. Automatically changes last characters of className into _valid or _invalid. Now supports different classnames for for fields, no longer support _default. 
//	1.10	Added className management for "support styling", for example a div that needs to change it's display based on valid or invalid value of a specific field

function updateDisplayValid (condition, valid) {
	//	----------------------------------------------------------------
	//	General preperation
	//	----------------------------------------------------------------
	var inputId = condition[0];
	var formField = document.getElementById(inputId);
	//	----------------------------------------------------------------
	//	Valid
	//	----------------------------------------------------------------
	if (valid) {
		//	----------------------------------------------------------------
		//	ClassName
		//	----------------------------------------------------------------
		if (formField) {
			var oldClassName = formField.className;
			if (oldClassName.substr(oldClassName.length - 8, 8) == '_invalid') {
				formField.className = oldClassName.substr(0, oldClassName.length - 8) +'_valid';
			}
		}
		//	----------------------------------------------------------------
		//	Support ClassName
		//	----------------------------------------------------------------
		var supportElement = document.getElementById(inputId +'_support');
		if (supportElement) {
			var oldSupportClassName = supportElement.className;
			if (oldSupportClassName.substr(oldSupportClassName.length - 8, 8) == '_invalid') {
				supportElement.className = oldSupportClassName.substr(0, oldSupportClassName.length - 8) +'_valid';
			}
		}
		//	----------------------------------------------------------------
		//	Tooltip
		//	----------------------------------------------------------------
		var tooltipBox = document.getElementById(inputId +'_tooltipBox');
		if (tooltipBox) {
			tooltipBox.style.display = 'none';
		}
		//	----------------------------------------------------------------
	//	----------------------------------------------------------------
	//	Invalid
	//	----------------------------------------------------------------
	} else {
		//	----------------------------------------------------------------
		//	ClassName
		//	----------------------------------------------------------------
		var oldClassName = formField.className;
		if (oldClassName.substr(oldClassName.length - 6, 6) == '_valid') {
			formField.className = oldClassName.substr(0, oldClassName.length - 6) +'_invalid';
		}
		//	----------------------------------------------------------------
		//	Support ClassName
		//	----------------------------------------------------------------
		var supportElement = document.getElementById(inputId +'_support');
		if (supportElement) {
			var oldSupportClassName = supportElement.className;
			if (oldSupportClassName.substr(oldSupportClassName.length - 6, 6) == '_valid') {
				supportElement.className = oldSupportClassName.substr(0, oldSupportClassName.length - 6) +'_invalid';
			}
		}
		//	----------------------------------------------------------------
		//	Tooltip
		//	----------------------------------------------------------------
		var tooltip = document.getElementById(inputId +'_tooltip');
		var feedback = condition[3];
		if (tooltip) {
			tooltip.setAttribute('tip', feedback);
		}
		var tooltipBox = document.getElementById(inputId +'_tooltipBox');
		if (tooltipBox) {
			tooltipBox.style.display = 'block';
		}
		//	----------------------------------------------------------------
	}
}

function hasInvalidField (invalidFields, condition) {
	for (var i = 0; i < invalidFields.length; i++) {
		if (invalidFields[i] == condition[0]) {
			return true;	
		}
	}
	return false
}

//	Accessed directly on focusIn or focusOut to check a specific field. Will also check entire form to update the "submit button".
function checkField (conditions, fieldName, handleInvalid) {
	//	Only proceed if conditions and fieldName are set
	if (conditions && fieldName) {
		//	Walk trough conditions
		for (var i = 0; i < conditions.length; i++) {
			//	Find every condition relating to field
			if (conditions[i][0] == fieldName) {
				//	Found a relating condition
				var condition = conditions[i];
				//	Check the condition
				if (!conditionValid(condition)) {
					//	Field value does not meet condition.
					//	If handleInvalid is set as true, update the view (show tooltip etc.). If handleInvalid is false or not set, the false condition result is not automaticcaly shown.
					if (handleInvalid) {
						updateDisplayValid(condition, false);
					}
					//	Check all conditions on all fields to update general status (submit button enabled / disabled)
					checkForm(conditions);
					//	Field value is invalid, no need to check more conditions, return false.
					return false;
				}
			}
		}
		//	Check if at least one condition was processed (if none, no need to update anything)
		if (condition) {
			//	At least one condition has been processed and not given a false result (if multiple conditions are set on one field "condition" is the last processed condition.
			//	Update the view (hide tooltip etc.)
			updateDisplayValid(condition, true);
			//	Check all conditions on all fields to update general status (submit button enabled / disabled)
			checkForm(conditions);
			//	Field is valid, nothing left to do, return true;
			return true;
		}
	}
}

function checkForm (conditions) {
	var invalidFields = new Array();
	for (var i = 0; i < conditions.length; i++) {
		var condition = conditions[i];
		if (!hasInvalidField(invalidFields, condition)) {
			var valid = conditionValid(condition);
			if (!valid) {
				//	Condition is not valid
				invalidFields.push(conditions[i][0]);
			}
		}
	}
	//	spam check
	var spam_check_field = document.getElementById('spam_check_passed');
	if (spam_check_field) {
		spam_check_field.value = 'true';	
	}
	//	submitButton
	var submitButton = document.getElementById('submitButton');
	var submitImage = document.getElementById('submitImage_button');
	if (invalidFields.length == 0) {
		//	Enable form button
		//if (submitButton) {
		//	submitButton.disabled = false;
		//}
		//if (submitImage) {
			//submitImage.src = 'site_images/send_default.gif';
			//submitImage.src = submitImage.src.replace(new RegExp('_disabled\\b'), '_default');
			//submitImage.style['cursor'] = 'pointer';
		//}
		return true;
	} else {
		//	Disable form button
		//if (submitButton) {
			//submitButton.disabled = true;
		//}
		//if (submitImage) {
			//submitImage.src = submitImage.src.replace(new RegExp('_default\\b'), '_disabled');
			//submitImage.src = submitImage.src.replace(new RegExp('_over\\b'), '_disabled');
			//submitImage.src = 'site_images/send_disabled.gif';
			//submitImage.style['cursor'] = 'auto';
		//}
	}
	return false;
}

//----------------------------------------------------------------------
//--- 1.05 -------------------------------------------------------------
//----------------------------------------------------------------------

//	Checks field and changes view accordingly to conditions result
function handleChange (evt) {
	if (evt) {
		//	Firefox a.o.
		var fieldName = evt.target.name;
	} else {
		//	IE
		var fieldName = window.event.srcElement.name;
	}
	checkField(conditions, fieldName, true);
}

//	Does check field and changes view if it changes from invalid to valid but does not change view to invalid.
function handleKeyUp (evt) {
	if (evt) {
		//	Firefox a.o.
		var fieldName = evt.target.name;
	} else {
		//	IE
		var fieldName = window.event.srcElement.name;
	}
	checkField(conditions, fieldName, false);
}

//	-------------------------------------------------------------------------------
//	--- addHandlerFunction --------------------------------------------------------		1.17
//	-------------------------------------------------------------------------------

function addHandlerFunction (oldFunc, newFunc) {
	if (typeof oldFunc != 'function') {
		return newFunc;
	} else {
		return function (evt) {
			if (oldFunc) {
				oldFunc(evt);
			}
			newFunc(evt);
		}
	}
}

//	-------------------------------------------------------------------------------
//	-------------------------------------------------------- addHandlerFunction ---
//	-------------------------------------------------------------------------------

function addField (fieldName) {
	var field = document.getElementById(fieldName);
	if (field) {
		if (field.type == 'select-one') {										//	1.16
			field.onchange = addHandlerFunction(field.onchange, handleChange);	//	1.16	//	1.17
		} else {																//	1.16
			field.onblur = addHandlerFunction(field.onblur, handleChange);		//	1.17
			field.onkeyup = addHandlerFunction(field.onkeyup, handleKeyUp);		//	1.17
		}																		//	1.16
	} else {	//	1.21 Possibly a radio button thingy
		var form = document.getElementById('form');
		if (form) {
			var formField = eval('form.'+ fieldName);
			if (formField) {
				for (i = 0; i < formField.length; i++) {
					formField[i].onchange = addHandlerFunction(formField[i].onchange, handleChange);
				}
			}
		}
	}
		
}

//----------------------------------------------------------------------
//------------------------------------------------------------- 1.05 ---
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//--- 1.06 -------------------------------------------------------------
//----------------------------------------------------------------------
//	1.07:	Added auto insert image script, so tooltip images do not have to be placed in contact view
//	1.08:	Changed insert tooltip-image script so image url can be set in contact view and thus easily changed per website

function containsValue (array, value) {
	for (var i = 0; i < array.length; i++) {
		if (array[i] == value) {
			return true;
		}
	}
	return false;
}


function addFields () {
	var fieldNames = new Array();
	for (var i = 0; i < conditions.length; i++) {
		var fieldName = conditions[i][0];
		if (!containsValue(fieldNames, fieldName)) {
			fieldNames.push(fieldName);
			//	Execute init
			addField(fieldName);
			//
			if (tooltipImageUrl) {
				var tooltipContainer = document.getElementById(fieldName +'_tooltipBox');
				if (tooltipContainer) {
					tooltipContainer.innerHTML = '<img id="'+ fieldName +'_tooltip" src="'+ tooltipImageUrl +'" title="'+ conditions[i][3] +'" />';
				}
			}
			//
		}
	}
}

//----------------------------------------------------------------------
//------------------------------------------------------------- 1.06 ---
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//--- 1.11 -------------------------------------------------------------
//----------------------------------------------------------------------
//	1.11:	Added functionality for submitImage.

function allValid () {
	for (var i = 0; i < conditions.length; i++) {
		if (!conditionValid(conditions[i])) {
			return false;
		}
	}
	return true;
}

function handleSubmitImageClick (evt) {
	if (allValid()) {
		var form = document.getElementById('form');
		form.submit();
	}
}

function prepareSubmitImage () {
	var submitImage = document.getElementById('submitImage_button');
	if (submitImage) {
		submitImage.onclick = handleSubmitImageClick;
		checkForm(conditions);
	}
}

//	1.11:	Added initializeForm() function

function initializeForm (evt) {
	if (conditions) {							//	1.15:	Only initialize if conditions is array (are set)
		addFields();
		prepareSubmitImage();
		if (ToolTip) {
			ToolTip.init();
		}
	}
}

//----------------------------------------------------------------------
//------------------------------------------------------------- 1.11 ---
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//--- 1.13 -------------------------------------------------------------
//----------------------------------------------------------------------
//	initialize the script after load

addLoadEvent(initializeForm);

//----------------------------------------------------------------------
//------------------------------------------------------------- 1.15 ---
//----------------------------------------------------------------------
