// acrescenta as funções do form no onLoad da página //
$(document).ready(function() {
	$('form').formSubmit();
	$('input').inputMask();
	$('textarea').limited();
});

// acrescenta validação de formulário no onSubmit //
$.fn.formSubmit = function() {
	inputFocus(this);
	this.submit(function() {
		return formValid(this);
	});
}

function inputFocus(form) {
	setFocus = false;
	if($(form).attr('focus') != 'no') {
		$(form).find('input,select,textarea').filter(':enabled').each(function() {
			if(!setFocus) {
				switch(this.getAttribute('type')) {
					case 'hidden':
					case 'submit':
						break;
					default:
						setFocus = true;
						this.focus();
						return;
				}
			}
		});
	}
}

// acrescenta máscara nos campos dos formulário //
$.fn.inputMask = function() {
	this.keypress(function(event) {
		switch(this.getAttribute('param')) {
			case 'date':
				return maskDate(event, this);
				break;
			case 'deci':
				return maskNumber(event);
				break;
			case 'numb':
				return maskNumber(event, this, this.getAttribute('mask'));
				break;
			case 'alphanum':
    		return maskAlpha(event);
				break;
			case 'cpf':
			case 'cnpj':
			case 'cpfcnpj':
				return maskNumber(event, this);
				break;
		}
	});
	this.keyup(function(event) {
		switch(this.getAttribute('param')) {
			case 'deci':
				return maskFloat(event, this, this.getAttribute('mask'));
				break;
		}
	});
}

// acrescenta limite nos campos textarea //
$.fn.limited = function() {
	this.keyup(function() {
		if(this.getAttribute('param') == 'limited')
			textLimit(this, this.getAttribute('maxlength'), this.getAttribute('target'));
	});
	this.change(function() {
		if(this.getAttribute('param') == 'limited')
			textLimit(this, this.getAttribute('maxlength'), this.getAttribute('target'));
	});
}

// valida um formulário //
function formValid(form) {
	valida = true;
	$(form).find('input,select,textarea').filter(':enabled').each(function() {
		if(valida) {
			if(this.getAttribute('required')) {
				if(this.getAttribute('type') == 'radio' || this.getAttribute('type') == 'checkbox') {
					if(!isChecked($(this.form).find('input[@name="' + this.name + '"]'), this.getAttribute('validationmsg'))) {
						valida = false;
						this.focus();
						return;
					}
				}
				else if(isEmpty(this.value, this.getAttribute('validationmsg'))) {
					valida = false;
					this.focus();
					return;
				}
			}
			switch(this.getAttribute('param')) {
				case 'date':
					if(!isDate(this.value)) {
						alert('Data Inválida!');
						valida = false;
						this.focus();
					}
					break;
				case 'email':
					if(!isMail(this.value)) {
						alert('E-mail Inválido!');
						valida = false;
						this.focus();
					}
					break;
				case 'cpf':
					if(!isCPF(this.value)) {
						alert('CPF Inválido!');
						valida = false;
						this.focus();
					}
					break;
				case 'cnpj':
					if(!isCNPJ(this.value)) {
						alert('CNPJ Inválido!');
						valida = false;
						this.focus();
					}
					break;
				case 'cpfcnpj':
					if(!isCPF(this.value) && !isCNPJ(this.value)) {
						alert('CPF / CNPJ Inválido!');
						valida = false;
						this.focus();
					}
					break;
			}
			if(field1 = this.getAttribute('compare')) {
				if(!compareStr($(form).find('input[@name="' + field1 + '"]')[0].value, this.value, this.getAttribute('validationmsg'))) {
					valida = false;
					this.focus();
					return;
				}
			}
			if(validate = this.getAttribute('validate')) {
				eval('valida = ' + validate + '("' + this.value + '");');
				if(!valida) {
					if(this.getAttribute('validationmsg') != '')
						alert(this.getAttribute('validationmsg'));
					this.focus();
					return;
				}
			}
		}
	});
	return valida;
}

// verifica se uma string está vazia ou só com espaços //
function isEmpty(str, msg) {
	if($.trim(str) != '')
		return false;
	if(msg != '')
		alert(msg);
	return true;
}

// verifica se um campo tipo checkbox ou radio de um formulário foi marcado //
function isChecked(field, msg) {
	if(field.length) {
		for(i = 0; i < field.length; i++) {
			if(field[i].checked)
				return true;
		}
	}
	else if(field.checked)
		return true;
	if(msg != '')
		alert(msg);
	return false;
}

