/*Copyright 2004 Daniel Bennett Email Contact dan AT railay DOT com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/

	//This will make sure that we can use a function called getElementById no matter the browser
	if(!document.getElementById){
	  if(document.all)
	  document.getElementById=function(){
	    if(typeof document.all[arguments[0]]!="undefined")
	    return document.all[arguments[0]]
	    else
	    return null
	  }
	  else if(document.layers)
	  document.getElementById=function(){
	    if(typeof document[arguments[0]]!="undefined")
	    return document[arguments[0]]
	    else
	    return null
	  }
	}




//	arrValidate[0]=["0FormID","1strID","2strShortName","3booIsCompulsory","4strFieldType","5intRangeHigh","6intRangelow"];
	
function Validate(arrValidation,objForm,action,alertType){
	var strErrorMessage="";
	var booFieldFocus=false;
	var objFieldToFocus;
	//strFieldType=none any text date number email postcode integer percentage

	for (var i =0; i < arrValidate.length; i++){
		var booContinue=true;
		var booFieldDefined=true;
		// create refereance to field
		//alert(arrValidate[i][2]);
		//first test field name is valid
		if (arrValidate[i][1]=="" || isInteger(arrValidate[i][1].substring(0,1))){
			alert("Unable to submit this form due to a bad field name, Please contact the site administrator");
			return;
		}
		if (typeof objForm=="undefined" || objForm==null ){
			if (arrValidate[i][0]=="" || (typeof arrValidate[i][0]=="undefined") || arrValidate[i][0]==null) {
				alert("Unable to submit this form, Please contact the site administrator"); 
				return;
			} 
			else {
				var objField=eval("document."+arrValidate[i][0]+"."+arrValidate[i][1]);
				objForm=eval("document."+arrValidate[i][0]);
			}
		}
		else var objField=eval("document."+objForm.name+"."+arrValidate[i][1])
		
		//first lets double check that this baby rearlly exists....
		if (typeof objField=="undefined" || objField==null ){
			strErrorMessage=strErrorMessage+" -"+arrValidate[i][2]+"This question ID Does not exist on the form! Contact the ADMINISTRATOR AND FIX THIS! \n";
			booContinue=false;
			booFieldDefined=false;
		}
		//uncolor the field incase it is colored- can always color againg...
		if(booContinue)UnColorError(objField);
		
		
		//first let us see if it compulsory
		if (arrValidate[i][3] && booContinue)  {
			//call isCompulsory function
			if (!ValidateHasValue(objField)){
				booContinue=false;
				strErrorMessage=strErrorMessage+" <li>"+arrValidate[i][2]+" is compulsory </li>\n";
			}
		}
		
		//Now let us see if it requires to check the nature of the contents
		// for the time being we will assume that it only makes sense to validate the contents if
		// We are not just allowing any old content
		// we are validating a text field
		if (booContinue && (arrValidate[i][4] != "any") && (objField.value!="") && (objField.type == "text" || objField.type == "textarea" || objField.type == "password" || objField.type == "file"))  {
			//check to see to see if it is a number
			if (arrValidate[i][4]=="number") {
				//call validate number
				var strValidateIsNumber=ValidateIsNumber(objField,arrValidate[i][5],arrValidate[i][6])
				if (strValidateIsNumber!=true){
					booContinue=false;
					//adds on the mesage returned from validate number. This message would pertain to ranges
					strErrorMessage=strErrorMessage+" <li>"+arrValidate[i][2]+" has to be a number " + strValidateIsNumber + "</li>\n";
				}
			}
			else if (arrValidate[i][4]=="positiveNumber") {
				//call isPositiveNumeric
				if (!isPositive(objField.value)){
					booContinue=false; 
					strErrorMessage=strErrorMessage+" <li>"+arrValidate[i][2]+" has to be a positive number </li>\n";
				}
			}
			else if (arrValidate[i][4]=="positiveInteger") {
				//call isPositiveNumeric
				if (!isPositive(objField.value) | ValidateIsInteger(objField)!=true){
					booContinue=false; 
					strErrorMessage=strErrorMessage+" <li>"+arrValidate[i][2]+" has to be a positive integer </li>\n";
				}
				
			}
			else if (arrValidate[i][4]=="postcode") {
				//call validate date
				if (!ValidatePostcode(objField)){
					booContinue=false; 
					strErrorMessage=strErrorMessage+" <li>"+arrValidate[i][2]+" has to be a valid postcode </li>\n";
				}
			}
			else if (arrValidate[i][4]=="integer") {
				//call validate number
				var strValidateIsInteger=ValidateIsInteger(objField,arrValidate[i][5],arrValidate[i][6])
				if (strValidateIsInteger!=true){
					booContinue=false;
					//adds on the mesage returned from validate number. This message would pertain to ranges
					strErrorMessage=strErrorMessage+"<li>"+arrValidate[i][2]+" has to be an Integer " + strValidateIsInteger + "</li>\n";
				}
			}
			else if (arrValidate[i][4]=="date") {
				//call validate date
				if (!ValidateIsDate(objField)){
					booContinue=false;
					strErrorMessage=strErrorMessage+" <li>"+arrValidate[i][2]+" has to be a valid date in the form dd-mm-yyyy </li>\n";
				}
			}
			else if (arrValidate[i][4]=="percentage") {
				//call validate date
				if (!ValidatePercentage(objField)){
					booContinue=false;
					strErrorMessage=strErrorMessage+" <li>"+arrValidate[i][2]+" has to be a Percentage </li>\n";
				}
			}
			else if (arrValidate[i][4]=="email") {
				//call validate email
				if (!ValidateIsEmail(objField)){
					booContinue=false;
					strErrorMessage=strErrorMessage+" <li>"+arrValidate[i][2]+" has to be a valid email address in the form someone@somewhere.com </li>\n";
				}
			}
		}// end validateion of text fields
		
		//do something pretty

		if (!booContinue && booFieldDefined) ColorError(objField)
		else if (typeof hasSubmitted != "undefined")UnColorError(objField);

		// set the focus of this field if focus is not already set, and this field is shite
		// crappy IE work around, as unless this is your last action it will overwrite the focus
		//alsoe cant seem to focus on radio buttons
		// this is an arse. if it is a multiple type then this will throw an error-
		// so catch error and then check first item of array for type
		if (objField.type==null) strType=eval("objField[0].type")
		else strType=objField.type
		if ((!booContinue && !booFieldFocus && booFieldDefined) & (strType!="checkbox" & strType!="radio")) {
			objFieldToFocus=objField;
			booFieldFocus=true;
		}
	}//end for loop
	
	// if there is an error, display it otherwise sumbit the form
	if (strErrorMessage!="") {
		//give up on the focus
		//objFieldToFocus.focus();
		
		// If we want an alert box, just doe it and then return...
		if (alertType=="alertBox"){
			//strip out the li's
			strErrorMessage=strErrorMessage.replace(/<li>/g,"* ");
			strErrorMessage=strErrorMessage.replace(/<\/li>/g,"");
			alert("The following errors below were detected when processing the form: \n" + strErrorMessage);
			return;
		}
		messages=document.getElementById("Messages");
		location.hash = 'error';

		//window.scrollTo(0,200);
		Errorbox="<table id='MessageBoxError' class='tableContent'><tr><td colspan=2 height=3></td></tr><tr><td valign='top' width=5><img src='images/iconError.gif' vspace=0></td><td width='100%'>";
		Errorbox+="<b>Please correct the following problems (highlighted in red) and resubmit the form:</b>";
		Errorbox+="<ul>"+strErrorMessage+"</ul></td></tr></table><br>";
		messages.innerHTML=Errorbox;
	} else {
		if (alertType!="alertBox")document.getElementById("Messages").innerHTML="";
		Calculate(objForm,action);
		//objForm.submit();
	}
	hasSubmitted=true;
}// end validate function
	
	

function ValidateIsNumber(objField,numHigh,numLow) {
	if (!isDecimal(objField.value)){
		return "";
	}
	if ((typeof numHigh!="undefined") && (typeof numLow!="undefined") && (numHigh!="" && numLow!="")){
		if (!isNumBetween(objField.value,numHigh,numLow)) {
			return "between " + numLow + " and " + numHigh;
		}
	}
	return true;
}

function ValidateIsInteger(objField,numHigh,numLow) {
	if (!isInteger(objField.value)){
		return "";
	}
	if ((typeof numHigh!="undefined") && (typeof numLow!="undefined") && (numHigh!="" && numLow!="")){
		if (!isNumBetween(objField.value,numHigh,numLow)) {
			return "between " + numLow + " and " + numHigh;
		}
	}
	return true;
}

function ValidatePostcode(objField){
	if (isInteger(objField.value)){
		if (isNumBetween(objField.value,9999,1000)) return true
	}
	else return false
	return false;
}
	
/***************************************
* Checks to see if the String it is 
 * passed isNumeric, >= 0 and <= 100
 * PARAMETERS:
 *  sPercentage - Number to check
 **************************************/
