//alert("hello - I am correctly embedded");
// Form validation pseudoclass by Anthony Buckland, Binary Refinery/Mnemonic 2007
// How to use:
// Create a HTML page with a form. Ensure that the form has a class attribute "br_validate". Each
// item in the form should have either a <label> or reside in a container (div, td etc etc)  as the 
// error messages are appended to the parent of the offending element- and if there is no parentNode;
// the error message will be attached to the form tag, making the layout somewhat bizarre.
//
// The validation is automatically attched to the submit event; and if required, to the onblur event of elements.
// It may also be called via BinaryRefineryFormValidation.fFullValidation(null, 'FORM_ID' );
//
// Usage:
// ---------------------------------------------
//<style type="text/css" >
//	 .invalid {
//		background-color:#FF0000;
//		border:1px solid #666666;
//		}
//	.infomation {
//		background-color:#FFCC99;
//		border: 1px solid #333333;
//		width:300px;
//		}
// </style>
//---------------------------------------------
//  <label for="EL_ID" >Text <ELEMENT id="EL_ID" name="EL_ID" title="DESCRIPTIVE ERROR MESSAGE" class="BR_CLASS"  /></label>
//---------------------------------------------
// To ensure validation of elements, use the following classes (BR_CLASS) on the element:
// Text, textarea	 : 	br_text
//  Numeric 			: 	br_number
//  Select boxes		: 	br_select
//  Radio groups	: 	br_radio (NB- this class should be applied to a <fieldset> element surrounding the whole radio group - NOT to 
//								  			   the radio buttons themselves
//											   Ensure that this fieldset has an id attribute. It will also work on single radio buttons, without the fieldset
//											   but with teh class applied to the single radio button)
//  Checkbox			: 	br_checkbox
//  File 					: 	br_file
//  Password			: 	br_password ( makes sure all elements with class "br_password" are identical )
//  Email address	:	br_email
//  RSA ID number	: 	br_ID
// ---------------------------------------------
// Setup info- in a javascript object named brConfig, created after this file is included 
// 
//  errorMode		: possible values: "text", "alert"
//  errorClassName : name of the CSS class that will be applied to elements that are invalide ( include a bg color and border )
//  errorInfoClassName : name of the class to apply to the errorElementType
//  errorElementType : eg "div", "span", "b", etc - any element that can hold text
//  validateOnBlur : boolean to decide if we validte a single element onblur
//  regExObjects : modifiable objects to validate against
//---------------------------------------------
//
//
var brConfig={
		errorMode:"text", 
		errorClassName:"invalid",
		errorInfoClassName:"infomation",
		errorElementType:"p",
		validateOnBlur:true,
		regExObjects: {
				br_text:new RegExp(/^[\w\W_-]+$/i)
				, br_number:new RegExp(/^[0-9]+$/i)
				, br_email:new RegExp(/^[\w_-]+(\.[\w_-]+)*@[\w_-]+(\.[\w_-]+)*\.\w{2,4}$/i)
				, br_file:new RegExp(/(\.)[A-Z0-9]{3,4}$/i )
				}
		}

