//Copyright pi-squared 2006


//------------------------------------------------------------------------------
// Description	: Clears the target element's values
// Parameters	: objIn
// Returns		: nothing
//------------------------------------------------------------------------------
function clrChild(objIn){
	var myType = chkType(objIn);	
	switch (myType)
	{
	case 'select-one':
	case 'select-multiple':
		clrList(objIn);
		break;
	case 'radio':
	case 'checkbox':
		clrArray(objIn);
		break;
	case 'text': 
	case 'textarea': 
	case 'password': 
	case 'file': 
		clrText(objIn);
	    break;
	default:
		break;
	}
}

//------------------------------------------------------------------------------
// Description	: Checkbox and radio button array clearer
// Parameters	: parent object
// Returns		: nothing
//------------------------------------------------------------------------------
function clrArray(objIn){
	if(objIn.length > 1){
	    //for an array of check boxes or radio buttons
		for(var a = 0; a < objIn.length; a++){
			objIn[a].checked=false;
		}
	}
	else{
	    //for a single check box or radio button
		objIn.checked = false;
	}
}

//------------------------------------------------------------------------------
// Description	: Drop down & multiple clearer
// Parameters	: parent object
// Returns		: nothing
//------------------------------------------------------------------------------
function clrList(objIn){
	for(var a = 0; a < objIn.length; a++){
		objIn[a].selected=false;
	}
}

//------------------------------------------------------------------------------
// Description	: Text input clearer
// Parameters	: parent object
// Returns		: nothing
//------------------------------------------------------------------------------
function clrText(objIn){
	objIn.value = '';
}

//------------------------------------------------------------------------------
// Description	: Hides targeted form elements onLoad, based on form element, plus target value
// Parameters	: none
// Returns		: nothing
//------------------------------------------------------------------------------
function Load(){
    //Search for ","
	var re = /,/gi;
	var newStr;
	for (var i = 0; i < myCheckArray.length; i++){
		newStr = myCheckArray[i].split(re);
		newStr[1] += '_'+newStr[2];
		if (document.getElementById(newStr[1]))		{
		    //only if there is a hidden div
			document.getElementById(newStr[1]).style.display = 'none';
		}
	}
}

//------------------------------------------------------------------------------
// Description	: Hider/un-hider of HTML elements containing targeted form elements
// Parameters	: parentObj,show
// Returns		: nothing
//------------------------------------------------------------------------------
function OtherBox(parentObj,trigger,show){
	var myObj = getObj(parentObj);
	newStr = myObj.name+'_'+trigger;	
	if (document.getElementById(newStr)){
	    myObj=document.getElementById(newStr);
		//only if there is a hidden element
		if(show == true){
			if (myObj.nodeName=="TR"){//got to treat TR's differently
				if (navigator.appVersion.indexOf("MSIE")!=-1){//for IE..could expand to test for container element type...
					myObj.style.display = 'block';
				}
				else{//for other browsers, so we can show/hide TR's as a block level element normally...
					myObj.style.display = 'table-row';
				}
			}
			else{
				myObj.style.display = 'block';
			}
		}
		else{
			myObj.style.display = 'none';
		}
	}
	else{
		return;
	}
}

//------------------------------------------------------------------------------
// Description	: Event handler for dynamically setting form elements to required 
// status, set in onLoad event handler for body tag
// Parameters	: myCheckArray (global)
// Returns		: Nothing
//------------------------------------------------------------------------------
function assignCheckArrays()
{
	var re = /,/gi;
	var myTemp;
	var combCheckArray=new Array(myCheckArray[0].split(re));
	var c=0;
	for (var i=1; i < myCheckArray.length; i++){//for multiple required assignments on different targets of same form element array
		myTemp = myCheckArray[i].split(re);
		if (combCheckArray[c][0]==myTemp[0] && combCheckArray[c][1]==myTemp[1]){
			combCheckArray[c][2]+='&'+myTemp[2];
			combCheckArray[c][3]+='&'+myTemp[3];
		}
		else{
			combCheckArray.push(myTemp);	
			c++;
		}
	}
	for (var i = 0; i < combCheckArray.length; i++)
	{
		checkReqEvents(combCheckArray[i]);
		
	}
}