function ValidatePercentage(objPercentage) {
    var bReturnCode = false;
    var sInputStr   = objPercentage.value.toString();
    /* Check that the String is Numeric*/
    if (isDecimal(sInputStr)) {
        /* Parse it into a float as is more general
         * and check that it is between 0 and 100*/
        var nPercentage = parseFloat(sInputStr); 
        if (nPercentage >= 0 && nPercentage <= 100)  {
            bReturnCode = true;
        }
    }
    return bReturnCode;
}

function isNumBetween(numNumber,numHigh,numLow) {
		// alert(numHigh + " other " + numLow);
	if (numHigh!="" && numLow!=""){
		if ((typeof numHigh!="undefined") && (typeof numLow!="undefined") && (numHigh!="" && numLow!="")) {
			if (parseFloat(numNumber)<parseFloat(numLow) || parseFloat(numNumber)>parseFloat(numHigh)) return false
			else return true
		}
		else return false
	}
	else return false	
	return true;
}
	

/***************************************
 * Checks to see if the String it is 
 * passed isNumeric and >= 0
 * PARAMETERS:
 *  sNumber - Number to check
 **************************************/
function isPositive(sNumber) {
    var bReturnCode = false;
    var sInputStr   = sNumber.toString();
    /* Check that the String is Numeric*/
    if (isDecimal(sInputStr)) {
        /* Parse it into a float as is more general 
         * and check that it is greater then or equal to 0*/
        if (parseFloat(sInputStr) >= 0){
            bReturnCode = true;
        }
    }
    return bReturnCode;
}

