/*

Requires: prototype.js




formElement Public Functions

- setCustomError( errorType, errorDescription )
- setAlertArea( id )
- setFocus()
- requireLength( len )
- requireEmail()
- requirePassword( confirmId )

- customHighlight()
- customValidation()

- validateRequired()
- validateEmail()
- validatePassoword()
- validate()


ValidateForm Public Functions

- setAlertArea( id )
- setAlertIntro( intro )
- addElement( id / name ) - option to tail the setCustomError function: addElement( id / name, errorType, errorDescription )
- removeElement( id / name )

- customError()
- customClearError()
- hideAlert() - turns off default alert() message on error

- validate()

*/



var formElement = Class.create();

formElement.prototype = {
	
	initialize: function( form, element ) {	
	
		if( this.getHandle( form, element ) ) {	
		
			this.setInitVars();
		
			this.getLabel( form, element );
						
			return this.handle;
	
		}
		
	},
	
	
	getHandle: function( form, element ) {	
		
		if( this.handle = document.getElementById( element ) ) return true;
		
		else if( this.handle = form[ element ] ) {
			
			if( !this.handle.type ) this.getChildType();
			
			return true;
		
		}
		
		else return false;
			
	},
	
	
	getChildType: function() {
	
		if( this.handle.length ) {
		
			this.handle.type = this.handle[0].type;
			
		}
	
	},
	
	
	setInitVars: function() {
	
		this.label = null;
		
		this.alertArea = null;
		
		this.requiredLength = 0;
		
		this.isEmail = false;
		
		this.passwordConfirm = null;
		
		this.customHighlight = function() {};
		
		this.customValidation = function() {};
	
		this.setErrors();
	
	},
	
	
	getLabel: function( form, element ) {
	
		var anchors = form.getElementsByTagName( "label" );

		for ( var i = 0; i < anchors.length; i++ )
		
			if( anchors[i].htmlFor == element ) this.label = anchors[i];

	},
	
	
	setErrors: function() {
	
		this.error = null;
		
		this.errorDescriptions = new Array();
		
		this.errorDescriptions['_length'] = "Problem with length";
		this.errorDescriptions['_checked'] = "Problem with checkbox";
		this.errorDescriptions['_radio'] = "Problem with radio";
		this.errorDescriptions['_select'] = "Problem with select";
		this.errorDescriptions['_list'] = "Problem with list";
		this.errorDescriptions['_email'] = "Problem with email";
		this.errorDescriptions['_password'] = "Problem with password";
		this.errorDescriptions['_custom'] = "";
	
	},
	
	
	setCustomError: function( errorType, errorDescription ) {
	
		this.errorDescriptions[ errorType ] = errorDescription;
	
	},
	
	
	setAlertArea: function( id ) {
	
		this.alertArea = id;
	
	},
	
	
	setFocus: function() {
	
		this.handle.focus();
	
	},
	
	
	requireLength: function( len ) {
	
		this.requiredLength = len;
	
	},
	
	
	requireEmail: function() {
	
		this.isEmail = true;
	
	},
	
	
	requirePassword: function( id ) {
	
		this.passwordConfirm = document.getElementById( id );
	
	},
	
	
	triggerError: function( errorType ) {
	
		this.validated = false;
		
		this.error = this.errorDescriptions[ errorType ];

		this.customHighlight();
	
	},
	
	
	validateRequired: function() {
	
		switch( this.handle.type ) {
		
			case "checkbox":
			
				if( !this.handle.checked ) this.triggerError( '_checked' );
			
			break;
		
			case "radio":

				var radioChecked = false;
				
				for( var i = 0; i < this.handle.length; i++ ) {

					if( this.handle[ i ].checked ) radioChecked = true;
				
				}
				
				if( radioChecked == false ) this.triggerError( '_radio' );

			break;
		
			case "select-one":
			
				if( this.handle[ this.handle.selectedIndex ].value == null || this.handle[ this.handle.selectedIndex ].value == "" ) this.triggerError( '_select' );

			break;
		
			case "select-multiple":
			
				if( this.handle.selectedIndex == -1 ) this.triggerError( '_list' );
			
			break;
		
			default:
			
				if( this.handle.value.length == 0 || ( this.requiredLength > 0 && this.handle.value.length < this.requiredLength ) ) this.triggerError( '_length' );
			
			break;		
		
		}
		
		return this.validated;
	
	},
	
	
	validateEmail: function() {
		
		if( this.isEmail ) {
		
			var at_pos = this.handle.value.indexOf( "@" );
			
			var dot_pos = this.handle.value.lastIndexOf( "." );
		
			if( at_pos < 1 || dot_pos - at_pos < 2 ) this.triggerError( '_email' );			
		
		}
		
		return this.validated;
	
	},
	
	
	validatePassword: function() {
	
		if( this.passwordConfirm )
		
			if( this.handle.value != this.passwordConfirm.value ) this.triggerError( '_password' );
	
		return this.validated;
	
	},
	
	
	validate: function() {
	
		this.validated = true;
		
		this.validateRequired();
		
		this.validateEmail();
		
		this.validatePassword();
		
		this.customValidation();
		
		return this.validated;
	
	}
		
};









var formValidate = Class.create();