//------------------------------------------------------------------------------
// Description	: Event handler for dynamically setting form elements to required status
// Parameters	: uses combCheckArray 
// Returns		: Nothing
//------------------------------------------------------------------------------
function checkReqEvents(combCheckArray){
	//might need to be adapted for diff. browsers...
	frmIn = eval ('document.forms.'+combCheckArray[0]);
	objIn = eval ('frmIn.'+combCheckArray[1]);
	var myType = chkType(objIn);
	if((objIn.length > 1 && myType == 'radio')||(objIn.length > 1&&myType == 'checkbox')){
	    //if a form element array
		for (var y=0; y < objIn.length; y++)
		{	
			objIn[y].onclick=function () {setChildReq(combCheckArray,myType)}
		}
	}
	else	{
		if(myType == 'radio' || myType == 'checkbox'){
		    //for single radio or check box
			objIn.onclick = function () {setChildReq(combCheckArray,myType)}
		}
		else{//all other form objects
			objIn.onchange = function () {setChildReq(combCheckArray,myType)}
		}
	}
}

//------------------------------------------------------------------------------
// Description	: Sets the additional form elements to be required/un-required
// Parameters	: combCheckArray, myType
// Returns		: nothing
//------------------------------------------------------------------------------
function setChildReq(combCheckArray,myType)
{
	var re = /&/gi;
	var frmIn,objIn,trigger,toChk;	
	frmIn = eval ('document.forms.'+combCheckArray[0]);
	objIn = eval ('frmIn.'+combCheckArray[1]);
	trigger = combCheckArray[2].split(re);
	toChk = combCheckArray[3].split(re);
	var query, newstr;
	var status = false;
	for (var i=0; i < trigger.length; i++){
		switch (myType){
		case 'select-one':
		case 'select-multiple':
			status = chkList(objIn,trigger[i]);
			break;
		case 'radio':
		case 'checkbox':
			status = chkArray(objIn,trigger[i]);
			break;
		case 'text': 
		case 'textarea': 
		case 'password': 
		case 'file': 
			status = checkText(objIn,trigger[i]);
			break;
		default:
			break;
		}
		classAssign(frmIn,objIn,trigger[i],toChk[i],status);
	}
}

//------------------------------------------------------------------------------
// Description	: visible style setter and 'req' class assigner/de-assigner for 
//                target form elements.
// Parameters	: parent form, target, status
// Returns		: nothing
//------------------------------------------------------------------------------
function classAssign(frmIn,objIn,trigger,toChk,status){
	var myStr = '';
	//Search for "-".
	var re = /-/gi;
	var toChkArray = toChk.split(re);	
	var done=false;
    //Search for " "
	var re = / /gi;
	if(toChkArray[0]!='null'){
		for (var i = 0; i < toChkArray.length; i++){
				var myQuery = eval('frmIn.'+ toChkArray[i]);
				myType = chkType(myQuery);
				if ((myType == 'checkbox' && myQuery.length > 1) || (myType == 'radio' && myQuery.length > 1)){
					query = myQuery[0];	
				}
				else{
					query = myQuery;
				}
				if (status == true){/*assign "req" class*/
					myStr = 'req ' + query.className;
					query.className = myStr;
					OtherBox(objIn,trigger,true);
				}
				else{
						if (done==false){//hack to only do it once...
							traverseNodes(objIn,frmIn,toChkArray,trigger);
							done=true;
						}

						OtherBox(objIn,trigger,false);
				}
			}	
		}
	else{
		OtherBox(objIn,trigger,status);	
	}
}

//------------------------------------------------------------------------------
// Description	: function to clear contents of all form elments within parent div 
//                that was made visible by a parent form element selection specified in myCheckArray, 
//                also clears "req" class assignments
// Parameters	: objIn,frmIn,toChkArray,trigger
// Returns		: nothing
//------------------------------------------------------------------------------

