/*
	// Exemplo de como formar o validator:
	<script type="text/javascript">
		var v = new Validator();	
		propriedades = {
			'campos'	:new Array({'l':'lblNome', 'i': 'txtNome'},	
								   {'l':'lblEmail', 'i': 'txtEmail'},
								   {'l':'lblSenha', 'i': 'txtSenha'},
								   {'l':'lblConfirmSenha', 'i': 'txtConfirmSenha'}),
			'style'		:new Array({'css':true, 'cssClass':'textoErro'})						
		};	
	</script>
	No onsubmit do formulário coloco: onsubmit='v.validarCamposVazios(propriedades)'.
	Notem que as variaveis v e o propriedades, são declaradas lá em cima dentro da minha tag <script>
	não são variáveis crias pela o validator.
	 
 */
/**
 * @autor Rodrigo Minervino Pereira
 * @data 27/03/2008
 * @version 0.5
 * 
 * O Objeto Validator serve para validar os campos passados pelo objeto propriedades, de acordo com a sua
 * configuração.
 * Campos de configuração:
 * -----------------------------
 * 	NA PROPRIEDADE 'CAMPOS'
 * -----------------------------
 * 		'i' => Id do campo que será validado;
 * 		'n' => Name do campo que será validado, normalmente o campo name é colocado para validar radio;
 * 		'tipo' => Tipo do campo que será validado, pois alguns campos são tratatos de forma diferentes;
 * 		'expRegular' => Para validar com o campo passando alguma expressão regular;
 * 		'func' => Depois que o campo for validato corretamente, ou seja, o valor do campo está correto,
 *  		      temos a oportunidade de chamar outra função para o campo. Exemplo: Depois que eu validar
 *  		      corretamente um campo de CPF, quero tirar todos os pontos e virgulas dele colocando a pro-
 *  		      priedade func e definindo uma função externa.
 *  	'funcAjax' => servi exatamente igual ao 'func' só que essa função é chamada pelo evento escolhido 
 *  			      e não será só depois da validação está correta;
 *  		          Obs.: Podemos passar 3 paramêtros: 1º Em qual evento eu vou chamar esse método;
 *  												 2º Aonde vou carregar a resposta;
 *  												 3º Qual arquivo (PHP, ASP, JAVA) vai ser chamado.
 *  -----------------------------
 *  NA PROPRIEDADE STYLE
 *  -----------------------------
 *  	'css' => Caso eu queira fazer alguma destaque com css para os campos que não foram preenchidos corretamente;
 *  	'cssClass' => Qual a classe css será caso eu queria usar a opção de cima ?
 *  	'cssClassDefault' => Qual a classe css default, a principal usada antes de dar um destaque no campo ?
 *  	'alert' => Para informar se a mensagem de validação será mostrada com um alert ou não.
 *  			   Obs.: TRUE = com alert; FALSE = sem alert
 *  	'container' => Caso eu escolha sem alert informe o id do elemento que queria carregar a mensagem.
 * 
 */
var obj;
var WI_validator = {};
WI_validator.Validator =  function(propriedades){
	this.objCampo = null;
	this.objLabel = null;
	this.campos = propriedades["campos"];
	this.estilo = propriedades["style"];
	for(var x = 0; x < this.campos.length; x++){
		if("l" in this.campos[x]){
			this.objLabel = document.getElementById(this.campos[x]['l']);			
		}
		if("i" in this.campos[x]){
			this.objCampo = document.getElementById(this.campos[x]['i']);
		}
		if("funcAjax" in this.campos[x]){
			this.objCampo.posicao = x;
			var evento = "";
			switch(this.campos[x]["funcAjax"][0].toLowerCase()){
				case "onblur":
					evento = "blur";
					break;
				case "onkeypress":
					evento = "keypress";
					break;
				case "onkeyup":
					evento = "keyup";
					break;
				case "onkeydown":
					evento = "keydown";
					break; 
				case "onmouseover":
					evento = "mouseover";
					break;
				case "onmouseout":
					evento = "mouseout";
					break; 
				case "onmousedown":
					evento = "mousedown";
					break;					
				case "onmousemove":
					evento = "mousemove";
					break;					
				case "onchange":
					evento = "change";
					break;
				case "onfocus":
					evento = "focus";
					break;
			}
			obj = this;
			if(this.objCampo.addEventListener){
				this.objCampo.addEventListener(evento, function(e){obj.validacaoServidor(e);}, true);
			}else if(this.objCampo.attachEvent){
				this.objCampo.attachEvent("on"+evento, function(e){obj.validacaoServidor();});
			}
		}
	}
}
/**
 * Método do validador que vai validar os campos de acordo com o tipo.
 * @param {Object} propriedades
 */
