//Validador de Formulários

// expressões regulares ou funções para a validação do formulário
var re_dt = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/,
re_tm = /^(\d{1,2})\:(\d{1,2})$/,

a_formats = {
	'alpha'   : /^[a-z\A-Z\.\-]*$/,
	'alphanum': /^\w+$/,
	'unsigned': /^\d+$/,
	'integer' : /^[\+\-]?\d*$/,
	'real'    : /^[\+\-]?\d*\.?\d*$/,
	'number'  : /^\d*$/,
	'email'   : /^[\w-\.]+\@[\w\.-]+\.[a-z]{2,4}$/,
	'phone'   : /^[\d\-\(\)]+$/,
	'zipcode' : /^[\d\-]+$/,
	'date'	  : 
	function (s_date) {
		// verifica o formato da data
		if (!re_dt.test(s_date))
			return false;
		// verifica limites permitidos para dia e mês
		if (RegExp.$1 > 31 || RegExp.$2 > 12)
			return false;
		// verifica número de dias possíveis em um mês
		var dt_test = new Date(RegExp.$3, Number(RegExp.$2-1), RegExp.$1);
		if (dt_test.getMonth() != Number(RegExp.$2-1))
			return false;
		return true;
	},
	'time'    : 
	function validate_time(s_time) {
		// verifica o formato da hora
		if (!re_tm.test(s_time))
			return false;
		// verifica os limites permitidos para hora, minutos //e segundos
		if (RegExp.$1 > 23 || RegExp.$2 > 59)// || RegExp.$3 > 59)
			return false;
		return true;
	}, 
	'cpf' 	  :	
	function validaCPF(tempcpf) {
	
	// desmascarando o CPF
		var cpf = new String ; 
		
		for(var i = 0; i<tempcpf.length; i++) {
	
			if(tempcpf.charAt(i)== '.' || tempcpf.charAt(i)== '-');
	
			else {
				cpf += tempcpf.charAt(i);
				
			}
		}
		
		erro = new String;
					
		if (cpf.length < 11) erro += "CPF inválido - Dígitos insuficientes.\n"; 
	
		var nonNumbers = /\D/;
		
		if (nonNumbers.test(cpf)) erro += "CPF inválido - Dígitos alfanuméricos não são permitidos.\n"; 
					 
		if (cpf == "00000000000" || cpf == "11111111111" || cpf == "22222222222" || cpf == "33333333333" || cpf == "44444444444" || cpf == "55555555555" || cpf == "66666666666"  || cpf == "77777777777" || cpf == "88888888888" || cpf == "99999999999") {
			erro += "CPF inválido.\n";
		}
					 
		var a = [];
		var b = new Number;
		var c = 11;
		for (i=0; i<11; i++){
			   a[i] = cpf.charAt(i);
			   if (i < 9) b += (a[i] * --c);
		}
	
		if ((x = b % 11) < 2) { a[9] = 0 } else { a[9] = 11-x }
	   
		b = 0;
		c = 11;
		for (y=0; y<10; y++) b += (a[y] * c--); 
	
		if ((x = b % 11) < 2) { a[10] = 0; } else { a[10] = 11-x; }
		if ((cpf.charAt(9) != a[9]) || (cpf.charAt(10) != a[10])){
			   erro +="CPF inválido.\n";
		}
	   
		if (erro.length > 0) return false;
				   
	 return true;
	 
	}, 
	'cnpj'   : 
	function validaCNPJ(CNPJ) {

		erro = new String;
		
		if (CNPJ.length < 18) erro += "CNPJ inválido - Dígitos insuficientes.\n"; 
		
		if (CNPJ == '00.000.000/0000-00') erro += "CNPJ inválido.\n"; 
		 
		if ((CNPJ.charAt(2) != ".") || (CNPJ.charAt(6) != ".") || (CNPJ.charAt(10) != "/") || (CNPJ.charAt(15) != "-")){
		 
			if (erro.length == 0) erro += "CNPJ inválido - Dígitos separadores inexistentes.\n";
		}
		 
		//substituir os caracteres que não são números
		if(document.layers && parseInt(navigator.appVersion) == 4){
			 x = CNPJ.substring(0,2);
			 x += CNPJ. substring (3,6);
			 x += CNPJ. substring (7,10);
			 x += CNPJ. substring (11,15);
			 x += CNPJ. substring (16,18);
			 CNPJ = x; 
		} 
		else {
			 CNPJ = CNPJ. replace (".","");
			 CNPJ = CNPJ. replace (".","");
			 CNPJ = CNPJ. replace ("-","");
			 CNPJ = CNPJ. replace ("/","");
		}
	
		var nonNumbers = /\D/;
	  
		if (nonNumbers.test(CNPJ)) erro += "CNPJ inválido - Dígitos alfanuméricos não são permitidos.\n"; 
				   
		var a = [];
		var b = new Number;
		var c = [6,5,4,3,2,9,8,7,6,5,4,3,2];
	
		for (i=0; i<12; i++){
			   a[i] = CNPJ.charAt(i);
			   b += a[i] * c[i+1];
		}
					
		if ((x = b % 11) < 2) { a[12] = 0 } else { a[12] = 11-x }
				   
		b = 0;
		for (y=0; y<13; y++) {
			   b += (a[y] * c[y]); 
		}
				   
		if ((x = b % 11) < 2) { a[13] = 0; } else { a[13] = 11-x; }
		
		if ((CNPJ.charAt(12) != a[12]) || (CNPJ.charAt(13) != a[13])){
			   erro +="CNPJ inválido.";
		}
				   
		if (erro.length > 0){
			   return false;
		} 
	   
	return true;
	},
	'ano':
	function validaANO(ano) {
	
	if( ano.length != 4 )
		return false;
		
	if( ano != '2008' && ano!= '2009'  && ano!='2010' && ano!=2011 && ano!=2012 )
	  return false;
		
	
	return true; 
	},
	'pispasep':
	function ChecaPIS(pis)
	{

	var str = new String;

	for(var i=0; i<pis.length; i++) {
		if( (pis.charAt(i) == '.') || (pis.charAt(i) == '-') );

		else {
		str += pis.charAt(i);
		}
	}

	pis = str;

	var ftap="3298765432";
	var total=0;
	var i;
	var resto=0;
	var numPIS=0;
	var strResto="";
	
	total=0;
	resto=0;
	numPIS=0;
	strResto="";

	numPIS=pis;
			
	if (numPIS=="" || numPIS==null)
	{
		return false;
	}
	
	for(i=0;i<=9;i++)
	{
		resultado = (numPIS.slice(i,i+1))*(ftap.slice(i,i+1));
		total=total+resultado;
	}
	
	resto = (total % 11)
	
	if (resto != 0)
	{
		resto=11-resto;
	}
	
	if (resto==10 || resto==11)
	{
		strResto=resto+"";
		resto = strResto.slice(1,2);
	}
	
	if (resto!=(numPIS.slice(10,11)))
	{
		return false;
	}
	
	return true;
	}
},