formValidate.prototype = {
	
	
	initialize: function( formId ) {	
	
		this.form = document.getElementById( formId );
		
		var validate = this.validate.bind(this);

		this.form.onsubmit = function() { return validate(); };
		
		this.setInitVars();
		
	},
	
	
	setInitVars: function() {
	
		this.elements = new Array();
		
		this.alertArea = null;
		
		this.alertIntro = "Please correct the following:\n\n";
		
		this.showAlert = true;
		
		this.customError = function() {};
		
		this.customClearError = function() {};
		
	},
	
	
	setAlertArea: function( id ) {
	
		this.alertArea = id;
		
	},
	
	
	setAlertIntro: function( intro ) {
	
		this.alertIntro = intro;
		
	},
	
	
	hideAlert: function() {
	
		this.showAlert = false;
		
	},
	
	
	addElement: function( element ) {	
		
		this.elements[ element ] = new formElement( this.form, element );
		
		if( arguments.length > 1 ) {
		
			this.elements[ element ].setCustomError( arguments[1], arguments[2] );
		
		}
		
	},
	
	
	removeElement: function( element ) {	
		
		this.elements[ element ].validate = function() {};
		
	},
	
	
	removeChildren: function( element ) {	
		
		if( element.hasChildNodes() ) {
		
			for( var i = 0; i < element.childNodes.length; i++ ) {
			
				element.removeChild( element.childNodes[i] );
			
			}
		
		}
		
	},
	
	
	findPosX: function( element ) {
		
		var curleft = 0;
		
		if( element.offsetParent ) {
		
			while( 1 ) {

			  curleft += element.offsetLeft;
			  
			  if( !element.offsetParent ) break;
			 
			  element = element.offsetParent;
			
			}
	
		} else if( element.x ) curleft += element.x;
		
		return curleft;
		
	},
	
	
	findPosY: function( element ) {
	
		var curtop = 0;
		
		if( element.offsetParent ) {
			
			while( 1 ) {

			  curtop += element.offsetTop;
			  
			  if( !element.offsetParent ) break;
			  
			  element = element.offsetParent;
			  
			}
		
		} else if( element.y ) curtop += element.y;
		
		return curtop;

	},
	
	
	scrollToElement: function( id ) {
	
		var element = document.getElementById( id );
		
		var x = this.findPosX( element );
		
		var y = this.findPosY( element );
		
		window.scrollTo( x, y );
		
		/*
		try { element.scrollTo( x, y ); }
		catch( e ) { 
			//alert( e.message );
			new Effect.ScrollTo(id);
		}
		*/
		
	},	
	
	
	clearAlertAreas: function() {	
		
		if( this.errorHtml ) {
		
			for( i in this.errorHtml ) {
		
				if( typeof this.errorHtml[i] != 'function' ) {
		
					var element = i.substring( 1 );
					
					var elementHandle = document.getElementById( element );
					
					this.removeChildren( elementHandle );
					
				}
		
			}
		
		}

	},
	
	
	updateErrorHtml: function( element, destination ) {
	
		if( element.error ) {
		
			if( !this.errorHtml[ destination ] )
				
				this.errorHtml[ destination ] = document.createElement( "ul" );	
				
			var elementError = document.createElement( "li" );
			
			var errorText = document.createTextNode( element.error );
		
			elementError.appendChild( errorText );
			
			this.errorHtml[ destination ].appendChild( elementError );
		
		}
	
	},
	
	
	showErrorHtml: function() {
	
		for( i in this.errorHtml ) {
	
			if( typeof this.errorHtml[i] != 'function' ) {
	
				var element = i.substring( 1 );
				
				var elementHandle = document.getElementById( element );
				
				this.removeChildren( elementHandle );
				
				elementHandle.appendChild( this.errorHtml[i] );
				
				elementHandle.style.display = "block";
	
			}
	
		}
		
		if( this.alertArea ) this.scrollToElement( this.alertArea );
	
	},
	
	
	showErrors: function( element ) {	
		
		var alertText = "";
		
		this.clearAlertAreas();
		
		this.errorHtml = new Array();
		
		for( var i = 0; i < this.errors.length; i++ ) {
		
			if( this.errors[ i ].alertArea ) this.updateErrorHtml( this.errors[ i ], '_' + this.errors[ i ].alertArea );
			
			else if( this.alertArea ) this.updateErrorHtml( this.errors[ i ], '_' + this.alertArea );
			
			else if( this.errors[ i ].error ) alertText += "- " + this.errors[ i ].error + "\n";
			
		}
		
		if( this.errorHtml ) this.showErrorHtml();

		if( alertText > "" && this.showAlert == true ) alert( this.alertIntro + alertText );	
		
		this.customError();
		
	},
	
	
	validate: function() {	
	
		this.validated = true;
		
		this.customClearError();

		this.errors = new Array();
		
		for( i in this.elements ) {
		
			if( typeof this.elements[i] != 'function' ) {
				
				var elementValidated = this.elements[i].validate();
				
				if( this.validated == true ) this.validated = elementValidated;
			
				if( elementValidated == false ) this.errors.push( this.elements[i] );
			
			}	
		
		}
		
		if( this.validated == false ) this.showErrors();
		
		return this.validated;

	}
		
};




