//+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+#
// JAVASCRIPT VALIDATION -- validate.js	v2																										     UPDATED: 07/11/06 CHRIS  #
//+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+#
//
//  Script Author: Chris Merry
//     
//	Description:   This script will validate any form data and enforce certain rules on the data entered via a validation obj alowing for multi level validation
//					   for formatting / extra validation objects via regular expressions.
//
//	Thanks to:	   Ben Clayton, Marc Woodhead :)													   
//
//+=+=+=+=+=+=+=+=+=+=+=+=+=[ (C) Chris Merry - Do not copy this script in anyway without permission. ]=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=#

var errorTxt = "The fields highlighted below must be completed.";

// ---------- VALIDATION REGULAR EXPRESSIONS ---------------------------------------------------------------------------------------
var urlRegxp			=	/^((http|https):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i
// -------------------------------------------------------------------------------------------------------------------------------------
var emailRegxp			=	/^([\w_-]+)(\.[\w_-]+)*@([\w_-]+)(\.[\w_-]*){0,1}(\.[a-zA-Z]{2,4}){1,2}$/; 
// -------------------------------------------------------------------------------------------------------------------------------------
var pcodeRegxp		=	/^([A-Za-z]{1,2})([0-9]{2,3})([A-Za-z]{2})$/;
// -------------------------------------------------------------------------------------------------------------------------------------
var dateRegxp			=	/^([0-9]){1,2}\/{1}([0-9]){1,2}\/([0-9]){2}$/;
// -------------------------------------------------------------------------------------------------------------------------------------
var passwordRegxp	=	/^[a-zA-Z0-9]{3,14}$/;
// -------------------------------------------------------------------------------------------------------------------------------------
var timeRegxp			=	/^[0-9]{2}:{1}[0-9]{2}$/;
// -------------------------------------------------------------------------------------------------------------------------------------
var usernameReqxp	=	/[a-zA-Z0-9]{6,20}/;
// -------------------------------------------------------------------------------------------------------------------------------------
var currencyRegxp	=	/^\d+(\.\d{1,2})?$/;
// -------------------------------------------------------------------------------------------------------------------------------------
var telnoRegxp			=	/^(^[0-9\+ ]+)$/
// -------------------------------------------------------------------------------------------------------------------------------------
var numericRegxp		=	/^([0-9\.]+)$/;
// -------------------------------------------------------------------------------------------------------------------------------------
var notblankRegxp		= /[a-zA-Z_0-9]+/;   // used by the isBlank function
// -------------------------------------------------------------------------------------------------------------------------------------

function submit_form(frmname,chklist){
	var frmObj = document.forms[frmname];
	if(frmObj){
		if(verifylist(frmObj,chklist)) frmObj.submit();
	}
}

function verifylist(formobj,chklist){
	
	var type = new Array();
	var good = new Array();
	var alt_tags = new Array();
	var fail=0;

	var debug=0;
	var debugTxt="";

	for (var i=0; i<formobj.length; i++){
		var e=formobj.elements[i];

		var opt_flag = -1;

		var name = e.name;
		var valObj;

		var valObj = chklist[name];

		if (!good[name]) good[name] = 0;
		debugTxt += "FIELD NAME: " + name;

		if(valObj){	
			var valtype = valObj.valtype;
			//alert(valtype);
			//alert(e.type);
			debugTxt += " - IN CHECKLIST ("+valtype+")";
			if	(isdisplayed(e) && e.type != 'hidden'){					
				debugTxt += " - VISIBLE\n";
				
				if(valtype.indexOf('opt~') != -1){
					//alert("OPTIONAL VALUE" + typ.replace(/opt_/,''));
					valtype = valtype.replace(/opt~/,'');
					opt_flag = 1;
				}

				//###############################################################
				var bits = validate_field_value(e,name,valObj,valtype,opt_flag,good[name]);											// VALIDATE A SINGLE FORM ELEMENT
				type[name] = valtype;
				good[name] = bits[0];
				alt_tags[name] = bits[1];
				//###############################################################

			}else{
				debugTxt += " - INVISIBLE";
				good[name]=1; // hidden so say it is good													 
			}
		}else{
			debugTxt += " - NOT IN CHECKLIST";
			good[name]=1; // not in list so say it is good													 
		}
		if(good[name]) 	debugTxt += " - GOOD\n";
		else debugTxt += " - " + alt_tags[name] + " - ERROR\n";
	}

	// BC new group checker
	for (ck in chklist){
		if (ck.indexOf('[') == 0){ // is there a group item in the chklist?
			//alert("Found Group Checker");
			var vo=chklist[ck];
			if (vo.extra_valtype == "notblank"){ // is the group test nonblank
				var qty=vo.variableB; // how many nonblank do we need to be good
				var field_array = vo.variableA.split(',');
				//alert("Qty required: "+qty+"  Fields:"+field_array[0]+','+field_array[1]);
				for (var x=0;x<field_array.length ;x++){
					var gf = document.getElementsByName(field_array[x]);
					gf = gf[0];
					if (gf){
						//alert("field "+field_array[x]+ " value=("+gf.value+") isblank="+isBlank(gf.value));
						if (!isBlank(gf.value)||!isdisplayed(gf)){ // note: if not displayed assume they are not blank
							//alert("NOT BLANK");
							qty--;
						}
					}else{
						//alert("field "+field_array[x]+" not found");
					}
				}
				//alert("Qty: " + qty);
				if (qty>0){	// if qty > 0 then there are not enough filled out so report error and alttxt for elements
					for (var x=0;x<field_array.length ;x++){
						good[field_array[x]]=0;
						var s = ck;
						s=s.replace(/\[|\]/g,'');
						var qtys = 	(vo.variableB==1)?"one":vo.variableB; // one is so common write it in words
						alt_tags[field_array[x]]="At least "+qtys+" of these fields '"+s+"' must be completed to proceed.";
					}
				}
			}
			//return false;
		}
	}

	if(debug) alert(debugTxt);

	for (g in good){
		//alert("Name: "+g+"  Result: "+good[g]+"  Error txt: "+alt_tags[g]);
		if (good[g] == 0){
			DispError(g,alt_tags[g],type[g]);
			fail = 1;
		}
		else if(good[g] == 1){
			ClrError(g,type[g]);
		}
	}

	display_error_dialogue(errorTxt,fail,1);

	return (fail)?false:true;
}

function validate_single_field(e,chklist){
	var valObj = chklist[e.name];
	//alert(e.name);
	var result = 0;
	var alt_tag = '';
	var opt_flag = 0;
	if(valObj){
		var valtype = valObj.valtype;
		if(isdisplayed(e)){					
			if(valtype.indexOf('opt~') != -1){
				valtype = valtype.replace(/opt~/,'');
				opt_flag = 1;
			}

			var bits = validate_field_value(e,e.name,valObj,valtype,opt_flag,result);											// VALIDATE A SINGLE FORM ELEMENT
			result = bits[0];
			alt_tag = bits[1];
		}else{
			result=1; // hidden so say it is good													 
		}
	}
	if(result == 0)	DispError(e.name,alt_tag);
	else if(result == 1) ClrError(e.name);
	return result;
}




//#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
//SUB FUNCTIONS
//#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#

function valobj(valtype,extra_valtype,variableA,variableB){
	this.valtype = valtype;
	this.extra_valtype = extra_valtype;
	this.variableA = variableA;
	this.variableB = variableB;
}
																				  //USED FOR RADIO VALIDATION ONLY
function validate_field_value(element,element_name,valobj,valtype,optional,prevresult){

	var result = 0;
	var force = 0;
	var alt_tag = '';
	var value = '';

	//====[ REPLACEMENTS ]=============================================
	if(valtype != "wordcount" && valtype != "text"){
		value = element.value.replace(/ /g,'');
		if(valtype == "currency"){
			value = value.replace(/[^0-9]*/g,'');
		}else	if(valtype != "email" && valtype != "numeric"){
			value = value.replace(/\./g,'');
			value = value.replace(/\,/g,'');
		}
	}else{
		value = element.value;
	}

	//====[ TEXT VALIDATION ]=============================================
	if (valtype=="text"){
		if ((optional != -1) && (value == '') || (value != "") && (!isBlank(value))) {
			result=1;
		}else{
			alt_tag = "This is a required field";
		}
	}
	//====[ CHECKBOX ]==================================================
	else if (valtype=="checkbox"){
		result=1;
	}
	//====[ SELECT-ONE ]================================================
	else if (valtype=="select-one"){
		if(element_name == 'pole_size'){
			force = 1;
		}
		if (element.value != "-1" || (optional != -1 && value == '')){
			result = 1;
		}else{
			alt_tag = "Please select a value from the pulldown menu";
			result = 0;
		}
	}
	//====[ RADIO ]======================================================
	else if (valtype=="radio"){
		if (element.checked || (optional != -1 && value == '')){
			result=1;
		}else{
			alt_tag="Please select at least one of these options";
			result=prevresult;
		}
	}
	//====[ DATE ]=======================================================
	else if (valtype=="date"){
		if (dateRegxp.test(value) == true || (optional != -1 && value == '')){
			result=1; 
		}else{ 
			alt_tag = "Date format must be eg. dd/mm/yy";
		}
	}
	//====[ TIME ]======================================================
	else if (valtype=="time"){
		if (timeRegxp.test(value) == true || (optional != -1 && value == '')){
			result=1; 
		}else{ 
			alt_tag = "Time format must be in 24hr format eg. 16:00";
		}
	}
	//====[ NUMERIC ]===================================================
	else if (valtype=="numeric"){
		if (numericRegxp.test(value) == true || (optional != -1 && value == '')){
			result=1; 
		}else{
			alt_tag = "Should only contain digits eg. 1234";
		}
	}
	//====[ CURRENCY ]==================================================
	else if (valtype=="currency"){
		if (currencyRegxp.test(value) == true || (optional != -1 && value == '')){
			result=1; 
		}else{ 
			alt_tag = "Must contain a positive currency value eg. 10.99"; 
		}
	}
	//====[ POSTCODE ]=================================================
	else if (valtype=="postcode"){
		if (pcodeRegxp.test(value) == true || (optional != -1 && value == '')){
			result=1; 
		}else{ 
			alt_tag = "Ensure postcode is valid eg. BN27 2GH"; 
		}
	}
	//====[ TELEPHONE ]=================================================
	else if (valtype=="telephone"){
		value = value.replace(/ /g, '');
		if (telnoRegxp.test(value) == true || (optional != -1 && value == '')){
			result=1; 
		}else{ 
			alt_tag = "Ensure this is a valid UK phone number eg. 01424 753456"; 
		}
	}
	//====[ WEBSITE ADDRESS ]===========================================
	else if (valtype=="http"){
		if (urlRegxp.test(value) == true || (optional != -1 && value == '')){
			result=1;
		}else{
			alt_tag = "Please ensure you have entered a valid web address.";
		}
	}
	//====[ EMAIL ]=====================================================
	else if (valtype=="email"){
		//alert("RESULT: "+emailRegxp.test(value));
		if (emailRegxp.test(value) == true || (optional != -1 && value == '')){
			result=1;
		}else{ 
			alt_tag = "Ensure this is a valid email address eg. somebody@domain.co.uk"; 
		}
	}

	//****[ SITE SPECIFIC VALIDATION ]***********************************
	else if (valtype=="cm" || (optional != -1 && value == '')){
		value = value.replace(/cm/,'');
		if (numericRegxp.test(value) == true){
			result=1;
		}else{
			alt_tag = "This should be a value in cm eg. 100cm";
		}
	}
	//*******************************************************************

	//====[ NO VALIDATION TYPE FOUND ]===================================
	else{
		alert('Element ('+element_name+') has unknown validation type! ('+valtype+')');
		result=1;
	}

	//###########################################################################
	// EXTRA VALIDATION TYPE PROCESSING ---------------------------------------------------------------------
	//###########################################################################
	// can be used to run secondary validation on form objects or to format existing value eg. round down to the 
	// nearest multiple of a given number. 
	//
	// It takes two parameters from the validation object. varA + varB these can be used for whatever purpose

	if(valobj.extra_valtype != '' && result || force){
		var extra_val_type_array = valobj.extra_valtype.split(',');
		var varA = valobj.variableA;
		var varB = valobj.variableB;

		//alert("Variable A: "+varA+"  Variable B: "+varB);
		for(var cnt=0;cnt<extra_val_type_array.length;cnt++){
			var extravaltype = extra_val_type_array[cnt];
			//====[ MINIMUM ]=====================================================================
			if(extravaltype == "minimum"){
				if(value >= varA){
					alt_tag = " "+varA+" ";
					result=0;
				}
			}
			//====[ MAXIMUM ]=====================================================================
			else if(extravaltype == "maximum"){
				if(value <= varA){
					alt_tag = " "+varA+" ";
					result=0;
				}
			}
			//====[ MAXIMUM ]=====================================================================
			else if(extravaltype == "minmax"){
				if(value > varB){
					alt_tag = "Value entered must be less than "+varB+".";
					value = varB;
					result = 0;
				}else if(value < varA){
					alt_tag = "Value entered must be more than "+varA+".";
					value = varA;
					result = 0;
				}
				
			}
			//====[ ROUND TO NEAREST ]=====================================================================
			else if(extravaltype == "round"){
				value = parseInt((value/varA) * varA);
			}
			//====[ ROUNDUP ]=====================================================================
			else if(extravaltype == "round_up"){
				value = parseInt((value * varA) / varA);
			}
			//====[ ROUNDDOWN ]==================================================================
			else if(extravaltype == "round_down"){
				value = (value / varA) * varA;
			}
			//====[ CONFIRMATION EMAIL ADDRESS ]====================================================
			else if (extravaltype == "conf_email"){
				var confObj = document.getElementById(varA);
				//alert(confObj);
				if(confObj){
					result = (value == confObj.value)?1:0;
					alt_tag = (result)?"":"Please ensure both email address fields match before continuing";
				}
			}
		}
	}

	// SET ELEMENT VALUE TO VALIDATED DATA AFTER PROCESSING
	element.value = value;
	return [result,alt_tag];
}

//===========================================================

function ClrError(name,type){
	//alert("CLEAR ERROR FOR OBJ "+name+" Type: "+type);
	if(type == 'radio'){
		var obj = document.getElementById(name+'_err_div');
		clear_error(obj,"");
	}else{
		var objs = document.getElementsByName(name);
		for(idx in objs){
			var obj = objs[idx];
			clear_error(obj,"");
		}
	}
}

//===========================================================

function DispError(name,alt_tag,type){
	//alert("DISPLAY ERROR FOR OBJ "+name+" Type: "+type);
	if(type == 'radio'){
		var obj = document.getElementById(name+'_err_div');
		if(obj) hilite_error(obj,alt_tag);
	}else{
		var objs = document.getElementsByName(name);
		for(idx in objs){
			var obj = objs[idx];
			hilite_error(obj,alt_tag);
		}
	}
}

//===========================================================

function clear_error(obj,alt_tag){
	if(obj.style) obj.style.backgroundColor = "";
	obj.backgroundColor = "";
	if(alt_tag){
		obj.title = alt_tag;
		obj.alt = alt_tag;
	}
}

//===========================================================

function hilite_error(obj,alt_tag){
	if(obj.style) obj.style.backgroundColor = "#F7C4D9";
	obj.backgroundColor = "#F7C4D9";
	if(alt_tag){
		obj.title = alt_tag;
		obj.alt = alt_tag;
	}
}

//===========================================================

function display_error_dialogue(error,fail,scroll){
	var errorDivObj = document.getElementById('form_error');
	if(errorDivObj){
		if(scroll) window.scrollTo(0,320);
		var display = (fail)?'block':'none';
		errorDivObj.style.display = display;
		errorDivObj.innerHTML = error;
	}
}

//===========================================================

function isBlank(s){  //BC 2006-12-05
	if (s == ''){return true}
	return !notblankRegxp.test(s);
}

//===========================================================

function isdisplayed(node){

	//This function is used to see if an INPUT is currently being displayed
	// ONLY looking for a encompassing DIV with a style including display:block or display:none
	// test with something like this:
	//       alert(isdisplayed(document.getElementById("surname")))
	var n=0;
	var fnd=0;
	while (fnd==0){
		if(n>1) { node = node.parentNode; }
		if (node){
			if (node.style){
				if (node.style.display){
					//alert(node.style.display);
					if (node.style.display=='block'){
						fnd=0;
						//return true;
					}
					if (node.style.display=='none'){
						fnd=1;
						//return false;
					}
				}
			}
		}else{
			fnd=3;
		}
		if (n>20){
			return true;
		}
		n++;
	}
	if(fnd==1){
		return false;
	}
	if(fnd==0||fnd==3){
		return true;
	}
}