/*
How to use this formchecker:

1. Include this file into your form-page.
	eg.: <script language="javascript" type="text/javascript" src="/Includes/FormCheck.js"></script>

2. Add Attributes to the FORM-Element:
	- ONSUBMIT="return validateForm(this);" (required)
		The function validateForm() will be called like this 
		and it will return True when the form is validated oke
		and it will return False when the form contains an error
	- ERRORTYPE="<errortype>" (required)
		One of three values can be submitted here:
			- "alert"
				Gives a javascript-alert with all the fields that are faulty
			- "div"
				Displays a Div-Element with all the fields that are faulty.
				The name of the Div-Element to display the error in is given in 
				the ERRORDIV-Attribute in the FORM-Element.
			- "inputboxes"
				Sets the ClassName of the faulty Input-Element to the given ErrorClassName.
				The ErrorClassName is given for every Input-Element that needs to be checked.
	- ERRORDIV="<name of the div-tag>" (required when ERRORTYPE="div")
		The name of the Div-Element to display the faulty fields in.
		This option is only required when ERRORTYPE="div".

3. Add Attributes to the INPUT-Elements that need to be checked:
	- REQUIRED
		Values: "true", "optional"
	- REQUIRED_TYPE
		Values: "text", "dutchzip", "phonenumber", "email", "dd/mm/yyyy"
		Tells the FormChecker what to check for.
	- ERRORMSG
		Holds the errormessage that will be shown.
		eg.: ERRORMSG="Lastname is not valid!"
	- ERRORCLASS
		Holds the ErrorClassName to set the classname of the faulty INPUT-Element to
		when this INPUT-Element is faulty
*/

Array.prototype.clear=function()
{
    this.length = 0;
};

Array.prototype.contains = function (element) 
{
	for (var i = 0; i < this.length; i++) 
    {
		if (this[i] == element) 
        {
			return true;
		}
	}
	return false;
};


var strFormErrorMessage = "";
var checkedCheckboxes = new Array();
var firstObj = null;

function validateForm(Form)
{
	var strRequired = "";
	var strRequiredType = "";
	var blnNeedsChecking;
	
	firstObj = null;
	// Clear array
	checkedCheckboxes.clear();
	
	strFormErrorMessage = "";
	
	//check every element on the form
	for (var i=0; i<Form.length; i++)
	{
		if (Form[i].getAttribute("REQUIRED") != null)
		{
			strRequired = Form[i].getAttribute("REQUIRED");
			strRequiredType = Form[i].getAttribute("REQUIRED_TYPE");
			strName = Form[i].name;
			blnNeedsChecking = false;
			if (strRequired != null)
			{
				if ((strRequired.toLowerCase() == "true") || (strRequired.toLowerCase() == "optional"))
				{
					blnNeedsChecking = true;
				}
			}
			if (checkedCheckboxes.contains(strName)==false)
			{
				if (Form[i].nodeName.toLowerCase()=='input')
				{
					checkedCheckboxes.push(strName);
				}
			}
			else
			{
				blnNeedsChecking = false;
			}
			//check wether an VALIDATED-Attribute exists
			if (blnNeedsChecking == true)
			{
				checkControl(Form, Form[i]);
			}
		}
	}

	// show the actual error messages
	valForm_ShowErrorMessage(Form);
	if (firstObj!=null)
	{
		try
		{
			firstObj.focus();
		}
		catch (e)
		{
			// error
			window.console("error");
		}
	}

	// first check if there are no more error messages, so the final submit is coming up
	if (strFormErrorMessage.length == 0)
	{
		// add a hidden input for all unchecked checkboxes
		valForm_FixCheckBoxes(Form);
	}
	
	return (strFormErrorMessage.length > 0 ? false : true);
}
	
