+/*
*	Javascript form validation
*	@author: Khalah Jones - Golden !Panda
*/
(function() //to self contain all vars :D
{
var forms = [];
$(document).ready( function()
{
	initGlobalVars();
	initEvents();
	initForms();
});

function initGlobalVars()
{
}
function initEvents()
{
	$('.invalid').live( 'keydown', function()
	{
		$(this).removeClass( 'invalid' );
	});
	$('.invalid').live( 'focus', function()
	{
		$(this).removeClass( 'invalid' );
	});
}
function initForms()
{
	$("form.validate").each(function( idx )
	{
		$(this).show();
		forms.push( new form( this ) );
		$(this).bind( 'isValid', function()
		{
			if( forms[idx].isValid() )
			{
				$(this).addClass( 'valid' )
				$(this).removeClass( 'invalid' );
			}
			else
			{
				$(this).addClass( 'invalid' );
				$(this).removeClass( 'valid' );
			}
		});
	});
}

function form(obj)// i also have to develop an error system for this, ooo can't wait
{
	var inputs = $(obj).find(":input");
	
	var TEXT_INPUT = ':text, :password, textarea';
	var CHECKBOX = ':checkbox';
	var NOTOPTIONAL_ERROR_TEXT = "Sorry but this is a required field";
	var NOMATCH_ERROR_TEXT = "Passwords do not match";
	var INVALIDEMAIL_ERROR_TEXT = "This doesn't appear to be a valid email address";
	
	inputs.each(function()
	{
		var $me = $(this);
		if( $me.hasClass("email") || $me.hasClass("password") || $me.hasClass("password-confirm") )
		{
				$me.after( '<div class="error-messages"></div>' );					//otherwise put it after me
		}
		else if( $me.is( CHECKBOX ) )
		{
			/*	
			*
			*	here's an example of proper markup format a single input checkbox:
			*
			*	<label for="checkbox#"><input type="checkbox" name="checkbox_group" value="value" id="id" />Text for checkbox</label>
			*
			*
			*	Here's and example group of checkboxs:
			*
			*	<label for="day"><input type="checkbox" name="time" value="day" id="day"/>Within a day</label>
			*	<label for="week"><input type="checkbox" name="time" value="week" id="week"/>Within a week</label>
			*	<label for="month"><input type="checkbox" name="time" value="month" id="month"/>Within a month</label>
			*
			*/
			var $last_in_group = $('input:checkbox[name="' + $me.attr('name') + '"]').last();
			if( $last_in_group.length <= 0 )
				$last_in_group.parent('label[for="' + $last_in_group.attr("id") + '"').after('<div class="error-messages"></div>');		//if you did add the error messages box after the label
		}
		else
			$me.addClass("always-valid");
		if( $me.is( TEXT_INPUT ) )
		{
			$me.data( 'vars', { initialval:$me.val() });						//setting the initial value in a data or event rather
			if( $me.is(':password') && $me.val() != '' )						//passwords with watermarks need special events that swap out inputs for the password one.
			{
				if($me.hasClass('password-confirm'))	//is it a password confirm 
					$me.after('<input type="text" class="watermark password-confirm" value="' + $me.val() + '" />');
				else
					$me.after('<input type="text" class="watermark password" value="' + $me.val() + '" />'); //adds the markup for all of thespecail password fields 
				$me.hide() 
					.val('');			//pretty straight forward 
				$next = $me.nextAll( "input.password:first" );
				if( !$next.length )
					$next = $me.nextAll( "input.password-confirm:first" );			
				$next.focus(function()				//add the input password field speical focus in event to hide what you're seeing
				{
					$me.show();
					$(this).hide();
					$me.focus();
				});
				$me.focusout(function()				//special focus out event for the password input field 
				{
					if( $(this).val() === '' )
					{
						$next = $me.nextAll( "input.password:first" );
						if( !$next.length )
							$next = $me.nextAll( "input.password-confirm:first" );
						$next.show();
						$(this).hide();
					}
				});
			}
			else if( $me.val() != '' )
			{
				$me.focus(function()
				{
					if( $me.val() === $me.data('vars').initialval )
						$me.val('')
						.removeClass('watermark');
				})
					.focusout(function()
				{
					if( $me.val() == '' )
						$me.val($me.data('vars').initialval)
							.addClass('watermark');
				})
					.addClass( 'watermark' );
			}
		}
		if( $me.attr("limit") && !$me.hasClass("password") && !$me.hasClass("password-confirm") )
		{
			var limit = $me.attr("limit");
			$me.keypress(function()
			{
				$(this).val( $(this).val().substr( 0, (parseInt($(this).attr("limit"))-1) ) );
			});
		}
	});
	this.validate = function()
	{
		var passed = true;
		inputs.each(function()		//this is where the different inputs are tested 
		{
			var $me = $(this), $next = $me.nextAll("div.error-messages:first");
			var pass = true, val = trimStr( $(this).val() );
			
			$me.focusout();
			$next.html('');
			
			$(this).removeClass('error');
			if( !$me.hasClass( 'optional' ) )
			{
				if( $me.is(TEXT_INPUT) )	//if i am a type text
				{
					if( val === '' || val === $me.data('vars').initialval )
					{
						$me.addClass( 'not-optional' );		//so it fails validation
						pass=false;
						$next.append(NOTOPTIONAL_ERROR_TEXT + "<br />");
					}
				}
				else if( $me.is(CHECKBOX) )
				{
					if( !$me.is(':checked') )
					{
						$me.addClass( 'not-optional' );		//so it fails validation
						pass=false;
						$next.append(NOTOPTIONAL_ERROR_TEXT);
					}
				}
			}
			if( $(this).hasClass('email') )
				if( !isValidEmail( val ) )
				{
					$me.addClass('invalid-email');
					pass=false;
					$next.append(INVALIDEMAIL_ERROR_TEXT);
				}

			if( $(this).hasClass( 'password-confirm' ) )
				if( $(this).val() != inputs.filter( '.password' ).val() )
				{
					$(this).addClass('no-match' );
					pass=false;
					$next.append(NOMATCH_ERROR_TEXT);
				}				
			if( !pass )			//if the input didn't pass the test
			{
				$(this).filter( TEXT_INPUT ).each(function()
				{
					$(this).addClass("invalid");
					vibrate( $(this) );
					$next.show('slow');
				});
				passed = false;
			}
		});
		return passed;
	}
	this.isValid = function()
	{
		return this.validate();
	}
}
}());
/*
*	Removes leading and trailing space in the input
*
*	@param str: The string you want to trim
*/
function trimStr(str)
{
	while(str.charAt(0) == ' ')
		str = str.substr(1);
	while(str.charAt(str.length-1) == ' ')
		str = str.substring(0, str.length-2);
	return str;
}
/*
*	This does the shake effect, won't work with object being position relative
*	
*	@param obj: the object you want to "vibrate"
*/
function vibrate(obj)
{
	obj.animate({
		"left": "+=10px"
	}, 50);
	for(var i =0; i < 2; i++)
	{
		obj.animate({
			"left": "-=20px"
		}, 50);
		obj.animate({
			"left": "+=20px"
		}, 50);
	}
	obj.animate({
		"left": "-=10px"
	}, 50);
}
/*
*	This checks against the most up to date W3C Standards for a valid email
*	
*	@param emailAddress: The email Address you want to validate
*/
function isValidEmail(emailAddress) 
{
	var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[(2([0-4]\d|5[0-5])|1?\d{1,2})(\.(2([0-4]\d|5[0-5])|1?\d{1,2})){3} \])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ ;
	return re.test(emailAddress);
}