var BinaryRefineryFormValidation=br= {
	init : function() {
			// default values...
		//alert("init called")
		br.errorMode=brConfig.errorMode;
		br.errorClassName=brConfig.errorClassName;
		br.errorElementType=brConfig.errorElementType;
		br.validateOnBlur=brConfig.validateOnBlur;
		br.errorInfoClassName=brConfig.errorInfoClassName;
		br.regExObjects=brConfig.regExObjects;
		//if the user pressed "back", the submit is disabled...?
		// get all forms with class br_validate
		var a = br.getElementsByClassName(document, "br_validate")
		// add validation to all forms with the class
		for(var i=0; i<a.length; a++) {	
			br.addSubmitEvent(a[i], br.fFullValidation)
			if(br.validateOnBlur==true) {
				// to each element within the form.
				var b= br.getElementsByClassNamePartial(a[i],  new RegExp(/^(br_)/i) )
				for(var j=0; j<b.length; j++) {	
						br.addBlurEvent(b[j], br.delegate(br, br.fSingleValidation, a[i],b[j], b[j].className));
					}	
			}	
		}				
	},

	fSingleValidation : function(form, element, type) {
		switch(type){
			case "br_text" : br.fValidateRegex(form, element, br.regExObjects[type] ); break; 
			case "br_number" : br.fValidateRegex(form, element, br.regExObjects[type] ); break;
			case "br_email" : br.fValidateRegex(form, element, br.regExObjects[type] ); break; 
			case "br_file" : br.fValidateRegex(form, element, br.regExObjects[type] ); break; 
			case "br_select" : br.fValidateSelect(form,element);break;
			case "br_radio" : br.fValidateRadio(form,element);break;
			case "br_checkbox" : br.fValidateCheckbox(form,element);break;
		}
		
	},
	
	fFullValidation : function () {		
		/* bit of a hack really! - submit passes one arguement, a click on a link to validate must pass 2 : null and the form id */
		if(arguments.length==1) {
				formElement=this
			} else {
				formElement=document.forms[arguments[1]];
			}
		this.bValidForm=true;
		var a=[]
		
		// Prevent double clicks on the submit	
		a = br.getElementsByAttribute(formElement, "input" , "type", "submit")
		for(var i=0; i<a.length; i++) {
			a[i].disabled=true;
			setTimeout('BinaryRefineryFormValidation.showSubmit()', 500)  
		}
	

		// get all required basic elements.
		for(var s in br.regExObjects) {
			//alert("testing " + s)
			a = br.getElementsByClassName(formElement, s);
			for(var i=0; i<a.length; i++) {	
				br.fValidateRegex(formElement, a[i], br.regExObjects[s] );
			}
		}
		// now, more complex elements
		a = br.getElementsByClassName(formElement, "br_select")
		for(var i=0; i<a.length; i++) {	
			br.fValidateSelect(formElement,a[i]);
		}	
		
		// radio groups - MUST be in "individual" fieldsets - one per group, with class "br_radio" and an ID attribute
		var a = br.getElementsByClassName(formElement, "br_radio");
		for (var i = 0; i<a.length; i++) {
			br.fValidateRadio(formElement,a[i]);
		}
	
		// checkbox
		a = br.getElementsByClassName(formElement, "br_checkbox")
		for(var i=0; i<a.length; i++) {	
			br.fValidateCheckbox(formElement,a[i]);
		}

		// alert("form is " + this.bValidForm);
		return this.bValidForm;
	
	
		/*
		// Passwords - all elements with the class "br_password" must match 
		a = br.getElementsByClassName(this, "br_password")
		for(var i=0; i<a.length; i++) {	
			// first clear any error messages and CSS...
			br.fSetCssClass("remove",a[i], br.errorClassName);
			var el=document.getElementById(a[i].id+"_errMsg")
			if(el!="undefined" && el!=null ) {
				try {
					a[i].parentNode.removeChild(el)
				}
				catch(err) {}
			}
			// get first password's value
			var sInit=a[0].value
			// now validate it
			if(a[i].value=="" || a[i].value!=sInit) {
				// set the CSS class for the element
				br.fSetCssClass("add", a[i], br.errorClassName);	
				if(br.errorMode=="alert") {
					alert((a[i].title != "undefined" && a[i].title != "") ? (a[i].title) : ("Please complete all required fields."));
					return false;
					} else {
					// set the message (if required) in a <b>
					var el = document.createElement(br.errorElementType);
					el.setAttribute("id",a[i].id+"_errMsg");
					el.className=br.errorInfoClassName;
					el.innerHTML=( a[i].title!="undefined" &&  a[i].title!="" ) ?  (a[i].title) : (" - This field is required.") ;
					a[i].parentNode.appendChild(el)
					// -------------------------------------
					// set on focus event...
					a[i].onfocus=function(){
						BinaryRefineryFormValidation.fSetCssClass("remove", this, br.errorClassName);
						var el=document.getElementById(this.id+"_errMsg")
						if(el!="undefined" && el!=null ) {
						try {
							this.parentNode.removeChild(el)
							}
							catch(err) {}
							}
						}
					}
				// set the bValidForm
				bValidForm=false;
			}
		}

		// ********************************************************************** //
		// TO DO:  textareas? is there any point?
		// ********************************************************************** //

	
		// ID numbers
		
		a = br.getElementsByClassName(this, "br_ID")
		for(var i=0; i<a.length; i++) {	
			// first clear any error messages and CSS...
			br.fSetCssClass("remove",a[i], br.errorClassName);
			var el=document.getElementById(a[i].id+"_errMsg")
			if(el!="undefined" && el!=null ) {
				try {
					a[i].parentNode.removeChild(el)
				}
				catch(err) {}
			}
			// now validate it
			if(!br.fIsValidID(a[i].value)) {
				// set the CSS class for the element
				br.fSetCssClass("add", a[i], br.errorClassName);	
				if(br.errorMode=="alert") {
					alert((a[i].title != "undefined" && a[i].title != "") ? (a[i].title) : ("Please complete all required fields."));
					return false;
					} else {
					// set the message (if required)
					var el = document.createElement(br.errorElementType);
					el.setAttribute("id",a[i].id+"_errMsg");
					el.className=br.errorInfoClassName;
					el.innerHTML=( a[i].title!="undefined" &&  a[i].title!="" ) ?  (a[i].title) : (" - This field is required and must be a valid South African ID number.");
					a[i].parentNode.appendChild(el)
					// -------------------------------------
					// set on focus event...
					a[i].onfocus=function(){
						BinaryRefineryFormValidation.fSetCssClass("remove", this, br.errorClassName);
						var el=document.getElementById(this.id+"_errMsg")
						if(el!="undefined" && el!=null ) {
						try {
							this.parentNode.removeChild(el)
							}
							catch(err) {}
							}
						}
					}
				// set the bValidForm
				bValidForm=false;
			}
		}
		
		*/
		
		// Finally ..................... 	

		// return bValidForm;
	},

 //------------------------------------------------------------------------------------------------------------------------------------------
 
 	clear : function(el,defaultValue) {
        // alert(el.value);
		if(el.value.toLowerCase()==defaultValue.toLowerCase()) {
			el.value="";
		}	
	},
	
	
 
 
	fValidateRegex : function(form, element,  re) {
			// first clear any error messages and CSS...
			br.fSetCssClass("remove",element, br.errorClassName);
			var el=document.getElementById(element.id+"_errMsg")
			if(el!="undefined" && el!=null ) {
				try {
					element.parentNode.removeChild(el)
				}
				catch(err) {}
			}
			// now validate it
			// alert("regex result " + re.test(element.value)); 
			if(!re.test(element.value)) {
				// set the CSS class for the element
				br.fSetCssClass("add", element, br.errorClassName);	
				if(br.errorMode=="alert") {
					alert((element.title != "undefined" && element.title != "") ? (element.title) : ("Please complete all required fields."));
					return false;
					} else {
					// set the message (if required)
					var el = document.createElement(br.errorElementType);
					el.setAttribute("id",element.id+"_errMsg");
					el.className=br.errorInfoClassName;
					el.innerHTML=( element.title!="undefined" &&  element.title!="" ) ?  (element.title) : (" - This field is required.") ;
					element.parentNode.appendChild(el);	
					// -------------------------------------
					// set on focus event...
					element.onfocus=function(){
						// alert("focussed on me: " + this.id);
						br.fSetCssClass("remove", this, br.errorClassName);
						var el=document.getElementById(this.id+"_errMsg")
						
						if(el!="undefined" && el!=null ) {
						try {
							this.parentNode.removeChild(el)
							}
							catch(err) {alert("error: " + err.toString())}
							}
						}
					}
				// set the bValidForm
				form.bValidForm=false;
			}
	},
	
	fValidateSelect : function(form, element, multiple) {
		// first clear any error messages and CSS...
			br.fSetCssClass("remove",element, br.errorClassName);
			var el=document.getElementById(element.id+"_errMsg")
			if(el!="undefined" && el!=null ) {
				try {
					element.parentNode.removeChild(el)
				}
				catch(err) {}
			}
			// now validate it
			// alert(element.id + " is multiple? " + element.multiple);
			
			var b=true;
			if(!element.multiple) {
				if(element[element.selectedIndex].value=="undefined" || element[element.selectedIndex].value=="") {
					b=false;
				}
			} else {
				// must be a multiple select	
				var arSelected=[]
				for (var j = 0; j < element.options.length; j++){
					if(element.options[j].selected) {
						arSelected.push(element.options[j].value);
					}
					if(arSelected.length<1) { b=false; }
				}
			}
			// now validate it
			if(!b) {	
				// set the CSS class for the element
				br.fSetCssClass("add", element, br.errorClassName);	
				if(br.errorMode=="alert") {
					alert((element.title != "undefined" && element.title != "") ? (element.title) : ("Please complete all required fields."));
					return false;
					} else {
					// set the message (if required) in a <b>
					var el = document.createElement(br.errorElementType);
					el.setAttribute("id",element.id+"_errMsg");
					el.className=br.errorInfoClassName;
					el.innerHTML=( element.title!="undefined" &&  element.title!="" ) ?  (element.title) : (" - Please make a selection.");
					element.parentNode.appendChild(el)
					// -------------------------------------
					// set on focus event...
					element.onfocus=function(){
						BinaryRefineryFormValidation.fSetCssClass("remove", this, br.errorClassName);
						var el=document.getElementById(this.id+"_errMsg")
						if(el!="undefined" && el!=null ) {
						try {
							this.parentNode.removeChild(el)
							}
							catch(err) {}
							}
						}
					}
				// set the bValidForm
				form.bValidForm=false;
			}	
	},
	
	fValidateRadio : function(form, element) {
			br.fSetCssClass("remove", element, br.errorClassName);
			var el = document.getElementById(element.id+"_errMsg");
			if (el != "undefined" && el != null) {
				try {
					element.removeChild(el);
				}
				catch(err) {}
			}
			var aRd = element.getElementsByTagName("input");
			var b = false;
			
			for (var j = 0; j<aRd.length; j++) {
				if (aRd[j].getAttribute("type") == "radio" && aRd[j].checked) {
					b = true;
				}
			}
			if (b != true) {
				br.fSetCssClass("add", element, br.errorClassName);
				if (br.errorMode == "alert") {
					alert((element.title != "undefined" && element.title != "") ? (element.title) : ("Please complete all required fields."));
					//return false;
					} else {
					// set the message (if required)
					var el = document.createElement(br.errorElementType);
					el.setAttribute("id", element.id+"_errMsg");
					el.className=br.errorInfoClassName;
					el.innerHTML = (element.title != "undefined" && element.title != "") ? (element.title) : ("Please make a selection.");
					element.parentNode.appendChild(el);
					// -------------------------------------
					// set on focus event...for each radio button
					element.onclick=function(){
						BinaryRefineryFormValidation.fSetCssClass("remove", this, br.errorClassName);
						var el=document.getElementById(this.id+"_errMsg")
						if(el!="undefined" && el!=null ) {
						try {
							this.parentNode.removeChild(el)
							}
							catch(err) {}
							}
						}
					}
				// set the bValidForm
				form.bValidForm = false;
			}
	},
	
	fValidateCheckbox : function(form, element) {
		// first clear any error messages and CSS...
			br.fSetCssClass("remove",element, br.errorClassName);
			var el=document.getElementById(element.id+"_errMsg")
			if(el!="undefined" && el!=null ) {
				try {
					element.parentNode.removeChild(el)
				}
				catch(err) {}
				}
			// now validate it
			if(!element.checked) {
				// set the CSS class for the element
				br.fSetCssClass("add", element, br.errorClassName);	
				if(br.errorMode=="alert") {
					alert((element.title != "undefined" && element.title != "") ? (element.title) : ("Please complete all required fields."));
					return false;
					} else {
					// set the message (if required)
					var el = document.createElement(br.errorElementType);
					el.setAttribute("id",element.id+"_errMsg");
					el.className=br.errorInfoClassName;
					el.innerHTML=( element.title!="undefined" &&  element.title!="" ) ?  (element.title) : (" - This field is required.");
					element.parentNode.appendChild(el)
					// set on focus event...
					element.onfocus=function() {
						br.fSetCssClass("remove", this, br.errorClassName);
						var el=document.getElementById(this.id+"_errMsg")
						if(el!="undefined" && el!=null ) {
							try {
							this.parentNode.removeChild(el)
							}
							catch(err) {}
							}
						}
					}
				// set the bValidForm
				form.bValidForm=false;
			}
		},
	
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
	/* --------------------------------------------------------------------------- */
	// Utilities 
	/* --------------------------------------------------------------------------- */
	showSubmit : function() {
			a = BinaryRefineryFormValidation.getElementsByAttribute(document, "input" , "type", "submit")
			for(var i=0; i<a.length; i++) {
				a[i].disabled=false;
				}	
		},

	getElementsByAttribute : function (obj, strTagName, strAttributeName, strAttributeValue) {
		var arrElements = (strTagName == "*" && obj.all)? obj.all : obj.getElementsByTagName(strTagName);
		var arrReturnElements = new Array();
		var oAttributeValue = (typeof strAttributeValue != "undefined")? new RegExp("(^|\\s)" + strAttributeValue + "(\\s|$)", "i") : null;
		var oCurrent;
		var oAttribute;
		for(var i=0; i<arrElements.length; i++){
			oCurrent = arrElements[i];
			oAttribute = oCurrent.getAttribute && oCurrent.getAttribute(strAttributeName);
			if(typeof oAttribute == "string" && oAttribute.length > 0){
				if(typeof strAttributeValue == "undefined" || (oAttributeValue && oAttributeValue.test(oAttribute))){
					arrReturnElements.push(oCurrent);
					}
				}
			}
		return arrReturnElements;
	}, 



	fIsEmail : function(s){
		var re=new RegExp(/^[\w_-]+(\.[\w_-]+)*@[\w_-]+(\.[\w_-]+)*\.\w{2,4}$/i);
		return re.test(s);
	},
	
	fIsValidID : function (iID) {
		var sR="";var sE="";var s="";var iO=0;var iE=0;var iC=0;var iTot=0;
		var reNum=/\b\d\d\d\d\d\d\d\d\d\d\d\d\d\b/
		if(!reNum.test(iID)) {return false;} 
		//
		sID=iID.toString();aID=sID.split("");
		for(i=0;i<=10;i+=2) {iO+=parseInt(aID[i]);}
		for(i=1;i<=11;i+=2) {sE+=(2*parseInt(aID[i])).toString();}
		aE=sE.split("");
		for(i=0;i<aE.length;i++) {iE+=parseInt(aE[i]);}
		iTot=parseInt(iO)+parseInt(iE);
		s=iTot.toString();a=s.split("");
		iC=10-(parseInt(a[1]));
		if(iC==10) iC=0;
		if(iC!=parseInt(aID[12])) {
			sR=false
			} else {
			sR=true
			}
		// The end..
		return sR;
	},

	getElementsByClassName : function(obj,className){
		var a=[];
		var re=new RegExp('(^| )'+className+'( |$)');
		var aAll=obj.getElementsByTagName('*');
		for(var i=0; i<aAll.length; i++) {
			if(re.test(aAll[i].className)){
				a.push(aAll[i]);	
			}
		}
		return a
	},
	
	getElementsByClassNamePartial : function(obj,regex){
		// alert("getting elements for " + obj.id + " with classname " + regex);
		var a=[];
		var re=regex;
		var aAll=obj.getElementsByTagName('*');
		for(var i=0; i<aAll.length; i++) {
			if(re.test(aAll[i].className)){
				a.push(aAll[i]);	
			}
		}
		return a
		
	},
	
	addSubmitEvent : function(form, func) { 
		// NB, all functions called here must return true or false.
		var oldSubmit = form.onsubmit; 
		//alert("oldSubmit is " + oldSubmit);
		if (typeof oldSubmit != 'function') { 
			form.onsubmit = func; 
			} else { 
			form.onsubmit = function() { 
			oldSubmit() ; 
			func() 
			return false; 
			} 
		} 
		return false;
	}, 
	
	addBlurEvent : function(el, func) { 
		// NB, all functions called here must return true or false.
		var oldBlur = el.onblur; 
		//alert("oldSubmit is " + oldSubmit);
		if (typeof oldBlur != 'function') { 
			 el.onblur= func; 
			 
			} else { 
			 el.onblur = function() { 
				oldBlur() ; 
				func() 
				return false; 
				} 
			} 
		 // alert(el + " onblur is now " +  el.onblur);
		return false;
	}, 
	
	fSetCssClass : function(action,obj,class1,class2) {
		switch(action) {
		case('swap') :
			obj.className=!br.fSetCssClass('check', obj,class1) ? obj.className.replace(class2,class1) : obj.className.replace(class1,class2);
			break;
		case('add') :
			if(!br.fSetCssClass('check',obj,class1)) {
				obj.className+=obj.className ? ' ' + class1 : class1;
				}
			break;
		case('remove') :
			var s=obj.className.match(' ' + class1) ? ' ' + class1 : class1;
			obj.className=obj.className.replace(s,'');
			break;
		case('check') :
			return new RegExp('\\b'+class1+'\\b').test(obj.className);
			break;
		}
	},
	
	delegate: 	function ( that, thatMethod ) {
   		 if(arguments.length > 2) 	{
      		var _params = [];
     		 for(var n = 2; n < arguments.length; ++n) { _params.push(arguments[n]); }
     		 return function() { 
					return thatMethod.apply(that,_params); 
			 	}
    	} else {
      		return function() { return thatMethod.call(that); }
		}
 	 }
	
}	
/* By Simon Wilson; http://simonwillison.net/2004/May/26/addLoadEvent/ */
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}
/*  example useage....
addLoadEvent(nameOfSomeFunctionToRunOnPageLoad);
addLoadEvent(function() {
  // more code to run on page load 
});
*/
addLoadEvent(BinaryRefineryFormValidation.init)