/***************************************
 * Checks to see if the String it is 
 * passed isNumeric and <= 0
 * PARAMETERS:
 *  sNumber - Number to check
 **************************************/
function isNegative(sNumber) {
    var bReturnCode = false;
    var sInputStr   = sNumber.toString();
    /* Check that the String is Numeric*/
    if (isNumeric(sInputStr)){
        /* Parse it into a float as is more general
         * and check that it is less then or equal to 0*/
        if (parseFloat(sInputStr) <= 0){
            bReturnCode = true;
        }
    }
    return bReturnCode;
}



/***************************************
 *  Returns a boolean depending if the 
 *  string is an Decimal
 *  Caters for a leading '+'or '-'
 *  Could use parseFloat but want to have 
 *  more specific rules.
 * PARAMETERS:
 *  sDecimal - string to test
 **************************************/
function isDecimal(sDecimal){
    var bReturnCode       = true;
    var nStartOfNum       = 0;
    var sInputStr         = sDecimal.toString();
    var bSeenDecimalPoint = false;
    /* Check if the first value is a '+' or '-' and skip it when checking for numbers */
    if (sInputStr.length > 0)  {
        var cFirstChar = sInputStr.charAt(0);
        if (cFirstChar == '+' || cFirstChar == '-') {
            nStartOfNum = 1;
        }
    }
    /* Check each char to see if it is a number or a '.'*/
    var i = nStartOfNum;
    while (i < sInputStr.length && bReturnCode) {
        var cOneChar = sInputStr.charAt(i);                       
        if (cOneChar == '.') {
            /* Can only have 1 decimal point */
            if (bSeenDecimalPoint == false) {
                bSeenDecimalPoint = true;
            }
            else {
                bReturnCode = false;
            }
        }
        else if (cOneChar < "0" || cOneChar > "9") {
            bReturnCode = false;
        }
        i++;
    }
    return bReturnCode;
}

/***************************************
 *  Returns a boolean depending if the 
 *  string is an integer
 *  Caters for a leading '+'or '-'
 *  Could use parseInt but want to have 
 *  more specific rules.
 * PARAMETERS:
 *  sInteger - string to test
 **************************************/