function traverseNodes(objIn,frmIn,toChkArray,trigger){
	//string variable to test for
	var re = / /gi;
	
	//determine id of parent element
	objIn=getObj(objIn);
	var targetStr = objIn.name+'_'+trigger;
	
	//initialise form array index variables
	var index, endIndex, startIndex =0;
	var endOfDom=1000;

	//determine form element index of final element in toChkArray
	index=detFormIndex(frmIn,toChkArray,toChkArray.length-1);
	
	//find end element in form array within parent element
	for (var i=0; i<endOfDom; i++){
		if(myObj.parentNode.id==targetStr){
			//alert(myObj.title+' is a child');
			endIndex=index;
			index++;
			myObj=frmIn[index];
		}
		else{
			myObj=myObj.parentNode;
			if (myObj==document){
				break;
			}
		}
	}

	//determine form element index of first element in toChkArray
	index=detFormIndex(frmIn,toChkArray,0);
	
	//find end element in form array within parent element;
	endOfDom=0;
	for (var i=1000; i>endOfDom; i--){
		if(myObj.parentNode.id==targetStr){
			//alert(myObj.title+' is a child');
			startIndex=index;
			index--;
			myObj=frmIn[index];
		}
		else{
			myObj=myObj.parentNode;
			if (myObj==document){
				break;
			}
		}
	}
	//clear all form elements inside parent element
	for (var i=startIndex; i<endIndex+1; i++){
		clrChild(frmIn[i]);
		myStr = frmIn[i].className.split(re);
		if(myStr[0] == 'req'){
			myStr.shift();
			var tmpStr='';
			for (var s=0; s<myStr.length; s++){
				tmpStr+=myStr[s]+' ';
			}
			frmIn[i].className = tmpStr;
		}
	}
}

//------------------------------------------------------------------------------
// Description	: Returns index in parent form array of object
// Parameters	: parent form, object
// Returns		: index
//------------------------------------------------------------------------------

function detFormIndex(frmIn,toChkArray,index){
	myObj = eval ('frmIn.'+toChkArray[index]);
	myObj = getObj(myObj);
	var index=0;
	for (var i=0; i<frmIn.length; i++){
		if(frmIn[i]==myObj){
			index=i;	
		}
	}
	return index;
}
	
//------------------------------------------------------------------------------
// Description	: Form validator function, gives the user an error list, and puts focus on 1st incorrect field
// Parameters	: parent object
// Returns		: nothing
//------------------------------------------------------------------------------
function fnValidateForm(frmIn){
	//for if only a single form to be checked
	if(frmIn.name){
		frmIn = new Array(frmIn);
	}
	var errorStack = new Array();
	
	//looks for blank gap in class assignments for form elements
	var re = / /gi;
	var check = '';
	var test, query, myStr;
	for (var m = 0; m < frmIn.length; m++){
		for (var i = 0; i < frmIn[m].length; i++){
			
			//makes sure sibling radio & check box elements don't all get processed, only collection
			if (frmIn[m][i].name != check){
				myStr = frmIn[m][i].className.split(re);
				if(myStr[0] == 'req'){
					//ensures that array of radio or check box elements get checked, not individual element of array
					query = eval('frmIn[m].'+frmIn[m][i].name);
					
					//checks to see whether a required form element has been selected/filled in or correctly formatted
					test = assignChk(query,myStr);
					if (test != true){
						errorStack.push(test);	
					}
				}
			}
			check = frmIn[m].elements[i].name;
		}
	}
	for (var m = 0; m < frmIn.length; m++){
		errorStack = chkMatches(errorStack,frmIn[m]);
	}
    //Search for ","
	re = /,/gi;
	//var errorMessageArray = errorMessages.split(re);
	
	var errorMessageArray = errorMessages;
	
	//Error Message Displayed on page.
	var bldErrorMessage = 'Please fill in the following details:\n-------------------------------------------------\n\n';
	for (var i = 0; i < errorStack.length; i++){
		bldErrorMessage += prcssErrorArray(errorMessageArray,errorStack[i])+'\n\n';
	}
	if (bldErrorMessage != 'Please fill in the following details:\n-------------------------------------------------\n\n'){
		alert(bldErrorMessage);
		return false;
	}
	else{
	  return true;
	}
}

