
// -------------------------------------------------------------------
// Madgex Limited
// Copyright (c) 2007 Madgex Limited. All Rights Reserved.
// Unobtrusive form validation v1.0 
// James Wragg
// 18 June 2007
// -------------------------------------------------------------------
 
 // Requires yahoo.js, common.js
 
 
	// trim whitespace from strings
	if(!String.trim){		
		String.prototype.trim=function(){ 
			return this.replace(/^\s*|\s*$/g,'');
		};
	}
	
	// IE does not handle indexOf on arrays.
	if(!Array.indexOf){
	    Array.prototype.indexOf = function(obj){
	        for(var i=0; i<this.length; i++){
	            if(this[i]==obj){
	                return i;
	            }
	        }
	        return -1;
	    };
	}


	
	
	// main FormValidator hub 
	// All modules are registered here, and validation is launched from here.
	var FormValidator = {
		
		name:'Madgex - Unobtrusive form validation',
		version: '1.0',
		modules: [], 
		
		config: {
			"findFormClass": "validate-me",
			"debug": false
		},

		Init: function(test){
		    
		    // Form validation controller
			if ( document.getElementById ) {

			    // go find the forms to validate 
				var formColl = getElementsByClassName( document.body, "form", FormValidator.config.findFormClass );

				for ( var x = 0; x < formColl.length; x++ ){

					if ( FormValidator.config.debug ){
					    var debugBtn = document.createElement("input");
					    debugBtn.type = "button";
					    debugBtn.value = "Validation only";
					    formColl[x].appendChild(debugBtn); 
					    addEvent(debugBtn, "click", FormValidator.ValidateForm, false);
					}
					
					addEvent(formColl[x], "submit", FormValidator.ValidateForm);
				}
			}
			
		},
		
		StopEvent: function (e) {
			e || window.event;
			if (e.stopPropagation) {
				e.stopPropagation();
				e.preventDefault();
			}

			/*@cc_on@*/
			/*@if(@_win32)
			e.cancelBubble = true;
			e.returnValue = false;
			/*@end@*/

			return false;
		},
        		
		Register: function( name ){	
			if ( FormValidator.modules.indexOf(name) == -1 && name !== null ) {
				// module is not already registered, go register it
				index = (FormValidator.modules.push(name) - 1);
				
				if ( FormValidator.config.debug )
				    console.log("Registered ", name, " as index: ", index);
				    
				return index;
			}

		},

		ValidateForm: function( e ) {

			// have we been passed the form node or the click event?
			if( !(formNode = e.target || e.srcElement) )
				formNode = e;

			if ( FormValidator.config.debug)
				formNode = formNode.parentNode;
				
			var isValidated = true;			
			
			for ( var y = 0; y < FormValidator.modules.length; y++ ){
				FormValidator.modules[y].Reset();

				if ( !(result = FormValidator.modules[y].Validate( formNode )) ){
					isValidated = false;
				}
				
				if ( FormValidator.config.debug ){
					if ( window.console){
						console.info("Module " + FormValidator.modules[y].name + " - " + result);
					}else{
						alert("Module " + FormValidator.modules[y].name + " - " + result);
					}
				}
			}
			
			if( !Boolean(isValidated) )
				return FormValidator.StopEvent(e);
			
			return true;
			
		},
		
		AddError: function( elem, module ){
			var errNodeId = module.name + elem.id;
			//var errNodeId = elem.id + "-ValidationErr";
	
			if ( !document.getElementById(errNodeId) ) {
				var errorMsg = document.createElement('span');
				errorMsg.setAttribute("id", errNodeId);
				errorMsg.className = 'pageError';
				errorMsg.innerHTML = module.config.ErrorTxt;
				elem.parentNode.appendChild(errorMsg);
				//elem.parentNode.parentNode.insertBefore(errorMsg, elem.parentNode.nextSibling);
				
				module.Errors.push(elem);
			}
		},
		
		RemoveError: function( elem, module ){
			var errNodeId = module.name + elem.id;
			//var errNodeId = elem.id + "-ValidationErr";
			
			if ( errorNode = document.getElementById(errNodeId) )
				errorNode.parentNode.removeChild(errorNode);
					
			for ( var x = 0; x < module.Errors.length; x++ ){
				if ( module.Errors[x].id == elem.id )
					module.Errors.splice(x, 1);
			}
		},
		
		AttachEvent: function( elem, ModuleIndex, type ){

			if ( type ) {
				addEvent(elem, type, FormValidator.modules[ModuleIndex].ValidateItem, false);
			}else if ( elem.nodeName.toLowerCase() == "select" ){
				addEvent(elem, 'change', FormValidator.modules[ModuleIndex].ValidateItem, false);
			}else if ( elem.nodeName.toLowerCase() == "input" ){
				addEvent(elem, 'keyup', FormValidator.modules[ModuleIndex].ValidateItem, false);
			}
			
			addEvent(elem, 'blur', FormValidator.modules[ModuleIndex].ValidateItem, false);
		
		}
		

	};


	// Startup the FormValidator
	YAHOO.util.Event.onDOMReady(FormValidator.Init);

	
	
	

	
	/*
	Required Validate module
	*/
	var vmRequired = {
		
		name:'vmRequired',
		version: '0.1',
		Errors: [],

		config: {
			"findClass": 'validate-required',
			"ErrorTxt": 'This is a required field.'
		},

		Reset: function(){
			//clear all error messages shown
			for (var x = 0; x < this.Errors.length; x++){
				FormValidator.RemoveError( this.Errors[x], this );
			}
			
			this.Errors.length = 0;
		},
		
		ValidateItem: function( e ){
			var isValid = true;

			if ( !(elem = e.target || e.srcElement) ){
				// we seem to be working on an element rather than event
				var elem = e;
			}
			
			var elemVal;
			if ( elem.tagName.toLowerCase() == 'input' || elem.tagName.toLowerCase() == 'textarea' )
			    elemVal = elem.value.trim();
			else if ( elem.tagName.toLowerCase() == 'select' ) {
			    if ( elem.selectedIndex != "-1")
					elemVal = elem.options[elem.selectedIndex].value;
			}
			        
		    // module specific item validation
		    if ( !elemVal || elemVal == "-1" ){
			    isValid = false;
			    FormValidator.AddError(elem, vmRequired);
		    }else{
			    FormValidator.RemoveError(elem, vmRequired);
	        }
	
			return isValid;
		},
		
		Validate: function( formNode ){
			var isValidated = true;
			
			var eltColl = getElementsByClassName( formNode, "input", this.config.findClass );
			eltColl = eltColl.concat(getElementsByClassName( formNode, "textarea", this.config.findClass ));
			eltColl = eltColl.concat(getElementsByClassName( formNode, "select", this.config.findClass ));
			for (var x = 0; x < eltColl.length; x++) {
				if ( !this.ValidateItem(eltColl[x]) ){
					isValidated = false;
				}

				FormValidator.AttachEvent(eltColl[x], this.ModuleIndex);
				
			}
							
			return isValidated;
		
		}
		
	};

	// go register with the FormValidator
	vmRequired.ModuleIndex = FormValidator.Register( vmRequired );

	



	/*
	Email Validate module
	*/
	var vmEmail = {
		
		name:'vmEmail',
		version: '0.1',
		Errors: new Array(),

		config: {
			"findClass": 'validate-email',
			"ErrorTxt": 'This is not a valid email address.'
		},

		Reset: function(){
			//clear all error messages shown
			for (var x = 0; x < this.Errors.length; x++){
				FormValidator.RemoveError( this.Errors[x], this );
			}
			
			this.Errors.length = 0;
		},
				
		Validate: function( formNode ){
			var isValidated = true;
			var isChecked = false;
			
			var eltColl = getElementsByClassName( formNode, "input", this.config.findClass );
			
			for (var x = 0; x < eltColl.length; x++) {
				if ( !this.ValidateItem(eltColl[x]) ){
					isValidated = false;
				}

				FormValidator.AttachEvent(eltColl[x], this.ModuleIndex, 'blur');

			}

			return isValidated;
		
		},

		ValidateItem: function( e ){
			var isValid = true;
			
			if ( !(elem = e.target || e.srcElement) ){
				// we seem to be working on an element rather than event
				var elem = e;
			}
			
			var elemVal = elem.value.trim();
			if ( elemVal != "" && !elemVal.match(/\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/) ){
				isValid = false;
				FormValidator.AddError(elem, vmEmail);
			}else {
				FormValidator.RemoveError(elem, vmEmail);
			}
			
			return isValid;

		}

	};

	// go register with the FormValidator
	vmEmail.ModuleIndex = FormValidator.Register( vmEmail );


    /*
	Required Email Validate module
	*/
	var vmEmailRequired = {
		
		name:'vmEmailRequired',
		version: '0.1',
		Errors: new Array(),

		config: {
			"findClass": 'validate-email-required',
			"ErrorTxt": 'This is not a valid email address.'
		},

		Reset: function(){
			//clear all error messages shown
			for (var x = 0; x < this.Errors.length; x++){
				FormValidator.RemoveError( this.Errors[x], this );
			}
			
			this.Errors.length = 0;
		},
				
		Validate: function( formNode ){
			var isValidated = true;
			var isChecked = false;
			
			var eltColl = getElementsByClassName( formNode, "input", this.config.findClass );
			
			for (var x = 0; x < eltColl.length; x++) {
				if ( !this.ValidateItem(eltColl[x]) ){
					isValidated = false;
				}

				FormValidator.AttachEvent(eltColl[x], this.ModuleIndex, 'blur');

			}

			return isValidated;
		
		},

		ValidateItem: function( e ){
			var isValid = true;
			
			if ( !(elem = e.target || e.srcElement) ){
				// we seem to be working on an element rather than event
				var elem = e;
			}
			
			var elemVal = elem.value.trim();
			if( elemVal == "")
			{
			    isValid = false;
				FormValidator.AddError(elem, vmEmail);
			}
			else if ( elemVal != "" && !elemVal.match(/\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/) )
			{
				isValid = false;
				FormValidator.AddError(elem, vmEmail);
			}
			else 
			{
				FormValidator.RemoveError(elem, vmEmail);
			}			
			return isValid;
		}
	};

	// go register with the FormValidator
	vmEmailRequired.ModuleIndex = FormValidator.Register( vmEmailRequired );


	/*
	URL Validate module
	*/
	var vmURL = {
		
		name:'vmURL',
		version: '0.1',
		Errors: [],

		config: {
			"findClass": 'validate-url',
			"ErrorTxt": 'This is not a valid URL. Please use the format http://www.mysite.com'
		},

		Reset: function(){
			//clear all error messages shown
			for (var x = 0; x < this.Errors.length; x++){
				FormValidator.RemoveError( this.Errors[x], this );
			}
			
			this.Errors.length = 0;
		},
				
		Validate: function( formNode ){
			var isValidated = true;
			var isChecked = false;
			
			var eltColl = getElementsByClassName( formNode, "input", this.config.findClass );
			
			for (var x = 0; x < eltColl.length; x++) {
				if ( !this.ValidateItem(eltColl[x]) ){
					isValidated = false;
				}
				
				FormValidator.AttachEvent(eltColl[x], this.ModuleIndex, 'blur');

			}

			return isValidated;

		},

		ValidateItem: function( e ){
			var isValid = true;
			
			if ( !(elem = e.target || e.srcElement) ){
				// we seem to be working on an element rather than event
				var elem = e;
			}
			
			var elemVal = elem.value.trim();
			if ( elemVal != "" && !elemVal.match(/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i) ){
				isValid = false;
				FormValidator.AddError(elem, vmURL);
			}else{
				FormValidator.RemoveError(elem, vmURL);
			}
			
			return isValid;

		}

	};
	
	// go register with the FormValidator
	vmURL.ModuleIndex = FormValidator.Register( vmURL );



	/*
	DATE Validate module
	*/
	var vmDate = {
		
		name:'vmDate',
		version: '0.1',
		Errors: [],

		config: {
			"findClass": 'validate-date',
			"ErrorTxt": 'This is not a valid date. Please use the format DD/MM/YYYY.'
		},


		Reset: function(){
			//clear all error messages shown
			for (var x = 0; x < this.Errors.length; x++){
				FormValidator.RemoveError( this.Errors[x], this );
			}
			
			this.Errors.length = 0;
		},
		
		Validate: function( formNode ){
			var isValidated = true;
			var isChecked = false;
			
			var eltColl = getElementsByClassName( formNode, "input", this.config.findClass );
			
			for (var x = 0; x < eltColl.length; x++) {
				if ( !this.ValidateItem(eltColl[x]) ){
					isValidated = false;
				}
				
				FormValidator.AttachEvent(eltColl[x], this.ModuleIndex, 'blur');

			}

			return isValidated;

		
		},

		ValidateItem: function( e ){
			var isValid = true;
			
			if ( !(elem = e.target || e.srcElement) ){
				// we seem to be working on an element rather than event
				var elem = e;
			}
			
			var elemVal = elem.value.trim();
				if ( elemVal != "" && !elemVal.match(/^((0[1-9]|[12][0-9]|3[01])([/])(0[13578]|10|12)([/])([1-2][0,9][0-9][0-9]))|(([0][1-9]|[12][0-9]|30)([/])(0[469]|11)([/])([1-2][0,9][0-9][0-9]))|((0[1-9]|1[0-9]|2[0-8])([/])(02)([/])([1-2][0,9][0-9][0-9]))|((29)(\.|-|\/)(02)([/])([02468][048]00))|((29)([/])(02)([/])([13579][26]00))|((29)([/])(02)([/])([0-9][0-9][0][48]))|((29)([/])(02)([/])([0-9][0-9][2468][048]))|((29)([/])(02)([/])([0-9][0-9][13579][26]))/i) ){
				isValid = false;
				FormValidator.AddError(elem, vmDate);
			}else{
				FormValidator.RemoveError(elem, vmDate);
			}
			
			return isValid;

		}

	};
	
	// go register with the FormValidator
	vmDate.ModuleIndex = FormValidator.Register( vmDate );
	
	
	
	
	
	
	
	
	
	// Check Required Validate module
	
	var vmCheckRequired = {
		
		name:'vmCheckRequired',
		version: '0.1',
		Errors: [],

		config: {
			"findClass": 'check-required',
			"ErrorTxt": 'You need to check this box to submit the form'
		},

		Reset: function(){
			for (var x = 0; x < this.Errors.length; x++){
				FormValidator.RemoveError( this.Errors[x], this );
			}
			this.Errors.length = 0;
		},
		
		Validate: function( formNode ){
			var isValidated = true;
			var isChecked = false;
			var eltColl = getElementsByClassName( formNode, "input", this.config.findClass );
			for (var x = 0; x < eltColl.length; x++) {
			    if( eltColl[x].getAttribute('type') == 'checkbox' ) {
				    if ( !this.ValidateItem(eltColl[x]) ){
					    isValidated = false;
				    }
					FormValidator.AttachEvent(eltColl[x], this.ModuleIndex, 'change');
				}
			}
			return isValidated;
		},

		ValidateItem: function( e ){
			var isValid = true;

			if ( !(elem = e.target || e.srcElement) ){
				// we seem to be working on an element rather than event
				var elem = e;
			}
			
            if(!elem.checked ) {
	            isValid = false;
				FormValidator.AddError(elem, vmCheckRequired);
		    }else{
				FormValidator.RemoveError(elem, vmCheckRequired);
			}
			return isValid;
		}
		
		
		
	};
	
	// go register with the FormValidator
	vmCheckRequired.ModuleIndex = FormValidator.Register( vmCheckRequired );
	
	
	
	
	// Check Required Validate module
	
	var vmRadioRequired = {
		
		name:'vmRadioRequired',
		version: '0.1',
		Errors: [],

		config: {
			"findClass": 'radio-required',
			"ErrorTxt": 'You must select one of the above options.'
		},

		Reset: function(){
			for (var x = 0; x < this.Errors.length; x++){
				FormValidator.RemoveError( this.Errors[x], this );
			}
			this.Errors.length = 0;
		},
		
		Validate: function( formNode ){
			var isValidated = true;
			var isChecked = false;
			var eltColl = getElementsByClassName( formNode, "input", this.config.findClass );
			for (var x = 0; x < eltColl.length; x++) {
			    if( eltColl[x].getAttribute('type') == 'radio' ) {
				    if ( !this.ValidateItem(eltColl[x]) ){
					    isValidated = false;
				    }
				    addEvent(eltColl[x], 'blur', FormValidator.modules[this.ModuleIndex].ValidateItem, false);
				}
			}
			return isValidated;
		},

		ValidateItem: function( e ){
			var isValid = false;

			if ( !(elem = e.target || e.srcElement) ){
				// we seem to be working on an element rather than event
				var elem = e;
			}
			
			var name = elem.name;
	        var lastRadioInSet;
	        var eltColl = document.getElementsByName( elem.name )
	        
			for (var x = 0; x < eltColl.length; x++) {    
                lastRadioInSet = eltColl[x];
                if(eltColl[x].checked )
                    isValid = true;         
            }
			
			// use parentNode to step out of label if input inside a label
			if ( lastRadioInSet.parentNode.nodeName.toLowerCase() == "label" )
    			lastRadioInSet = lastRadioInSet.parentNode;
			
			if( isValid == false )
			    FormValidator.AddError(lastRadioInSet, vmRadioRequired);
			else
			    FormValidator.RemoveError(lastRadioInSet, vmRadioRequired);
          
			return isValid;
		}	
		
	};
			
	// go register with the FormValidator
	vmRadioRequired.ModuleIndex = FormValidator.Register( vmRadioRequired );
	
	
	//Check Valid Password
	
	var vmPassword = {
		
		name:'vmPassword',
		version: '0.1',
		Errors: [],

		config: {
			"findClass": 'validate-password',
			"findClass2" : 'validate-newpassword',
			"ErrorTxt": 'The passwords should be between 6 and 10 characters in length.  It must include a number at the start or end and all other characters should be alphabetic.'
		},

		Reset: function(){
			for (var x = 0; x < this.Errors.length; x++){
				FormValidator.RemoveError( this.Errors[x], this );
			}
			this.Errors.length = 0;
		},
		
		Validate: function( formNode ){
			
		    var isValidated = true;
			var eltColl = getElementsByClassName( formNode, "input", this.config.findClass );
			if(!eltColl || eltColl.length < 1) 
			    eltColl = getElementsByClassName( formNode, "input", this.config.findClass2 );
						
			for (var x = 0; x < eltColl.length; x++) {
			    if( eltColl[x].getAttribute('type') == 'password' ) {
				    if ( !this.ValidateItem(eltColl[x]) ){
					    isValidated = false;
				    }
				    addEvent(eltColl[x], 'keydown', FormValidator.modules[this.ModuleIndex].ValidateItem, false);
				}
			}
			return isValidated;
		},

		ValidateItem: function( e ){
			var isValid = true;

			if ( !(elem = e.target || e.srcElement) ){
				// we seem to be working on an element rather than event
				var elem = e;
			}
			
		    // module specific item validation
		    var elemVal = elem.value.trim();						
			if( elemVal == "")
			{
			    isValid = false;
			    FormValidator.AddError(elem, vmPassword);
			}
			else if ( elemVal != "" && !( elemVal.match(/([a-z]+\d)|(\d+[a-z])/i) && elemVal.length >=6 &&  elemVal.length <=10 ) )
			{
			    isValid = false;
			    FormValidator.AddError(elem, vmPassword);
		    }
		    else
		    {
			    FormValidator.RemoveError(elem, vmPassword);
	        }
	
			return isValid;
		}
		
	};
	
	// go register with the FormValidator
    vmPassword.ModuleIndex = FormValidator.Register( vmPassword );


    // Check new password confirmed

    var vmConfirmNewPassword = {
		
		name:'vmConfirmNewPassword',
		version: '0.1',
		Errors: [],

		config: {
			"findPasswordClass": 'validate-newpassword',
			"findConfirmClass": 'validate-confirmpassword',
			"ErrorTxt": 'The passwords you have entered do not match.'
		},

		Reset: function(){
			for (var x = 0; x < this.Errors.length; x++){
				FormValidator.RemoveError( this.Errors[x], this );
			}
			this.Errors.length = 0;
		},
		
		
		Get1stPasswordInputByClassName : function(formNode, className)
		{
		    var eltColl = getElementsByClassName( formNode, "input", className );
			if(eltColl != null && eltColl.length > 0) 
			{			
			    for (var x = 0; x < eltColl.length; x++) 
			    {
			        if( eltColl[x].getAttribute('type') == 'password' ) 
			            return eltColl[x];
			    }
			}
			return null;
		}, 
				
		Validate: function( formNode )
		{		   		    
	    	var elt1 = this.Get1stPasswordInputByClassName(formNode, this.config.findPasswordClass);	    		    	
	    	if(elt1 != null)
	    	{
		        var elt2 = this.Get1stPasswordInputByClassName(formNode, this.config.findConfirmClass );
	            //addEvent(elt1, 'blur', FormValidator.modules[this.ModuleIndex].ValidateItem, false);
		        //addEvent(elt2, 'blur', FormValidator.modules[this.ModuleIndex].ValidateItem, false);
		        
		        return this.ValidateItem(elt1, elt2);			
		    }		
			return true;
		},

		ValidateItem: function( elt1, elt2 ){
		    var isValid = true;
			var password, passwordconfirm, elem;
					
		    password = elt1.value.trim();
		    passwordconfirm = elt2.value.trim();
		    
		    if( password != "" && (passwordconfirm == "" || (password != passwordconfirm)))
		    {		        
                isValid = false;		        
		    }
		    
		    if( isValid == false )
		        FormValidator.AddError( elt2, vmConfirmNewPassword);
		    else
		        FormValidator.RemoveError( elt2, vmConfirmNewPassword);		
		   
			return isValid;
		}	
		
	};
	

	// go register with the FormValidator
    vmConfirmNewPassword.ModuleIndex = FormValidator.Register( vmConfirmNewPassword );
    
    