// mensagens de aviso para o processo de construção das validações
a_messages = [
	'Nao foi passado o nome do formulario para a rotina da contrucao do validator',
	
	'Nehum array de "%form%" (campos do formulario) passado para a rotina da contrucao do validator',
	
	'Formulario "%form%" nao pode ser encontrado neste documento',
	
	'Incompleto "%n%"  descricao de entrado  do campo do formulario . "l" atributo esta perdido',
	
	'Nao encontrado campo com nome "%n%" no formulario "%form%"',
	
	'Nao pode encontrar o rotulo da tag (id="%t%")',
	
	'Nao pode verificar combinacao. O Campo "%m%" nao foi encontrado',
	
	'O campo "%l%" deve ser preenchido.',
	
	'O tamanho/valor "de %l%" deve ser %mn% caracteres ou mais',
	
	'O tamanho/valor "de "%l%" deve ser menos que %mx% caracteres',

	'"%v%" não é um valor válido para o campo "%l%".',
	
	'"%l%" tem que combinar "%ml%"'
]

// método construtor das rotinas de validações
function validator(s_form, a_fields, o_cfg) {
	this.f_error = validator_error;
	this.f_alert = o_cfg && o_cfg.alert
		? function(s_msg) { alert(s_msg); return false }
		: function() { return false };
		
	// verifica parâmetros requiridos
	if (!s_form)	
		return this.f_alert(this.f_error(0));
	this.s_form = s_form;
	
	if (!a_fields || typeof(a_fields) != 'object')
		return this.f_alert(this.f_error(1));
	this.a_fields = a_fields;

	this.a_2disable = o_cfg && o_cfg['to_disable'] && typeof(o_cfg['to_disable']) == 'object'
		? o_cfg['to_disable']
		: [];
		
	this.exec = validator_exec;
}