function isInteger(sInteger) {
    var bReturnCode = true;
    var nStartOfNum = 0;
    var sInputStr    = sInteger.toString();
    /* Check if the first value is a '+' or '-' and skip it when checking for numbers */
    if (sInputStr.length > 0)  {
        var cFirstChar = sInputStr.charAt(0);
        if (cFirstChar == '+' || cFirstChar == '-') {
            nStartOfNum = 1;
        }
    }
    /* Check each char to see if it is a number*/
    var i = nStartOfNum;
    while (i < sInputStr.length && bReturnCode) {
        var cOneChar = sInputStr.charAt(i)                        
        if ((cOneChar < "0" || cOneChar > "9")) {
            bReturnCode = false;
        }
        i++;
    }
    return bReturnCode;
}


	
function ColorError(objField){
	var strType
	// this is an arse. if it is a multiple type then this will throw an error-
	// so catch error and then check first item of array for type
	if (objField.type==null) strType=eval("objField[0].type")
	else strType=objField.type
	
	//lets double check that this baby rearlly exists....
	if (typeof objField=="undefined" || objField==null )return
	
	//lets test then
	//alert(strType + objField.value);
	if (strType=="text" || strType=="textarea" || strType=="file"){
		objField.style.background="#FF6464";
	}
	else if (strType=="checkbox" || strType== "radio"){
		//oDocElement.dataType = sAttribValue;
		//oDocElement.style.textAlign = "right";
		//shite hack if only one box
		if (typeof objField.length=="undefined" || objField.length==null || objField.length==0 || objField.length==1){
			objField.style.border="inset red 2px";
		}
		else {
			for (var j =0; j < objField.length; j++){
				objField[j].style.border="inset red 2px";
			}
		}
	}
	else if (strType=="select-one" || strType=="select-multiple"){
		objField.style.background="#FF6464";
	}
}//end function ColorError
	
function UnColorError(objField){
	var strType
	// this is an arse. if it is a multiple type then this will throw an error-
	// so catch error and then check first item of array for type
	if (objField.type==null) strType=eval("objField[0].type")
	else strType=objField.type
	
	//lets double check that this baby rearlly exists....
	if (typeof objField=="undefined" || objField==null )return
	
	//lets test then
	if (strType=="text" || strType=="textarea" || strType=="file"){
		objField.style.background="white"
	}
	else if (strType=="checkbox" || strType== "radio"){
		//oDocElement.dataType = sAttribValue;
		//oDocElement.style.textAlign = "right";
		//shite hack if only one box
		if (typeof objField.length=="undefined" || objField.length==null || objField.length==0 || objField.length==1){
			objField.style.border="";
		}
		else {
			for (var j =0; j < objField.length; j++){
				objField[j].style.border="";
			}
		}
	}
	else if (strType=="select-one" || strType=="select-multiple"){
		objField.style.background="white";
	}
}//end function UnColorError


function ValidateHasValue(objField){
	var booHasValue=false;
	var strType
	// this is an arse. if it is a multiple type then this will throw an error-
	// so catch error and then check first item of array for type
	if (objField.type==null) strType=eval("objField[0].type")
	else strType=objField.type
	//lets test then
	if (strType=="text" || strType=="textarea" || strType=="file"){
		if (!objField.value=="") booHasValue=true
	}
	else if (strType=="checkbox" || strType== "radio"){
		//oDocElement.dataType = sAttribValue;
		//oDocElement.style.textAlign = "right";
		//shite hack if only one box
		if (typeof objField.length=="undefined" || objField.length==null || objField.length==0 || objField.length==1){
			if(objField.checked) booHasValue=true
		}
		else {
			for (var j =0; j < objField.length; j++){
				if(objField[j].checked) booHasValue=true
			}
		}
	}
	else if (strType=="select-one" || strType=="select-multiple"){
		if (!objField.options[objField.selectedIndex].value=="")  booHasValue=true
	}
	return booHasValue;
}//end function ValidateHasValue
	
	
function ValidateIsEmail(objFieldd) {
	var e =objFieldd.value;
	var ok = "1234567890qwertyuiop[]asdfghjklzxcvbnm.@-_QWERTYUIOPASDFGHJKLZXCVBNM";
		for(var i=0; i < e.length ;i++){
			if(ok.indexOf(e.charAt(i))<0){ 
				return (false);
			}	
		} 
		if (document.images) {
			re = /(@.*@)|(\.\.)|(^\.)|(^@)|(@$)|(\.$)|(@\.)/;
			re_two = /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
			if (!e.match(re) && e.match(re_two)) {
				return (-1);		
			} 
		}
}//end chaeckemail
	