// verifica se uma string é uma data (dd/mm/aaaa) //
function isDate(str) {
	if(str.length >= 10) {
		dia = parseInt(str.substr(0, 2), 10);
		mes = parseInt(str.substr(3, 2), 10);
		ano = parseInt(str.substr(6, 4), 10);
		if(dia > 0 && dia < 32 && mes > 0 && mes < 13 && ano > 999 && ano < 10000) {
			if(mes == 2 && dia > 28) {
				if(ano % 4)
					return false;
				else if(dia > 29)
					return false;
			}
			switch(mes) {
				case 4:
				case 6:
				case 9:
				case 11:
					if(dia > 30)
						return false;
					break;
			}
		}
		else
			return false;
	}
	else if(str.length)
		return false;
	return true;
}

// verifica se uma string é um e-mail válido //
function isMail(str) {
	if(str.length)
		return(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(str));
	return true;
}

// verifica se uma string é um CPF válido //
function isCPF(str) {
	var i, j, soma;
	if(str.length) {
		if(str.length != 11)
			return false;
		j = true;
		for(i = 0; i < 9; i++) {
			if(parseInt(str.charAt(i), 10) != parseInt(str.charAt(i + 1), 10)) {
				j = false;
				break;
			}
		}
		if(j)
			return false;
		for(j = 0; j < 2; j++) {
			soma = 0;
			for(i = 0; i < 9 + j; i++)
				soma += parseInt(str.charAt(i), 10) * (10 + j - i);
			soma = 11 - (soma % 11);
			if(soma > 9)
				soma = 0;
			if(soma != parseInt(str.charAt(9 + j), 10))
				return false;
		}
	}
	return true;
}

// verifica se uma string é um CNPJ válido //
function isCNPJ(str) {
	var i, j, k, soma;
	if(str.length) {
		if(str.length != 14)
			return false;
		for(k = 0; k < 2; k++) {
			soma = 0;
			j = 5 + k;
			for(i = 0; i < 12 + k; i++) {
				soma += parseInt(str.charAt(i), 10) * j;
				if(j > 2)
					j--;
				else
					j = 9;
			}
			soma = 11 - soma % 11;
			if(soma > 9)
				soma = 0;
			if(soma != parseInt(str.charAt(12 + k), 10))
				return false;
		}
	}
	return true;
}

// compara duas strings //
function compareStr(str1, str2, msg) {
	if(str1 != str2) {
		if(msg != '')
			alert(msg);
		return false;
	}
	return true;
}

// substitui todas as ocorrências de um char por replace numa string //
function substitui(chr, rpl, str) {
	txt = str.replace(chr, rpl);
	while(txt != str) {
		str = txt;
		txt = str.replace(chr, rpl);
	}
	return str;
}

// cria data a partir de uma string (dd/mm/aaaa) //
function toDate(data) {
	if(isDate(data)) {
		dia = parseInt(data.substr(0, 2), 10);
		mes = parseInt(data.substr(3, 2), 10);
		ano = parseInt(data.substr(6, 4), 10);
		return new Date(ano, mes - 1, dia);
	}
	else
		return new Date();
}

// completa com zeros à esquerda //
function Zeros(texto, tamanho) {
	while(texto.length < tamanho)
		texto = '0' + texto;
	return texto;
}

// convert data para string (dd/mm/aaaa) //
function toDateStr(data) {
	dia = Zeros(data.getDate().toString(10), 2);
	mes = Zeros((data.getMonth() + 1).toString(10), 2);
	ano = data.getFullYear();
	return dia + '/' + mes + '/' + ano;
}

// retorna tamanho do mes //
function monthLen(mes, ano) {
	switch(mes) {
		// meses com 30 dias //
		case 4:
		case 6:
		case 9:
		case 11:
			return 30;
			break;
		// fevereiro //
		case 2:
			// se ano não for bisexto //
			if(ano % 4)
				return 28;
			else
				return 29;
			break;
		// meses com 31 dias //
		default:
			return 31;
	}
}

// adiciona em uma parte da data um número //
function dateAdd(parte, numero, data) {
	dia = data.getDate();
	mes = data.getMonth() + 1;
	ano = data.getFullYear();
	switch(parte) {
		// acrescenta dias na data //
		case 'd':
			dia += numero;
			while(dia > monthLen(mes, ano)) {
				dia -= monthLen(mes, ano);
				mes += 1;
				if(mes > 12) {
					mes = 1;
					ano += 1;
				}
			}
			break;
		// acrescenta meses na data //
		case 'm':
			mes += numero;
			while(mes > 12) {
				mes -= 12;
				ano += 1;
			}
			if(dia > monthLen(mes, ano))
				dia = monthLen(mes, ano);
			break;
		// acrescenta anos na data //
		case 'y':
			ano += numero;
			if(mes == 2 && dia == 29 && ano % 4)
				dia = 28;
			break;
		default:
			// erro de parâmetro (retorna a mesma data) //
	}
	return new Date(ano, mes - 1, dia)
}