function checkControl(form, obj)
{
	var strValue = "";
	var strErrorMsg = obj.getAttribute("ERRORMSG");
	var required = obj.getAttribute("REQUIRED");
	var type = obj.getAttribute("REQUIRED_TYPE");
	var strLastCheckedRadio = "";
	var re = "";

	if ((required.toLowerCase() == "true") || (required.toLowerCase() == "optional"))
	{
		//make sure a filled optional text-box is cleared
		if ((required.toLowerCase() == "optional") && (obj.value == ""))
		{
			valForm_SetOK(form, obj);
		}
		else
		{

			switch (type.toLowerCase())
			{
				case "text":
					if (obj.value == "")
					{
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
				case "dutchzip":
					valForm_formatDutchZip(obj);
					//read new value
					strValue = obj.value;
					re = /^[0-9]{4}\s{0,1}[a-zA-Z]{2}$/; 
					if (valForm_doRegularExpression(re,strValue)== false) 
					{
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
				case "phonenumber":
					//only NUMERIC KEYS, (, ) , * , +, -,# and spaces are allowed
					strValue = obj.value;
					re = /^[\d\(\)\-\+\*\# ]+$/;
					if (valForm_doRegularExpression(re,strValue)== false) 
					{
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
				case "numeric":
					strValue = obj.value;
					re = /^[0-9]+$/;
					if (valForm_doRegularExpression(re,strValue)== false) 
					{
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
				case "price":
					strValue = obj.value;
					re = /^(\d+)[\.\,]?(\d{1,2})?$/; 					
					if (valForm_doRegularExpression(re,strValue)== false) 
					{
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
				case "password":
					strValue = obj.value;
					re = /(?=^.{8,30}$)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_+}{"":;'?/>.<,]).*$/;
					if (valForm_doRegularExpression(re,strValue)== false) 
					{
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
				case "passwordsimple":
					strValue = obj.value;
					re = /(?=^.{6,30}$)(?=.*\d)(?=.*[a-z,A-Z]).*$/;
					if (valForm_doRegularExpression(re,strValue)== false) 
					{
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
				case "email":
					//check if the email address is valid
					strValue = obj.value;
					re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,6})+$/;
					if (valForm_doRegularExpression(re,strValue)== false) 
					{
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
				case "dd/mm/yyyy":
					//check if date is valid for the format: DD/MM/YYYY
					//If D or M is supplied, a preceding 0 will be automatically added.
					//YYYY should have four digits
					//allowed separation chars: '/','-','.',' '(space)
					//All separation chars will be replaced by a '/'
					valForm_formatDate(obj);
					if (CheckDate(obj.value,'dd/mm/yyyy')== false) {
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
					//arSupportedTypes[0] = "hh:mm"
					//arSupportedTypes[2] = "mm/dd/yyyy"
				case "select":
					if (obj.value == "")
					{
						valForm_SetError(form, obj);
					}
					else
					{
						valForm_SetOK(form, obj);
					}
					break;
				case "check":
					var checks = document.getElementsByName(obj.name);
					if (chkFrm_isOneCheckboxSelected(checks))
					{
						valForm_SetOK(form, obj);
					}
					else
					{
						valForm_SetError(form, obj);
					}
					break;
				case "radio":
						//Get radio collection, use getElementsByName or names with a | or & in them will cause an error
						var objRadio = document.getElementsByName(obj.name);
						if (obj.name != strLastCheckedRadio) 
						{
							//This radiobuttongroup is not checked yet
							strLastCheckedRadio = obj.name;
							if (!(chkFrm_isOneRadioButtonSelected(objRadio))) 
							{
								valForm_SetError(form, obj);
							}
							else
							{
								valForm_SetOK(form, obj);
							}
						}
					break;
				default:
					break;
			}
		}
	}
}

function valForm_FixCheckBoxes(Form)
{
	var newElement = null;
	
	//check every checkbox
	for (var i=0; i<Form.length; i++)
	{
		if (Form[i].type.toLowerCase() == "checkbox")
		{
			//when a checkbox is not checked...
			if (Form[i].checked == false)
			{
				//create a hidden input-box and put the alternative value in it...
				//because a non-checked checkbox is not submitted with the form...
				newElement = document.createElement("INPUT");
				newElement.type = "hidden";
				newElement.name = Form[i].name;
				newElement.value = Form[i].getAttribute("ALTERNATIVEVALUE");
				
				//add the hidden text-box in the DOM-hierarchy...
				if (Form[i].nextSibling)
				{
					if (Form[i].nextSibling.nodeName.toUpperCase() == "#TEXT")
					{
						Form[i].parentNode.appendChild(newElement);
					}
					else
					{
						Form[i].nextSibling.insertBefore(newElement);
					}
				}
				else
				{
					Form[i].parentNode.appendChild(newElement);
				}
			}
		}
	}
}

function ResetForm(Form)
{
	//check every element on the form
	for (var i=0; i<Form.length; i++)
	{
		if (Form[i].getAttribute("REQUIRED") != null)
		{
			valForm_SetOK(Form, Form[i]);
		}
	}
}

function valForm_SetOK(form, obj)
{
	if (obj.getAttribute("normalClass") != null)
	{
		obj.className = obj.getAttribute("normalClass");
		obj.removeAttribute("normalClass", false);
	}
}

function valForm_SetError(form, obj)
{
	var strErrorType = (form.getAttribute("ERRORTYPE")) ? form.getAttribute("ERRORTYPE") : "";
	//append to the error message, depending on the errortype
	switch (strErrorType.toLowerCase())
	{
		case "alertandinputboxes":
			strFormErrorMessage += obj.getAttribute("ERRORMSG") + "\n";
			if (obj.getAttribute("normalClass") == null)
			{
				obj.setAttribute("normalClass", obj.className, 0);
				obj.className = obj.getAttribute("ERRORCLASS");
			}
			if (firstObj==null) firstObj=obj;
			break;
		case "alert":
			strFormErrorMessage += obj.getAttribute("ERRORMSG") + "\n";
			if (firstObj==null) firstObj=obj;
			break;
		case "div":
			strFormErrorMessage += obj.getAttribute("ERRORMSG") + "<BR>";
			break;
		case "inputboxes":
			strFormErrorMessage = " ";
			//put the classname in a new attribute and put the classname to the errorclass
			if (obj.getAttribute("normalClass") == null)
			{
				obj.setAttribute("normalClass", obj.className, 0);
				obj.className = obj.getAttribute("ERRORCLASS");
			}
			break;
		case "":
			strFormErrorMessage = " ";
			break;
		default:
			break;
	}
}

function valForm_ShowErrorMessage(form)
{
	var strErrorMsgDivID = "";
	var strErrorType = (form.getAttribute("ERRORTYPE")) ? form.getAttribute("ERRORTYPE") : "";
	var strErrorMsgDivID = (form.getAttribute("ERRORDIV")) ? form.getAttribute("ERRORDIV") : "";

	var errorDiv = ((strErrorMsgDivID != "") ? document.getElementById(strErrorMsgDivID) : null);
	
	if (strFormErrorMessage.length > 0)
	{
		switch (strErrorType.toLowerCase())
		{
			case "alert":
				alert(strFormErrorMessage);
				break;
			case "div":
				if (errorDiv != null)
				{
					errorDiv.innerHTML = strFormErrorMessage;
					errorDiv.style.display = "inline";
				}
				else
				{
					alert("Please set the Form-attribute: \"ERRORDIV\" to hold the ID of the DIV that will display the errormessage!");
				}
				break;
			case "inputboxes":
				break;
			case "":
				alert("Please set the Form-attribute: \"ERRORTYPE\" to one of the following values: \"alert\", \"div\" or \"inputboxes\" ");
				break;
			default:
				break;
		}
/*		var obj = document.getElementById("FormCheckerError");
		obj.innerHTML = strFormErrorMessage;
		obj.style.display = "block";*/
	}
	else
	{
		switch (strErrorType.toLowerCase())
		{
			case "div":
				errorDiv.innerHTML = "";
				errorDiv.style.display = "none";
				break;
			default:
				break;
		}
	}
}

function valForm_formatDutchZip(obj) 
{
	//remove all spaces
	obj.value = obj.value.replace(/ /g,'')
	//upperCase value
	obj.value = obj.value.toUpperCase();
}

function valForm_doRegularExpression(re, strWhat) 
{
	return (re.test(strWhat) == true);
}

function valForm_formatDate(objField) {
	//replace all spaces, dots and stripes with a slash '/'
	objField.value = objField.value.replace(/[\. \-]/g,'/')
	var arValue = objField.value.split("/")
	var strTmpvalue = '';
	var i;
	if (arValue.length == 3) {
		//two slashes are found
		//Make sure the values have a preceding 0, except the last element
		for (i=0;i<arValue.length-1;i++){
			if (arValue[i].length < 2) {
				arValue[i] = '0' + arValue[i]
			}
		}
		//The last element should have 4 characters (==year)
		while (arValue[arValue.length-1].length < 4) {
			//Ad an x until the length is at least 4 chars
			arValue[arValue.length-1] = 'x' + arValue[arValue.length-1]
		}
		
		//save array data into a string
		for (i=0;i<arValue.length;i++){
			strTmpvalue += arValue[i] + '/'
		}
		//Remove last slash
		if (strTmpvalue.substr(strTmpvalue.length-1,1)=='/') {
			strTmpvalue = strTmpvalue.substr(0,strTmpvalue.length-1)
		}
		
		//Show altered value 
		objField.value = strTmpvalue;
	}
}

function CheckDate(strDatum, strFormat)
{
	//Input: 
	//	strDatum: Date string to check, use / a delimiter
	//	strFormat: either 'dd/mm/yyyy' OR 'mm/dd/yyyy'
	var datDate, strNewDate = ""
	var strDate_mmddyyyy

	//Create  a string conform mm/dd/yyyy
	switch (strFormat.toLowerCase()) {
		case ('dd/mm/yyyy') :
			var arTmp = strDatum.split("/")
			if (arTmp.length == 3) {
				//two slashes are found
				strDate_mmddyyyy = arTmp[1] + '/' + arTmp[0] + '/' + arTmp[2]
			} else {
				strDate_mmddyyyy = ''
			}
			break;
		case ('mm/dd/yyyy'):
			strDate_mmddyyyy = strDatum
			break;
	}

	//Perform datecheck on DD/MM/YYYY string
	datDate = new Date(strDate_mmddyyyy)
	
	//NOTE :getMonth is zero based
	if( ( datDate.getMonth() + 1 ) < 10 ){strNewDate += "0"}
	strNewDate += ( datDate.getMonth() + 1 ) + "/"
	if( datDate.getDate() < 10 ){strNewDate += "0"}
	strNewDate += datDate.getDate() + "/"
	strNewDate += datDate.getFullYear()
	
	if( ( strNewDate == strDate_mmddyyyy ) && ( strNewDate.length == 10 ) ){
		return true
	} else{
		return false
	}
}


function chkFrm_isOneCheckboxSelected(objCheckbox) 
{
	//objCheckbox is the radio button collection, not one specific field!!
	var bOneIsChecked = false
	for (k=0;k<objCheckbox.length;k++){
		if (objCheckbox[k].checked) {
			bOneIsChecked = true;
			break;
		}
	}
	return (bOneIsChecked);
}	

function chkFrm_isOneRadioButtonSelected(objRadio) 
{
	//objRadio is the radio button collection, not one specific field!!
	var bOneIsChecked = false
	for (k=0;k<objRadio.length;k++)
	{
		if (objRadio[k].checked) 
		{
			bOneIsChecked = true;
			break;
		}
	}
	return (bOneIsChecked);
}	


/*
var checkFrmVersion = "1.0.0"
var arSupportedTypes = new Array()
arSupportedTypes[0] = "hh:mm"
arSupportedTypes[1] = "dd/mm/yyyy"
arSupportedTypes[2] = "mm/dd/yyyy"
arSupportedTypes[3] = "text"
arSupportedTypes[4] = "email"
arSupportedTypes[5] = "numeric"
arSupportedTypes[6] = "alphanumeric"
arSupportedTypes[7] = "dutchzip"
arSupportedTypes[8] = "floatingnumber"
arSupportedTypes[9] = "twodecimalnumber"
arSupportedTypes[10] = "phonenumber"
arSupportedTypes[11] = "radio"


function xxvalidateForm(objFrm) {
	var strLastCheckedRadio = "" //Hold the name of the radiobutton which was last checked 
	var i
	
	//Loop through form collection
	for (i=0;i<objFrm.length;i++) {
		var objField = objFrm[i]
		var strValue = objFrm[i].value
		var bRequired
		var re //will hold the regular expression to use
		
		//Get custom Attributes
		var strRequired = chkFrm_getCustomAttibute(objField,"formcheck").toLowerCase();
		var strType = chkFrm_getCustomAttibute(objField,"formcheck_type").toLowerCase();

		//set default values if no values are received
		strType = (strType.length==0) ? "text" : strType;
		bRequired = (strRequired=="required");
		bOptional = (strRequired=="optional");
		
		if ((bRequired) || (bOptional)) {
			//Perform check if this field is required OR if it is optional and filled.
			if (!(bOptional) || ((bOptional) && (strValue.length!=0)))
			{
				//Check the type of validation to perform			
				switch (strType) {
					case arSupportedTypes[0] : //"hh:mm"
						//check if time is valid
						re = /^([0-1][0-9]|[2][0-3]):([0-5][0-9])$/;
						if (chkFrm_doRegularExpression(re,strValue)== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[1] : //"dd/mm/yyyy"
						//check if date is valid conform DD/MM/YYYY
						//If D or M is supplied, a preceding 0 will be automatically added.
						//YYYY should have four digits
						//allowed separation chars: '/','-','.',' '(space)
						//All separation chars will be replaced by a '/'
						chkFrm_formatDate((objField));
						//read new value
						strValue = objField.value
						strValue = objField.value
						if (CheckDate(strValue,'dd/mm/yyyy')== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[2] : //"mm/dd/yyyy"
						//check if date is valid conform MM/DD/YYYY
						//If D or M is supplied, a preceding 0 will be automatically added.
						//YYYY should have four digits
						//allowed separation chars: '/','-','.',' '(space)
						//All separation chars will be replaced by a '/'
						chkFrm_formatDate((objField));
						//read new value
						strValue = objField.value
						if (CheckDate(strValue,'mm/dd/yyyy')== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[3] : //"text"
						//check if the field is not empty
						if (strValue.length == 0 ){
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[4] : //"email"
						//check if the email address is valid
						re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,6})+$/;
						if (chkFrm_doRegularExpression(re,strValue)== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[5] : //"numeric"
						//only numeric entries are allowed
						re = /^[0-9]+$/;
						if (chkFrm_doRegularExpression(re,strValue)== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[6] : //"alphanumeric"
						//only alphanumeric characters (a-z AND A-Z) are allowed, no special characters
						re = /^[a-zA-Z\s]+$/; 
						if (chkFrm_doRegularExpression(re,strValue)== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[7] : //"dutchzip"
						chkFrm_formatDutchZip(objField);
						//read new value
						strValue = objField.value
						re = /^[0-9]{4}\s{0,1}[a-zA-Z]{2}$/; 
						if (chkFrm_doRegularExpression(re,strValue)== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[8] : //"floatingnumber"
						//number started with - or +
						//and one decimal sign . or ,
						re = /^[-+]?\d*[\.\,]?\d+$/; 
						if (chkFrm_doRegularExpression(re,strValue)== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[9] : //"twodecimalnumber"
						//one . or , as decimal seperator, other chars only 0-9
						//two decimals max
	
						re = /^\d+[\.\,]?\d{1,2}$/; 
						if (chkFrm_doRegularExpression(re,strValue)== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[10] : //"phonenumber"
						//only NUMERIC KEYS, (, ) , * , +, -,# and spaces are allowed
						re = /^[\d\(\)\-\+\*\# ]+$/; 
						if (chkFrm_doRegularExpression(re,strValue)== false) {
							chkFrm_showError(objField);
							blnReturn = false;
							//return false;
						}
						break;
					case arSupportedTypes[11] : //"radio"
						//Get radio collection, use getElementsByName or names with a | or & in them will cause an error
						objRadio = document.getElementsByName(objField.name)
						if (objField.name != strLastCheckedRadio) {
							//This radiobuttongroup is not checked yet
							strLastCheckedRadio = objField.name;
							if (!(chkFrm_isOneRadioButtonSelected(objRadio))) {
								//No radio button in the group is selected
								chkFrm_showError(objField);
								blnReturn = false;
								//return false;
							}
						}
						break;
				}
			}			 
		}
	}
	if (blnReturn)
		return true;
	else
		return false;
}

function chkFrm_getCustomAttibute(objItem,strAttribName) {
	//return the attribute with the specified name if it exists, else return '';
	var strReturn = (objItem.getAttribute(strAttribName)) ? objItem.getAttribute(strAttribName) : '';
	return strReturn;
}


function chkFrm_isOneRadioButtonSelected(objRadio) {
	//objRadio is the radio button collection, not one specific field!!
	var bOneIsChecked = false
	for (k=0;k<objRadio.length;k++){
		if (objRadio[k].checked) {
			bOneIsChecked = true;
			break;
		}
	}
	return (bOneIsChecked);
}	

*/
