/**
	jQuery.validformhints
	2009, icograma.com 
	Licensed under GPL license (http://www.opensource.org/licenses/gpl-license.php).

	@version 0.201
 **/
 
 //Prefix utilizado para las clases de css que va a hookear el script, 
//el default es verify, es decir que va a hookear cualquier cosa que sea class="verifyAlgo" y este dentro del form que se envia (con la mayuscula despues del prefix)
classprefix = 'verify';

/*
//Este es un ejemplo de la funcion extendible
//Mediante esta funcion se pueden agregar clases adicionales para la comprobacion
//Los parametros son fijos, el primero es el prefix de la clase, el segundo el type de validacion que le pasaron
//Y el tercero el value a validar, la funcion debe devolver true o false

function isTypeValidExt( classprefix, type, value )
{
	if( type == classprefix + 'Test' )
	{
		alert('testEval');
		return true;
	}
	
	return true;
}
*/

var annoy=true;
function debug(msg){if(annoy){annoy=confirm(msg);};}

$(document).ready(function(){
	mustCheck = true;
	/**
	lista = new Array( "cero", "uno", "dos" )
	lista[1000] = "mil"
	debug( lista.length )
	debug( lista[99] )
	/**/
	
	/**
	lista = new Object();
	lista["ochomil"] = 8000;
lista["1000"] = "mil";

	lista2 = lista;
	lista2["nuevemil"] = "9000"
	debug(lista["nuevemil"])
	/**/

	/**
	lista[2] = "dos";	
	lista[1000] = "mil";
	debug( lista.1 )
	debug( lista.length )
	debug( lista["ochomil"] )
	debug( lista.length )
	/**
	//function mamifero(){
	
	mamifero = function(){
			this.patas = 4;
			this.monotremas = "ornitorrinco";
			}
			mamifero.primates= function(){
			this.pulgaroponible = true;
			}
			mamifero.primates.homosapiens = function(){
				this.chabon = true;
				}
	var cacho = new mamifero;
	var cacho2 = new mamifero.primates.homosapiens;
	
	cacho.primates = new mamifero.primates
	
	debug( cacho.primates );
	
	
	debug( cacho.patas );
	debug( cacho2.patas );
	debug( cacho2.chabon );
	// debug( mamiferos.primates.pulgaroponible );
	/**/
	
	$("."+classprefix+"Cancel").click(function(event){
		mustCheck = false;
	});
	
	//add *title hints to form elements
	for( var i=0; i < document.forms.length; i++)
	{
		var fe = document.forms[i].elements;	
		for ( var j=0; j < fe.length; j++ )
		{
			
			//Reference hints
			if( (fe[j]).title.indexOf("**")==0 )
			{
				if( (fe[j]).value == "" || (fe[j]).value == titleHint )
				{
					var titleHint = (fe[j]).title.substring(2);
					(fe[j]).value = titleHint;
				}
			}
			else if( ( (fe[j]).type == "text" || (fe[j]).type == "password" ) &&  (fe[j]).title.indexOf("*")==0  )
			{
				addHint( (fe[j]) );
				$(fe[j]).blur(function(event){ addHint(this); });
				$(fe[j]).focus(function(event){ removeHint(this); });
			}//end type==text
		}//end j
	}//end f
	// form validation
	
	/*
	$("FORM").submit(function(event){
		if( !checkForm(this) ) //si falla la validacion, no se envia el FORM
		{
			event.preventDefault();
		};
	}); // end form validation
	*/	

	$("FORM").submit(function(event){
		
		if(mustCheck)
		{
			if( !checkForm(this) ) //si falla la validacion, no se envia el FORM
			{
				event.preventDefault();
			};
		}
		else
		{
			mustCheck = !mustCheck;
		}
		/*
			executeTestQuery(this);
			event.preventDefault();
		*/

	}); // end form validation
}); // end jQuery $(document).ready



/******
*title hints functions
******/

function addHint(field)
{
	
	var titleHint = field.title.substring(1);
	if( field.value == "" || field.value == titleHint )
	{
			//in "password" inputs, set to "text" to show hint, preserve type in class attribute
			if( field.type == "password" )
			{
				$( field ).addClass("password");
				var newObject = changeInputType( field, "text" )//returns false for non-ie
			}//end type == "password"

			
			$(field).addClass("hint");
			field.value = titleHint;
			
	}//end value==""
	
}//end addHint


function removeHint(field)//only on INPUT.text items
{
	/*if( field.type == "text" && field.title.indexOf("*")==0 )
	{*/
		var titleHint = field.title.substring(1);
		if( field.value == "" || field.value == titleHint )
		{
			$(field).removeClass('hint');
			field.value="";
			
			//re-set password type if appropiate
			if($(field).hasClass("password"))
			{
				var newObject = changeInputType( field, "password" ); //returns false for non-ie
				if(newObject)///IE, element was replaced: reset focus
				{
					$(newObject).focus();
					$(newObject).select();
				}
			}//end hasClass("password")
			
		}//end value == titleHint
	//}//end what.title
	
}//end rmhint