WI_validator.Validator.prototype.validarCampos = function(propriedades){
	this.verificarFuncionalidade();
	for(var x = 0; x < this.campos.length; x++){
		this.objLabel = null;
		this.objCampo = null;
		if("l" in this.campos[x]){
			this.objLabel = document.getElementById(this.campos[x]['l']);			
		}
		if("i" in this.campos[x]){
			this.objCampo = document.getElementById(this.campos[x]['i']);
			if(this.campos[x].tipo == "text" || this.campos[x].tipo == "select"){
				if("funcAjax" in this.campos[x]){
					obj = this;
					switch(this.campos[x]["funcAjax"][0]){
						case "onblur" :
							//Capturando o evento de onblur dos elementos
							this.objCampo.onblur = function(e){
								obj.verificarCampo(v.objLabel.id, v.objCampo);
								obj.validacaoServidor(e);
							}		
						break;
						default:
							//Capturando o evento de onblur dos elementos
							this.objCampo.onblur = function(){
								obj.verificarCampo(v.objLabel.id, v.objCampo);
							}
						break;											
						
					}
				}else{
					obj = this;
					//Capturando o evento de onblur dos elementos
					this.objCampo.onblur = function(){
						obj.verificarCampo(obj.objLabel.id, obj.objCampo);
					}
				}
				if(this.validarCamposText(x) == false){
					this.cssPadrao(x);
					return false;
				}
			}
		}else if ("n" in this.campos[x]){
			this.objCampo = document.getElementsByName(this.campos[x].n);
			if(this.campos[x].tipo == "radio"){
				if(this.validarCamposRadio(x) == false){
					return false;
				}
			}
		}
		if("func" in this.campos[x]){
			try{
				if(eval(this.campos[x].func) == false){
					return false;
				}
			}catch(e){
				throw new ReferenceError("A função ' " + this.campos[x].func + " ' não está definida");
			}
		}
	}
}

/**
 * Méotodo do validator que seta o css padrão para os campos.
 * @param {Object} x
 */
WI_validator.Validator.prototype.cssPadrao = function(x){
	for(var z = 0; z<this.campos.length; z++){
		if(z == x){
			continue;
		}
		if("l" in this.campos[z]){
			var objLabel = document.getElementById(this.campos[z]['l']);			
		}
		objLabel.className = this.estilo[0]['cssClassDefault'];
	}
}

/**
 * Método que validar os campos text e select.
 * @param {Object} posicao
 */
WI_validator.Validator.prototype.validarCamposText = function(posicao){
	if(this.objCampo.value == ""){
		if(this.estilo[0]["alert"] == true){
			alert("Por favor, preencha o(s) campo(s) requerido(s).");
		}else{
			document.getElementById(this.estilo[0]["container"]).innerHTML = "Por favor, preencha o(s) campo(s) requerido(s).";
		}
		this.objCampo.focus();
		if(this.estilo[0]['css'] == true){
			if(this.objLabel != null){
				this.objLabel.className = this.estilo[0]['cssClass'];
			}	
		}
		return false;
	}else{
 		if("expRegular" in this.campos[posicao]){
			if(this.objCampo.value.match(this.campos[posicao].expRegular) === null){
				if(this.estilo[0]["alert"] == true){
					alert("Por favor, preencha o campo requerido corretamente");
				}else{
						document.getElementById(this.estilo[0]["container"]).innerHTML = "Por favor, preencha o campo requerido corretamente";
				}
				this.objCampo.select();
				if(this.estilo[0]['css'] == true){
					if(this.objLabel != null){
						this.objLabel.className = this.estilo[0]['cssClass'];
					}			
				}
				return false;
			}
		}
	}
	return true;
}

/**
 * Método do Validator para validar os campos radio.
 * @param {Object} posicao
 */
WI_validator.Validator.prototype.validarCamposRadio = function(posicao){
	var retorno = false;
	for(var i = 0; i < this.objCampo.length; i++){
		if(this.objCampo[i].checked == true){
			retorno = true;
			break;
		}
	}
	if(retorno == false){
		if(this.estilo[0]["alert"] == true){
			alert("Por favor, preencha o(s) campo(s) requerido(s).");
		}else{
			document.getElementById(this.estilo[0]["container"]).innerHTML = "Por favor, preencha o(s) campo(s) requerido(s)."; 
		}
		if(this.estilo[0]['css'] == true){
			if(this.objLabel != null){
				this.objLabel.className = this.estilo[0]['cssClass'];
			}				
		}
		return false;
	}
}

/**
 * Método do Validator que é levantado no evento de onblur dos campos verificando se o campo
 * em questão ainda está vazio e caso sete expressão regular se ele está válido, pois caso tenha
 * o css de destaque, tirar ou não.
 * @param {Object} labelCampo
 * @param {Object} obj
 * @param {Object} cssClass
 */
