// Verify Form 3
// Author: 			Scott Jackman
// Original: 		14/2/07
// Previous Update:	6/1/10
// Last Update:		4/2/11 (added 'NOTVALID') flag
/////////////////////////////////////////////////////////////////////////////////
//
//		Mark fields in the form you want to verify by adding to the class attribute, "VF" plus any combination of the following letters:
//		MANDATORY	- mandatory field
//		EMAIL 		- correct email address format
//		NUMBER		- numerals only
//		INTEGER		- whole unsigned only
//		ALPHA		- alpha only
//		PHONE		- allows the inclusion of brackets () and + common in phone numbers
//		DEPENDANT	- dependant field set - at least one must be chosen (eg radio buttons)
//
//		NOTVALID	- simply flags any field to throw an error regardless of it's value 
//		CHECKING	- same as invalid, but can be used to temporarliy stop form being submitted if an ajax call is in progress
//
//		The "title" attribute of the input field can be used to define a message that will be shown if the field does not verify
//
//		Examples:
//			<input type="text" name="Name" value="" class="input MANDATORY" title="Please fill in your name">
//			(mandatory field)
//
//			<input type="text" name="Email" value="" class="input EMAIL" title="Please enter a valid email address">
//			(optional field that if filled out, must be a valid email)
//
//			<input type="text" name="Phone" value="" class="input MANDATORY PHONE">
//			(mandatory field, and can contain only phone number - (numbers, brackets and spaces))
//
//		
//
//
/////////////////////////////////////////////////////////////////////////////////
function verifyform(check_scope) {
// note: when disp is true the class of the field will NOT be changed
// note: if 'output' is given (this will be an object), the script will output any messages to this object instead of an alert
var error = "";
var chkFlds = ["input","select","textarea","checkbox"];
var dependencies = new Object();
// loop thru field types - chkFlds
for (var j=0; j < chkFlds.length; j++) {
	// get all the fields for the current type into array
	var frmObjs = check_scope.getElementsByTagName(chkFlds[j]);
	// loop thru type array
	for (var i=0; i < frmObjs.length; i++) {
		var displayname = (frmObjs[i].title == "")?frmObjs[i].name:frmObjs[i].title;
		var type = frmObjs[i].type;
			// if not resetting, get value and alt from current object
			var fldVal = frmObjs[i].value;
			var fldClassName = frmObjs[i].className;
			var thiserror = 0;
			if (frmObjs[i].disabled !== true) {
				var fldVfy = fldClassName;// .substr(fldClassName.indexOf('VF')+2);
				// Check for INVALID field (arbitrary flag that can be set on any field to invalidate form)
				if (fldVfy.indexOf("INVALID")!=-1) {
					verify_flag_error(frmObjs[i]);
					error += "   Required: "+displayname+'\n';
					thiserror = 1;
					}
				// Check for empty mandatory fields - MANDATORY
				if (fldVal == "" && fldVfy.indexOf("MANDATORY")!=-1) {
					verify_flag_error(frmObjs[i]);
					error += "   Required: "+displayname+'\n';
					thiserror = 1;
					}
					
				// Check for invalid flag - NOTVALID
				if (fldVfy.indexOf("NOTVALID")!=-1) {
					verify_flag_error(frmObjs[i]);
					error += "   Invalid field: "+displayname+'\n';
					thiserror = 1;
					}
				// Check for checking flag - CHECKING
				if (fldVfy.indexOf("CHECKING")!=-1) {
					verify_flag_error(frmObjs[i]);
					error += "   Wait! Checking field: "+displayname+'\n';
					thiserror = 1;
					}
					
				// check for unticked checkbox - MANDATORY
				if (type == "checkbox" && fldVfy.indexOf("MANDATORY")!=-1 && frmObjs[i].checked !== true) {
					verify_flag_error(frmObjs[i]);
					error += "   Unticked checkbox: "+displayname+'\n';
					thiserror = 1;
					}
					
				// Check for non numeral - NUMBER
				var numerror = 0;
				var numerals = "-0123456789. \r\n";
				if (fldVal !== "" && fldVfy.indexOf("NUMBER")!=-1) {
					for (k=0; k<fldVal.length; k++) {
						var ch = fldVal.charAt(k);
						var x = numerals.indexOf(ch);
						if (x == -1) {
							numerror = 1;
							} 
						}
					if (numerror == 1) {
						verify_flag_error(frmObjs[i]);
						error += "   Numbers only: "+displayname+'\n';
						thiserror = 1;
						}
					}
				// Check for whole unsigned - INTEGER
				var numerror = 0;
				var numerals = "0123456789 \r\n";
				if (fldVal !== "" && fldVfy.indexOf("INTEGER")!=-1) {
					for (k=0; k<fldVal.length; k++) {
						var ch = fldVal.charAt(k);
						var x = numerals.indexOf(ch);
						if (x == -1) {
							numerror = 1;
							} 
						}
					if (numerror == 1) {
						verify_flag_error(frmObjs[i]);
						error += "   Integers only: "+displayname+'\n';
						thiserror = 1;
						}
					}
		
				// Check for non phone number - PHONE
				var phoneerror = 0;
				var numerals = "0123456789.+() \r\n";
				if (fldVal !== "" && fldVfy.indexOf("PHONE")!=-1) {
					for (k=0; k<fldVal.length; k++) {
						var ch = fldVal.charAt(k);
						var x = numerals.indexOf(ch);
						if (x == -1) {
							phoneerror = 1;
							} 
						}
					if (phoneerror == 1) {
						verify_flag_error(frmObjs[i]);
						error += "   Phone numbers only: "+displayname+'\n';
						thiserror = 1;
						}
					}
		
		
				// Check for non alpha - ALPHA
				var alphaerror = 0;
				var numerals = "0123456789. ";
				if (fldVal !== "" && fldVfy.indexOf("ALPHA")!=-1) {
					for (k=0; k<fldVal.length; k++) {
						var ch = fldVal.charAt(k);
						var x = numerals.indexOf(ch);
						if (x !== -1) {
							alphaerror = 1;
							} 
						}
					if (alphaerror == 1) {
						verify_flag_error(frmObjs[i]);
						error += "   Numbers not allowed: "+displayname+'\n';
						thiserror = 1;
						}
					}
				// Check for password confirmation - PASSCHECK
				if (fldVfy.indexOf("PASSCHECK")!=-1) {
					var p1 = document.getElementById('P1');
					var p2 = document.getElementById('P2');
					//if(p1.value != '' && p2.value != ''){ // dont need this check cos if they are both blank, then they match!
						if(p1.value != p2.value){
							error += "   Password doesn't match! Please retype.\n";
							//p2.value = '';
							verify_flag_error(p2,"Password doesn't match! Please retype." );
							thiserror = 1;
							} else {
							verify_unflag_error(p2);	
							}
						//}
		
					}
		
		
				// Check for incorrect email address - EMAIL
				if (fldVal !== "" && fldVfy.indexOf("EMAIL")!=-1) {
					var at =  fldVal.indexOf("@");
					var dot = fldVal.indexOf(".");
					if (at==-1 || dot==-1) {
						verify_flag_error(frmObjs[i]);
						error += "   Incorrect email address: "+displayname+'\n';
						thiserror = 1;
						}
					}
					
					
				// Check for dependant field - DEPENDANT - a field set where at least one field must be filled out
				if (fldVfy.indexOf("DEPENDANT")!=-1) {
					var did = fldVfy.substr(fldVfy.indexOf("DEPENDANT"),2);
					if(!dependencies[did]){
						dependencies[did] = new Object();
						dependencies[did]['verified'] = false;
						dependencies[did]['fieldlist'] = '';
						dependencies[did]['msg'] = (type == 'radio' || type == 'checkbox')?'   Please choose a '+ displayname +':\n':'   At least one of these fields must be completed:\n';
						}
					var unchecked = ((type == "checkbox" || type == "radio")&& frmObjs[i].checked == false)?true:false;
					if(fldVal == '' || unchecked){
						if(type=="radio"){
							dependencies[did]['fieldlist'] += '     - '+fldVal+'\n';
							} else {
							dependencies[did]['fieldlist'] += '     - '+displayname+'\n';
							}
						} else {
						dependencies[did]['verified'] = true;
						}
					}				
			// If field ok, set colour to normal
				if (thiserror!=1) {					
					verify_unflag_error(frmObjs[i]);
					}
				}
			}
		}
	// loop through dependencies object
	for(var d in dependencies){
		if(!dependencies[d]['verified']){
			thiserror = 1;
			error += dependencies[d]['msg'];
			error += dependencies[d]['fieldlist']+'\n';
			}
		}


// If errors, give error alert, otherwise, submit the form
	if (!error == "") {
		//alert(error);
		// the following only works with prototype / scriptaculous library
		//////////////////////////////////////////////////////////////////
		
		
		// first, in case the form does not have an ID, we need to give it one! 
		if(!check_scope.id){
				//We'll just assign the id-less form an id of it's name (doesn't matter if none) plus a random number preceeded by an underscore
				check_scope.setAttribute('id','form_'+Math.floor(Math.random()*100));
				}
		try{
		$$('#'+check_scope.id+' div.error_message').each(function(e){
											  if(e.getStyle("position") == 'absolute'){
												  $(e).hide().appear();
												  } else {
												  Effect.BlindDown(e.id, {duration: 0.3});
												  }
											  // let's add a listener to each error field so that when it's focused on the next time,
											  // the error message will vanish
											  $(e).previous().observe('focus', function(e){
												//e.target.removeClassName('VERIFY_ERROR');
												e.target.next().fade();						 	
											  	});
											  });
            // scroll to the first error element on the page
            try{
            Effect.ScrollTo($$('#'+check_scope.id+' .VERIFY_ERROR')[0],{ duration:'0.2', offset:-40 });
            } catch(sce){
                // scroll didn't work but let's not let that stop us
            }
		} catch(e) {
			// this will run if prototype not present or if there was some other prototype error
			alert(error);
			}
		return false;
		} else {
		return true;
		}
}
function verify_flag_error(obj,msg){
	var cc = obj.className;
	if(cc.indexOf('VERIFY_ERROR') == -1){
		obj.className = obj.className+" VERIFY_ERROR";
		var em = document.createElement('div');
		em.className = "error_message";
		em.setAttribute('style', 'display:none;');
		em.setAttribute('id', 'errmsg_'+obj.name);
		var c = obj;
		while(c = c.nextSibling){
			if(c.className){
				if(c.className.indexOf('error_message') != -1){
					obj.parentNode.removeChild(c);
				}
			}
		}
		if(msg != null){
			em.appendChild(document.createTextNode(msg));
			} else {
			em.appendChild(document.createTextNode(obj.title));
			}
		obj.parentNode.appendChild(em);
	}
}
function verify_unflag_error(obj){
	var cc = obj.className;
	if(cc.indexOf('VERIFY_ERROR') != -1){
		obj.className = cc.replace("VERIFY_ERROR","");
		var c = obj;
		while(c = c.nextSibling){
            try{
			if(c.className.indexOf('error_message') != -1){
				obj.parentNode.removeChild(c);
			}
            } catch(err){
                //
            }
		}
	}
}