function changeInputType(oldObject, oType)
{
//based on http://arjansnaterse.nl/changing-type-attribute-in-ie
//used to simulate change of INPUT type in IE
	
	if(!document.all){
		oldObject.type = oType;
		return false;
	}else{
	//ie can't change INPUT's type, must create new element
		/*
		newObject = $(oldObject).clone(true);
		//newObject.type = oType;
		$(newObject).attr('type');
		$(newObject).insertBefore(oldObject);
		debug(newObject);
		return newObject;
		*/

	  var newObject = document.createElement('input');
	  newObject.type = oType;
	  if(oldObject.size) newObject.size = oldObject.size;
	  if(oldObject.title) newObject.title = oldObject.title;
	  if(oldObject.value) newObject.value = oldObject.value;
	  if(oldObject.name) newObject.name = oldObject.name;
	  if(oldObject.id) newObject.id = oldObject.id;
	  if(oldObject.className) newObject.className = oldObject.className;
	  oldObject.parentNode.replaceChild(newObject,oldObject);
	  //live()
	  return newObject;
  }//end document.all
}

function checkForm(form)
{
	//Inicializamos variables
	var send = true;
	var password = '';
	radioGroups = Array();
	
	//Sacamos la clase de haserrors del form si la tenia
	$( form ).removeClass ( "haserrors" );

	//Buscamos todos los inputs que tienen el prefix, o son hijos de un .required (input, textarea y select) y estan debajo del <form> que se envia
	//inputs = $(form).find('INPUT[class*="' + classprefix + '"]');
	inputs = $(form).find('INPUT[class*="' + classprefix + '"], .required INPUT, .required TEXTAREA, .required SELECT');
	//Iteramos sobre la respuesta de la consulta
	//alert(inputs.length);
	
	$.each(inputs, function(i, val) {  
     	input = $(val);
     	if( input.attr('offsetWidth') != 0 ) //Si estan ocultos no se valida
     	{
     	
     			//alert(input.attr('type'));
     			
     			switch(input.attr('type'))
     			{
     				case 'select-one':
     					//Si el tipo es SELECT y el campo seleccionado no tiene texto lo marcamos erroneo
     					if( input.get(0)[ input.attr('selectedIndex') ].text == '')
     					{
     						if( send ) moveTo(input);
							showErrorOn( input );
							send = false;
     					}
     				break;
     				
     				case 'radio':
     					//Guardamos los radios en un array asociados por el name para ser procesados despues
     					if( window.radioGroups[ input.attr('name') ] === undefined ) radioGroups[input.attr('name')] = new Array();
     					radioGroups[input.attr('name')][ radioGroups[ input.attr('name') ].length ] = input;
     				break;
     				
     				case 'checkbox':
     					//Si no esta checkeada la marcamos como no valida
     					if( !input.attr('checked') )
     					{
     						if( send ) moveTo(input);
							showErrorOn( input );
							send = false;
     					}
     				break;
     				
     				case 'file':
     					//Si el campo de field no esta lleno
     					if( !isFilled(input) )
     					{
     						if( send ) moveTo(input);
							showErrorOn( input );
							send = false;
     					}
     				break;
     				
     				case 'password':
     					//Si la clase es PasswordConfirm y es distinta a la password anterior marcamos como no valida
     					if( input.hasClass( classprefix + 'PasswordConfirm' ) )
     					{
     						if( input.val() != password ) 
     						{
     							if( send ) moveTo(input);
								showErrorOn( input );
								send = false;
     						}
     						//Ejecutamos un break para que no siga con la validacion (No hace falta validar passconfirm)
     						break;
     					}
     					else
     					{
     						//Si el campo es type="password" y no tiene PasswordConfirm como clase guardamos el value en la variable
     						//No ejecutamos ningun break para que siga a la validacion del campo
							password = input.val();
     					}
     				//Para textarea y text
     				case 'textarea':
     				case 'text':
     					//Si esta lleno o es requerido y no es valido marcamos como erroneo el campo
						if( ( isFilled(input) || isRequired(input) ) && ( !isValid(input) ) )
     					{
							//Si todavia no se encontro ningun error movemos la pantalla a ese campo
							if( send ) moveTo(input);
							//Marcamos el campo con la clase error
							showErrorOn( input );
							//Marcamos a send como false
							send = false;
     					}
     				break;
     				
     				default:
     				break;
     			}
		}
		
		
    });
    
    //Validacion para los radios
    //Usamos un foreach para pasar cada grupo de radios
	for ( var i in radioGroups )
	{
		//Usamos un foreach para pasar cada radio
		for ( var j in radioGroups[i] )
		{
			//Si encuentra que hay uno checkeado ejecuta un break
			if( radioGroups[i][j].attr('checked') )
			{
				break;
			}
		}
		
		//Si el ultimo radio checkeado es false (es decir que no corto en uno que estaba checkeado)
		//Marcamos como erroneo cada radio del grupo
		if( !radioGroups[i][j].attr('checked') )
		{
			for ( var j in radioGroups[i] )
			{
				if( send ) moveTo( radioGroups[i][j] );
				showErrorOn( radioGroups[i][j] );
			}
			
			send = false;
		}
	} 
	
	//Regresamos send, si no ocurrio ningun error de validacion es true, caso contrario false.
	return send;
}