WI_validator.Validator.prototype.verificarCampo = function (labelCampo, obj, cssClass){
	var objLabel = document.getElementById(labelCampo);
	if(obj.value != ""){
		for(var x in this.campos){
			if(this.campos[x].l == labelCampo){
				if("expRegular" in this.campos[x]){
					if(obj.value.match(this.campos[x].expRegular) !== null){
						if("cssClassDefault" in this.estilo[0]){
							objLabel.className = this.estilo[0]['cssClassDefault'];	
						}else{
							objLabel.className = "";
						}
						if(this.estilo[0]["alert"] == false){
							document.getElementById(this.estilo[0]["container"]).innerHTML = "";
						}
 					}
				}else{
					if("cssClassDefault" in this.estilo[0]){
						objLabel.className = this.estilo[0]['cssClassDefault'];	
					}else{
						objLabel.className = "";
					}
					if(this.estilo[0]["alert"] == false){
						document.getElementById(this.estilo[0]["container"]).innerHTML = "";
					}
				}
			}
		}
	}
}
/**
 * Método do Validator que valida os campos no servidor, ou seja chamando alguma arquivo que acesse o servidor.
 * Por exempl: PHP, ASP, JAVA.
 * @param {Object} evento
 */
WI_validator.Validator.prototype.validacaoServidor = function(evento){
	if(evento == null){
		evento = window.event;
	}
	objAtual = evento.srcElement == null ? evento.target : evento.srcElement;
	var requisicao;
	var campoValidar = this.campos;
	for(var x = 0; x < this.campos.length; x++){
		if(this.campos[x]["i"] == objAtual.id){
			if(window.XMLHttpRequest){
				requisicao = new XMLHttpRequest();
			}else if(window.ActiveXObject){
				requisicao = new ActiveXObject("Microsoft.XMLHTTP");
			}
			requisicao.open("POST", this.campos[x]["funcAjax"][2], false);
			requisicao.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			//Isso aqui só tá funcionando no Internet Explorer
			requisicao.onreadystatechange = function(){
				if(requisicao.readyState == 4){
					if(requisicao.status == 200){
						document.getElementById(campoValidar[x]["funcAjax"][1]).innerHTML = requisicao.responseText;
					}
				}
			}
			requisicao.send("campo="+objAtual.name+"&valor="+objAtual.value);
			document.getElementById(this.campos[x]["funcAjax"][1]).innerHTML = requisicao.responseText;
		}
		continue;
	}
}

/**
 * Método que verifica se os campos passado na propriedade estão realmente corretos.
 */
WI_validator.Validator.prototype.verificarFuncionalidade = function(){
	for(var x = 0; x < this.campos.length; x++){
		if("i" in this.campos[x]){
			if(document.getElementById(this.campos[x]["i"]) == null){
				throw new Error ("O id passado para a propriedade está incorreto ou não existe: \n\n " +
								 "VOCÊ USOU: \n" +
								 "\' i \' : ' " + this.campos[x]["i"] + " '");
			}
		}else{
			if("n" in this.campos[x]){
				if(document.getElementById(this.campos[x]["n"]) == null){
				throw new Error ("O name passado para a propriedade está incorreto ou não existe. \n\n " +
								 "VOCÊ USOU: \n\n" +
								 "\' n \' : ' " + this.campos[x]["n"] + " '");
				}
			}else{
				throw new Error("Para fazer a validação você deve declarar ou o \'id\' ou o \'name\', \n "+
								"com \' i \' ou \' n \' respectivamente. \n\n "+
								"Ex.: \' i \' : \' idNome \' ou \' n \' : \' nameNome \'");
			}
		}
		
		if("tipo" in this.campos[x]){
			if(this.campos[x]["tipo"] != "text" && this.campos[x]["tipo"] != "select" && this.campos[x]["tipo"] != "radio"){
				throw new Error("A propriedade \' tipo \' só pode ter os valores: ' text ', ' select ' ou ' radio. ' \n\n " +
								"VOCÊ USOU: \n\n" +
								"\' tipo \' : ' " + this.campos[x]["tipo"] + " '");
			}
		}else{
			throw new Error("A propriedade \' tipo \' é obrigatória. \n " +
							"Ex.: \' tipo \' : 'text' ou \' tipo \' : 'select' ou \' tipo \' : 'radio'");
		}
	}
	if(this.estilo[0]['cssClass'] == null){
		throw new Error("Você disse que ia usar css, mas não disse qual era a classe \n Ex.: \' cssClass \':\' classeErro \'");
		return false;
	}
	if(this.estilo[0]["alert"] == false){
		if(document.getElementById(this.estilo[0]["container"]) === null){
			throw new Error("O id do container está incorreto: \n \' container \': ' "+ this.estilo[0]["container"] + " '");
			return false;
		}
	}
}