// método de execução das validações
function validator_exec() {

	var o_form = document.forms[this.s_form];

	if (!o_form)	
		return this.f_alert(this.f_error(2));
		
	b_dom = document.body && document.body.innerHTML;
	
	// verifica a integridade da estrutura da descrição dos campos do formulário
	for (var n_key in this.a_fields) {
		// verifica a descrição da entrada de dados
		this.a_fields[n_key]['n'] = n_key;
		if (!this.a_fields[n_key]['l'])
			return this.f_alert(this.f_error(3, this.a_fields[n_key]));
		o_input = o_form.elements[n_key];
		if (!o_input)
			return this.f_alert(this.f_error(4, this.a_fields[n_key]));
		this.a_fields[n_key].o_input = o_input;
	}

	// Limpa efeito dos labels
	if (b_dom)
		for (var n_key in this.a_fields) 
			if (this.a_fields[n_key]['t']) {
				var s_labeltag = this.a_fields[n_key]['t'], e_labeltag = get_element(s_labeltag);
				if (!e_labeltag)
					return this.f_alert(this.f_error(5, this.a_fields[n_key]));
				this.a_fields[n_key].o_tag = e_labeltag;
				
				//atribuição do estado normal do label
				e_labeltag.className = 'tfvNormal';
			}

	//Coleção de valores de acordo com o tipo do atributo input da tag form
	for (var n_key in this.a_fields) {
		var s_value = '';
		o_input = this.a_fields[n_key].o_input;
		if (o_input.type == 'checkbox') // checkbox
			s_value = o_input.checked ? o_input.value : '';
		else if (o_input.value) // text, password, hidden
			s_value = o_input.value;
		else if (o_input.options) // select
			s_value = o_input.selectedIndex > -1
				? o_input.options[o_input.selectedIndex].value
				: null;
		else if (o_input.length > 0) // radiobuton
			for (var n_index = 0; n_index < o_input.length; n_index++)
				if (o_input[n_index].checked) {
					s_value = o_input[n_index].value;
					break;
				}
		this.a_fields[n_key]['v'] = s_value.replace(/(^\s+)|(\s+$)/g, '');
	}
	
	// verifica se tem erros
	var n_errors_count = 0,
		n_another, o_format_check;
	for (var n_key in this.a_fields) {
		o_format_check = this.a_fields[n_key]['f'] && a_formats[this.a_fields[n_key]['f']]
			? a_formats[this.a_fields[n_key]['f']]
			: null;

		// limpa erros anteriores se houver
		this.a_fields[n_key].n_error = null;

		// verifica campos requeridos
		if (this.a_fields[n_key]['r'] && !this.a_fields[n_key]['v']) {
			this.a_fields[n_key].n_error = 1;
			n_errors_count++;
		}
		// verifica tamanho
		else if (this.a_fields[n_key]['mn'] && String(this.a_fields[n_key]['v']).length < this.a_fields[n_key]['mn']) {
			this.a_fields[n_key].n_error = 2;
			n_errors_count++;
		}
		else if (this.a_fields[n_key]['mx'] && String(this.a_fields[n_key]['v']).length > this.a_fields[n_key]['mx']) {
			this.a_fields[n_key].n_error = 3;
			n_errors_count++;
		}
		// verifica formato
		else if (this.a_fields[n_key]['v'] && this.a_fields[n_key]['f'] && (
			(typeof(o_format_check) == 'function'
			&& !o_format_check(this.a_fields[n_key]['v']))
			|| (typeof(o_format_check) != 'function'
			&& !o_format_check.test(this.a_fields[n_key]['v'])))
			) {
			this.a_fields[n_key].n_error = 4;
			n_errors_count++;
		}
		// verifica limites
		else if (this.a_fields[n_key]['m']) {
			for (var n_key2 in this.a_fields)
				if (n_key2 == this.a_fields[n_key]['m']) {
					n_another = n_key2;
					break;
				}
			if (n_another == null)
				return this.f_alert(this.f_error(6, this.a_fields[n_key]));
			if (this.a_fields[n_another]['v'] != this.a_fields[n_key]['v']) {
				this.a_fields[n_key]['ml'] = this.a_fields[n_another]['l'];
				this.a_fields[n_key].n_error = 5;
				n_errors_count++;
			}
		}


	}

	// Coleção de mensagens de erros e efeitos de labels para campos incorretos
	var s_alert_message = '',
		e_first_error;

	if (n_errors_count) {
		for (var n_key in this.a_fields) {
			var n_error_type = this.a_fields[n_key].n_error,
				s_message = '';
				
			if (n_error_type)
				s_message = this.f_error(n_error_type + 6, this.a_fields[n_key]);

			if (s_message) {
				if (!e_first_error)
					e_first_error = o_form.elements[n_key];
				s_alert_message += s_message + "\n";
				//atribuição do estado normal do label
				if (b_dom && this.a_fields[n_key].o_tag)
					this.a_fields[n_key].o_tag.className = 'tfvHighlight';
			}
		}
		alert(s_alert_message);
		// posiciona o focus no primeiro erro encontrado
		if (e_first_error.focus && e_first_error.type != 'hidden'  && !e_first_error.disabled)
			eval("e_first_error.focus()");
		// cancela o submit do formulário se houver erros
		return false;
	}
	
	for (n_key in this.a_2disable)
		if (o_form.elements[this.a_2disable[n_key]])
			o_form.elements[this.a_2disable[n_key]].disabled = true;


	return true;
}

function validator_error(n_index) {
	var s_ = a_messages[n_index], n_i = 1, s_key;
	for (; n_i < arguments.length; n_i ++)
		for (s_key in arguments[n_i])
			s_ = s_.replace('%' + s_key + '%', arguments[n_i][s_key]);
	s_ = s_.replace('%form%', this.s_form);
	return s_
}

function get_element (s_id) {
	return (document.all ? document.all[s_id] : (document.getElementById ? document.getElementById(s_id) : null));
}