//------------------------------------------------------------------------------
// Description	: determines whether the form element in the error stack has a description in errorMessages
// Parameters	: errorMessageArray, element
// Returns		: element name/
//------------------------------------------------------------------------------
function prcssErrorArray(errorMessageArray,myError){
	//Search for "-".
	var re1 = /,/gi;
	var re2 = /-/gi;
	var test = false;
	var errorMsg = '';
	
	if (!myError.type){
        //if an array with a message at the end. ie. incorrectly formatted input, or non matching inputs
		for (var k = 0; k < myError.length-1; k++){
			for (var x = 0; x < errorMessageArray.length; x++){
				var tempArray1 = errorMessageArray[x].split(re1);
				var tempArray2 = tempArray1[1].split(re2);
				if (myError[k].name == tempArray2[0] && myError[k].form.name == tempArray1[0]){
					errorMsg+='\''+tempArray2[1]+'\'';
					if(k != myError.length-2){
						errorMsg+=' & ';
					}
					test = true;
					break;
				}	
			}
			if(test == false){
				errorMsg+='\''+myError[k].title+'\'';
				if(k != myError.length-2){
					errorMsg+=' & ';
				}
			}
		}
		errorMsg+=' '+myError[myError.length-1];
		return errorMsg;
	}
	else{
		
		 //just a normal form element in the array
		for (var x = 0; x < errorMessageArray.length; x++){
			var tempArray1 = errorMessageArray[x].split(re1);
			var tempArray2 = tempArray1[1].split(re2);
			if (myError.name == tempArray2[0] && myError.form.name == tempArray1[0]){
				return '\''+tempArray2[1]+'\' needs to be completed.';
			}	
		}
		return '\''+myError.title+'\' needs to be completed.';
	}
}

//------------------------------------------------------------------------------
// Description	: determines whether the form element is a single element or array
// Parameters	: parent object
// Returns		: myType
//------------------------------------------------------------------------------

function chkType(objIn){
	if (!objIn.type){//for radio button and check box arrays 
		return objIn[0].type;
	}
	else{
		return objIn.type;
	}
}

//------------------------------------------------------------------------------
// Description	: determines whether the form element is a single element or array
// Parameters	: parent object
// Returns		: myType
//------------------------------------------------------------------------------

function getObj(objIn){
	if (!objIn.type){//for radio button and check box arrays 
		return objIn[0];
	}
	else{
		return objIn;
	}
}

//------------------------------------------------------------------------------
// Description	: Determines input type, assigns correct check function
// Parameters	: parent object, class string array
// Returns		: parent object, false
//------------------------------------------------------------------------------

function assignChk(objIn,myStr){
	var myType = chkType(objIn);
	switch (myType){
    	case 'select-one': 
		case 'select-multiple': 
			return chkList(objIn);
		case 'radio': 
		case 'checkbox': 
			return chkArray(objIn); 
		case 'text': 
		case 'textarea': 
		case 'password': 
		case 'file': 
			return checkText(objIn,myStr); 
    	default: 
			return 'unknown';
	}
}

//------------------------------------------------------------------------------
// Description	: Checkbox and radio button array checker
// Parameters	: parent object
// Returns		: parent object, checked
//------------------------------------------------------------------------------
function chkArray(objIn,target){
	var checked = false;
	var toReturn;
	if(objIn.length > 1){
	    //for an array of check boxes or radio buttons
		for(var a = 0; a < objIn.length; a++)		{
			if (objIn[a].checked){
				if(!target){
					if(objIn[a].value != ''){//make sure selected option has a value, ie. not 'please select'
						checked = true;
					}
				}
				else{
					if(objIn[a].value == target){//tests if radio or check button selected matches the target
						checked = true;
					}
				}
			}
		}
		toReturn = objIn[0];//id tag is set on 1st element of radio or check array
	}
	else{//for a single check box or radio button
		if (objIn.checked){
			if(!target){
				if(objIn.value != ''){//make sure selected option has a value, ie. not 'please select'
					checked = true;
				}
			}
			else{
				if(objIn.value == target){//tests if radio or check button selected matches the target
					checked = true;
				}
			}
		}
		toReturn = objIn;
	}
	if (checked == false){
		if (target){
			return checked;
		}
		else{
			return toReturn;
		}
	}
	else{
		return checked;
	}
}