function ValidateIsDate(objField) {
	// Checks for the following valid date formats:
	// DD/MM/YY   DD/MM/YYYY   DD-MM-YY   MM-DD-YYYY
	// Also separates date into month, day, and year variables
	var dateStr = objField.value
	var datePat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{2}|\d{4})$/;

	// To require a 4 digit year entry, use this line instead:
	// var datePat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{4})$/;
	
	var matchArray = dateStr.match(datePat); // is the format ok?
	if (matchArray == null) return false
	day = matchArray[1]; // parse date into variables
	month = matchArray[3];
	year = matchArray[4];
	if (month < 1 || month > 12) { // check month range
		return false;
	}
	if (day < 1 || day > 31) {
		return false;
	}
	if ((month==4 || month==6 || month==9 || month==11) && day==31) {
		//alert("Month "+month+" doesn&'t have 31 days!")
		return false;
	}
	if (month == 2) { // check for february 29th
		var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
		if (day>29 || (day==29 && !isleap)) {
			//alert("February " + year + " doesn&#39t have " + day + " days!");
			return false;
		}
	}
	return true;  // date is valid
}//END DATE VALID

function getRadioValue(radio){
	for (var i = 0; i< radio.length; i++) {
		if (radio[i].checked) {
			return radio[i].value;
		}
	} 
}


function round_decimals(original_number, decimals) {
    var result1 = original_number * Math.pow(10, decimals)
    var result2 = Math.round(result1)
    var result3 = result2 / Math.pow(10, decimals)
    return result3;
	//return pad_with_zeros(result3, decimals)
}


function NumberRounding(number,dec_places){
//(c) Copyright 2008, Russell Walker, Netshine Software Limited. www.netshinesoftware.com
var new_number='';var i=0;number=number.toString();dec_places=dec_places*1;dec_point_pos=number.lastIndexOf(".");if(dec_point_pos==0){number="0"+number;dec_point_pos=1}if(dec_point_pos==-1||dec_point_pos==number.length-1){if(dec_places>0){new_number=number+".";for(i=0;i<dec_places;i++){new_number+="0"}return new_number}else{return number}}var existing_places=(number.length-1)-dec_point_pos;if(existing_places==dec_places){return number}if(existing_places<dec_places){new_number=number;for(i=existing_places;i<dec_places;i++){new_number+="0"}return new_number}var end_pos=(dec_point_pos*1)+dec_places;var round_up=false;if((number.charAt(end_pos+1)*1)>4){round_up=true}var digit_array=new Array();for(i=0;i<=end_pos;i++){digit_array[i]=number.charAt(i)}for(i=digit_array.length-1;i>=0;i--){if(digit_array[i]=="."){continue}if(round_up){digit_array[i]++;if(digit_array[i]<10){break}}else{break}}for(i=0;i<=end_pos;i++){if(digit_array[i]=="."||digit_array[i]<10){new_number+=digit_array[i]}else{new_number+="0"}}if(dec_places==0){new_number=new_number.replace(".","")}return new_number}

function pad_with_zeros(rounded_value, decimal_places) {
    // Convert the number to a string
    var value_string = rounded_value.toString()
    // Locate the decimal point
    var decimal_location = value_string.indexOf(".")
    // Is there a decimal point?
    if (decimal_location == -1) {
        // If no, then all decimal places will be padded with 0s
        decimal_part_length = 0
        // If decimal_places is greater than zero, tack on a decimal point
        value_string += decimal_places > 0 ? "." : ""
    }else {
        // If yes, then only the extra decimal places will be padded with 0s
        decimal_part_length = value_string.length - decimal_location - 1
    }
    // Calculate the number of decimal places that need to be padded with 0s
    var pad_total = decimal_places - decimal_part_length
    if (pad_total > 0) {
        // Pad the string with 0s
        for (var counter = 1; counter <= pad_total; counter++) 
            value_string += "0"
        }
    return value_string
}