function isRequired(input)
{
	//Checkeamos en los parents del input alguno que tenga la clase required
	return input.parents( ".required" ).length != 0;
}

function isFilled(input)
{
	hintText = '';
	//clear HINTs before validation
	if( input.attr('title').indexOf("**")==0)
	{
		var hintText = input.attr('title').substring(2);
		//es un value de referencia
	}
	else if( input.attr('title').indexOf("*")==0)
	{
		var hintText = input.attr('title').substring(1);
	}//end clear hints
	
	//Si el value del input no es igual al hintText y no es igual a nada regresamos true
	return input.val() != hintText && input.val() != '' ;
}

function isValid( input )
{
	//Si el campo esta vacio devolvemos false y nos ahorramos todo
	if( !isFilled(input) ) return false;
	
	//Precargamos los values para ejecutar mas rapido la funcion
	string = input.attr('class');
	value = input.val();
	
	//Cargamos en donde empieza a leer el string del class
	start = string.indexOf(classprefix);
	
	//Declaracion de variables
	type = '';
	result = true;

	while(result)
	{
		//Si no se encontro la clase o encontro un Prefix solo corta la funcion 
		//(es decir que el campo es valido, ya que no tiene ningna especificacion con que validar)
		if( 
			start == -1 || 
			string.charAt( (start+classprefix.length) ) == ' ' || 
			string.charAt( (start+classprefix.length) ) != string.charAt( (start+classprefix.length) ).toUpperCase() 
		)
		{	
			break;
		}
		//Caso contrario obtiene el tipo de validacion requerida y lo manda a typevalid, si no es valido corta el ciclo
		//y devuelve false, sino sigue buscando mas especificaciones de validacion
		else
		{
			for( i=start; i < string.length; i++ )
			{
				if(string.charAt(i) == ' ')
				{
					break;
				}

				type += string.charAt(i);
			}

			//validacion si es true sigue sino break;
			if( !isTypeValid( type, value ) )
			{
				result = false;
				break;
			}
			
			start = string.indexOf(classprefix,start+1);
		}
	}
	
	return result;

}

//Esta funcion se encarga de recibir el tipo de validacion necesaria como parametro y ejecuta la regexp necesaria.
function isTypeValid( type, value )
{
	if( type == classprefix + 'Text' )
	{
		return true;
	}
	
	if( type == classprefix + 'Integer' )
	{
		return ( ( value.match(/^[\d|,|\.|\s]*$/) ) && ( value != '' ) );
	}
	
	if( type == classprefix + 'Url' )
	{
		return ( value.match( /^(https?:\/\/)?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+\/?)$/ ) );
			
	}
	
	if( type == classprefix + 'ManyWords' )
	{
		return value.match(/^.*[^^]\s[^$].*$/);
	}
	
	if( type == classprefix + 'Mail' )
	{
		if( value.indexOf("@example.com")>-1){return false;};
		var emailFilter=/^.+@.+\..{2,}$/;
		var illegalChars= /[\(\)\<\>\,\;\:\\\/\"\[\]]/
		if(!(emailFilter.test(value))||value.match(illegalChars)){return(false);}else{return (true);}
		return false;
	}
	
	//Si existe la funcion isTypeValidExt la ejecutamos para comprobar validaciones personalizadas
	if(typeof isTypeValidExt == 'function') {
		fr = isTypeValidExt( classprefix, type, value );
		
		//Si la funcion devuelve false es que dio una respuesta valida, caso contrario la respuesta es true o es invalida, 
		//en el caso de que sea invalida devolvemos true para no cortar la validacion
		if( isTypeValidExt( classprefix, type, value ) === false )
		{
			return false;
		}
		else
		{
			return true;
		}
	} 
	
	return true;

}

//Se encarga de mover la pantalla al input que se le indique
function moveTo( input )
{
	//input.get(0).select();
	var targetOffset = input.offset().top - 40;
	$('html,body').animate({scrollTop: targetOffset}, 200 );
	input.get(0).focus();
}

//Basicamente agrega al input que se le pase como parametro la funcion de ejecutar cuando
//esta focus, mousedown o keydown, de sacar la clase de error
function showErrorOn( input )
{
	input.bind('focus.rmErrorClass', function(){
		rmErrorClass( this );
	});
	
	input.bind('mousedown.rmErrorClass', function(){
		rmErrorClass( this );
	});
	
	input.bind('keydown.rmErrorClass', function(){
		rmErrorClass( this );
	});
	
	input.addClass( "error" );
	
	input.parents( ".required, .field, TR" ).addClass( "error" );
}

//Remueve las clases de error del elemento
function rmErrorClass( elm )
{
	var etag=$(elm).parents(".error");
	var eform = $(elm).parents( 'FORM' );
	
	$(elm).removeClass("error");
	$(elm).unbind('.rmErrorClass'); //no further clicks will trigger rmErrorClass();
	
	if(etag){ $(etag).removeClass( "error" ); };
}