//------------------------------------------------------------------------------
// Description	: Drop down & multiple select checker
// Parameters	: parent object, target
// Returns		: parent object, checked
//------------------------------------------------------------------------------

function chkList(objIn,target){
	var checked = false;
	for(var a = 0; a < objIn.length; a++){
		if (objIn[a].selected){
			if(!target){//checks to see if target has beeen selected
				if (objIn[a].value != ''){//make sure selected option has a value, ie. not 'please select' or something like that...'
					checked = true;
				}
			}
			else{
				if (objIn[a].value == target){//checks to see if the target value was selected
					checked = true;
				}
			}
		}
	}
	if (checked == false){
		if (target){
			return checked;
		}
		else{
			return objIn;
		}
	}
	else{
		return checked;
	}
}

//------------------------------------------------------------------------------
// Description	: Text input checker
// Parameters	: parent object
// Returns		: parent object, false
//------------------------------------------------------------------------------

function checkText(objIn,myStr,target){
	if(!target){
		if (objIn.value == ''){
			return objIn;
		}
		else{
			return assignFormatValidator(objIn,myStr);
		}
	}
	else{
		if (objIn.value != ''){
			return true;
		}
		else{
			return false;
		}
	}
}

//------------------------------------------------------------------------------
// Description	: Assigns correct text field format validator
// Parameters	: objIn
// Returns		: parent object, false
//------------------------------------------------------------------------------

function assignFormatValidator(objIn,myStr){
	switch (myStr[1]){
	    //to grow list with date, telephone etc. functions...
		case 'email': 
			return verifyEmail(objIn);
		case 'ccnumber': 
			return verifyCcNumber(objIn);
		default: 
			return true;
	}
}

//------------------------------------------------------------------------------
// Description	: Email validator
// Parameters	: FormFieldName
// Returns		: parent object, false
//------------------------------------------------------------------------------
function verifyEmail(FormFieldName)
{
	var emailReg = "^[\\w-_\.]*[\\w-_\.]\@[\\w]\.+[\\w]+[A-Za-z0-9]$"; // credit: madcow@olg.com (slightly adapted)
	var emailExp = new RegExp(emailReg);
	if (emailExp.test(FormFieldName.value)){
		return true;
	}
	else{
		return [FormFieldName,'needs to be formatted correctly.'];
	}
}

//------------------------------------------------------------------------------
// Description	: CCnumber validator
// Parameters	: FormFieldName
// Returns		: parent object, false
//------------------------------------------------------------------------------

function verifyCcNumber(FormFieldName)

{
	var charityReg = /^\d{15,}$/; //must be at least 6 numbers only
	var charityExp = new RegExp(charityReg);
	if (charityExp.test(FormFieldName.value)){
		return true;
	}
	else{
		return [FormFieldName,'needs to contain at least 15 numbers, and no spaces.'];
	}
}
//------------------------------------------------------------------------------
// Description	: determines whether elements in confirmArray are correctly matched
// Parameters	: errorStack, parent form
// Returns		: errorStack
//------------------------------------------------------------------------------
function chkMatches(errorStack,frmIn){
	var re, myStr;
	for (var i = 0; i < confirmArray.length; i++)	{
		var mtchArray = new Array();
		re = /,/gi;
		myStr = confirmArray[i].split(re);
		if (myStr[0] == frmIn.name){
			re = /-/gi;
			myStr = myStr[1].split(re);
			for (var k = 0; k < myStr.length; k++){
				mtchArray.push(eval('frmIn.'+myStr[k]));
			}
			for (var j = 0; j < myStr.length-1; j++){
				query1 = mtchArray[j];
				query2 = mtchArray[j+1];
				if (query1.value != query2.value){
					mtchArray.push('need to match each other.');
					errorStack.push(mtchArray);
				}
			}
		}
	}
	return errorStack;
}