// compara duas datas //
function compareDate(data1, data2) {
	if(data1 < data2)
		return -1;
	else if(data1 > data2)
		return 1;
	else
		return 0;
}

// compara duas datas como string (dd/mm/aaaa) //
function compareDateStr(data1, data2) {
	d1 = toDate(data1);
	d2 = toDate(data2);
	return compareDate(d1, d2);
}

// converte texto para valor numerico
function toNumber(valor) {
	return parseFloat(valor.replace(',', '.').replace('.', ''));
}

// mascara genérica de campos
function maskField(ev, accept, field, mask) {
	if(validKey(ev, accept)) {
		if(field && mask) {
			i = field.value.length;
			if(i < mask.length && i < field.maxLength) {
				c = mask.charAt(i);
				if(accept.indexOf(c) < 0)
					field.value += c;
			}
		}
	}
	else if(!cntrlChars(ev)) {
		if(jQuery.browser.msie)
			ev.returnValue = false;
		else {
			ev.preventDefault(false);
			ev.stopPropagation();
		}
		return false;
	}
}

// valida tecla pressionada
function validKey(ev, keys) {
	var key, pos;
	key = ev.charCode || ev.keyCode || 0;
	pos = keys.indexOf(String.fromCharCode(key));
	return (pos >= 0);
}

// valida teclas de controle
function cntrlChars(ev) {
	var chrs, key, pos;
	chrs = String.fromCharCode(8, 9, 13, 46); // Back, Tab, Enter e Del
	for(i = 35; i < 41; i++) // Home, End e Setas
		chrs += String.fromCharCode(i);
	for(i = 112; i < 124; i++) // F1 a F12
		chrs += String.fromCharCode(i);
	key = (!isNaN(ev.charCode) && !ev.charCode && ev.keyCode ? ev.keyCode : 0);
	pos = chrs.indexOf(String.fromCharCode(key));
	return (pos >= 0);
}

// aceita a digitação somente de números com ou sem máscara (keypress) //
function maskNumber(ev, field, mask) {
	return maskField(ev, '0123456789', field, mask)
}

// aceita a digitação somente de números com ou sem máscara (keypress) //
function maskAlpha(ev) {
	return maskField(ev, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
}

// coloca mascara em campo data (dd/mm/aaaa) [keypress] //
function maskDate(ev, campo) {
	return maskNumber(ev, campo, '99/99/9999 99:99:99');
}

// coloca mascara em campo float [keyup] //
function maskFloat(ev, campo, mask) {
	mask = parseInt((!mask ? 2 : mask), 10);
	valor = substitui('.', '', substitui(',', '', campo.value));
	valor = parseInt((!valor ? '0' : valor), 10).toString(10);
	valor = Zeros(valor, mask + 1);
	tam = valor.length;
	sinais = Math.floor((tam - 1) / 3);
	while(tam + sinais > campo.maxLength) {
		tam--;
		valor = valor.substr(0, tam);
		sinais = Math.floor((tam - 1) / 3);
	}
	inteiro = '';
	num = tam - mask;
	fracao = valor.substr(num);
	valor = valor.substr(0, num);
	for(i = 1; i < sinais; i++) {
		inteiro = '.' + valor.substr(num - (3 * i), 3) + inteiro;
		valor = valor.substr(0, num - (3 * i));
	}
	campo.value = valor + inteiro + ',' + fracao;
}

// calcula módulo //
function modulo(numero, mod, x) {
	total = 0;
	for(i = 0; i < numero.length; i++)
		total += parseInt(numero.substr(numero.length - (i + 1), 1), 10) * ((i % 8) + 2);
	digito = mod - (total % mod);
	return (digito > 9) ? x : digito;
}

// copia itens de um select para outro //
function copySel(origem, destino) {
	tam = origem.options.length;
	for(i = 0; i < tam; i++) {
		if(origem.options[i].selected) {
			var Opt = new Option();
			Opt.text = origem.options[i].text;
			Opt.value = origem.options[i].value;
			for(j = 0; j < destino.options.length; j++)
				if(Opt.text < destino.options[j].text)
					break;
			if(j < destino.options.length)
				destino.options.add(Opt, j);
			else
				destino.options.add(Opt);
			origem.remove(i);
			tam--;
			i--;
		}
	}
}

// limita campo textarea [change][keyup]
function textLimit(campo, tam, count) {
	if(campo.value.length >= tam)
		campo.value = campo.value.substr(0, tam);
	$('#' + count).html(campo.value.length + '');
}
