function jFormError(input, error) {
	// Pega o element
	var element = input.parent();
	if (element.is('.parent_label')) {
		element = element.parent();
	} else if (element.is('.duplo_label')) {
		element = element.prev();
	} else if (element.is('.duplo_parent_label')) {
		element = element.parent().parent();
	} else if (element.is('.triplo_label')) {
		element = element.prev().prev();
	} else if (element.is('.quadruplo_label')) {
		element = element.prev().prev().prev();
	} else if (input.is('.label_datepicker')) {
		element = element.parent().parent().parent();
	}
	
	// Escreve a div do erro	
	if ( $('div#jFormError').html() == null ) {
		var data = '<div id="jFormError" class="boxAvisos bordaRed">';
			data += '<p class="tipoAvisoRedErro"></p>';
			data += '</div>';
		
		$('div#base').append( data );
	}
	
	// Escreve o Erro
	$('div#jFormError p').html( error );
	$('div#jFormError').insertBefore( element );
	$('div#jFormError').show();
	
	// Sobe ate o erro
	sobeTopo( $('div#jFormError').get(0).offsetTop );
}

/*
 * $(obj).jField - Informacoes do campo
 * 
 * Cria um objeto para cada campo a ser verificado
 * Valores para type
 *					int:				[09,.]
 *					lower:			[a-z]
 *					lowers:			[a-z??????]
 *					upper:			[A-Z]
 *					uppers:			[A-Z??????]
 *					alpha:			[a-zA-Z]
 *					alphas:			[a-zA-Z??????]
 *					lowerInt:		[a-z0-9]
 *					lowersInt:		[a-z0-9??????]
 *					upperInt:		[A-Z0-9]
 *					uppersInt:		[A-Z0-9??????]
 *					alphaInt:		[a-zA-Z0-9]
 *					alphasInt:		[a-zA-Z0-9??????]
 */
jQuery.fn.jField = function(options){
	// Inicial as configuracoes
	var options = options || {};

	// Configuracoes basicas ou nao	
	options.name				= options.name;
	options.minLength			= options.minLength || 0;
	options.minLengthError	= options.minLengthError || false;
	options.type 				= options.type || 'alphasInt';
	options.typeError			= options.typeError || false;
	options.empty				= options.empty || 'yes';
	options.emptyError		= options.emptyError || false;
	options.showError		= options.showError || true;
	options.showIcon		= options.showIcon || 'true';
	options.telDDD			= options.telDDD || false;

	// Metodos para o atributo	
	var jField = this;
	jField.options = options;
	
	// Validacao imediata
	this.keyup(function(event){
		$.jForm.checkField( jField, this.id );
	});
	
	// Formata Valores Reais
	if (options.type == 'currency')
	{
		//onkeypress="reais(this,event)" onkeydown="backspace(this,event)"
		this.keypress(function(event){
			reais(this, event);
		});
		
		this.keydown(function(event){
			backspace(this, event);
		});
	}
	
	// Format CNPJ
	if (options.type == 'cnpj') {
		this.maskedinput('99.999.999/9999-99');
	}
	
	// Valida imediata para SELECT
	if (options.type == 'select')
	{
		this.change(function(){
			$.jForm.checkField( jField, this.id );
		});
	}
	
	// Retorna o objeto jQuery + jField
	return jField;
}

/*
 * $(obj).jForm - Informacoes do formulario
 *
 * Pega os campos de $(obj).jField e, quando enviado, chama $.jForm
 */
jQuery.fn.jForm = function(jFields, messageBox){
	// Inicializa os campos
	var jForm 		= {};
	jForm.jFields	= jFields || {};
	
	// Configuracoes do jForm
	jForm.config 				= {}
	jForm.config.messageBox	= messageBox || 'msgErro';
	
	// Check inicial, eh requirido ?
	$.jForm.checkRequireds( jForm );
	
	// Form Enviado
	this.submit(function(){
		var valid = $.jForm.checkFields( jForm );
		
		if (!valid) {
			return false;
		} else {
			$.jForm.floatlizeFields( jForm );
		}
	});
	
	return jForm;
}

/*
 * $.jForm - Checagem do formulario
 *
 * Quando o formulario e enviado, chama-se o $.jForm e faz a checagem
 */
$.jForm = {
	// Remove todas as classes de validacao e deixa apenas a que for ativada
	activeClass:
		function( jField, id, className ){
			var showIcon = jField.options.showIcon;
			
			if (showIcon == 'false')
				return false;
		
			//$('label#label_' + id).removeClass('obrigatorio');
			//$('label#label_' + id).removeClass('naoValida');
			//$('label#label_' + id).removeClass('valida');
			$('input#' + id).parents('label').removeClass('obrigatorio');
			$('input#' + id).parents('label').removeClass('naoValida');
			$('input#' + id).parents('label').removeClass('valida');
			
			if (className != false)
				$('input#' + id).parents('label').addClass(className);
				//$('label#label_' + id).addClass( className );
		}
	
	// Diz se o valor e valido ou nao, retorna a mensagem de erro
	,isValid:
		function( jField, id ){
			var minLength  		= jField.options.minLength;
			var minLengthError  	= jField.options.minLengthError;
			var type 				= jField.options.type;
			var typeError 			= jField.options.typeError;
			var value 				= jField.val();
			var empty				= jField.options.empty;
			var emptyError 			= jField.options.emptyError;
			var telDDD				= jField.options.telDDD;
			var output 				= {valid: true, empty: false, error: false, showError: true};
			
			if (type == 'select')
			{
				if (empty == 'no' && (value == 0 || value == '0'))
				{
					output = {valid: false, empty: true, error: 'Selecione um valor em "' + jField.options.name + '"' };
				}
				else
				{
					output.valid = true;
					output.empty = true;
					output.error = false;
				}
			}
			else
			{
				// Regex Match
				if (type == 'int' && value.match(/[^\d]/))
				{
					jField.val( value.replace(/\D/g, '') );
					output = {valid: false, error: 'Preencha apenas com n&uacute;meros o campo "' + jField.options.name + '"' };
				}
				else if (type == 'cel' && (value.match(/[^\d]/) || (value.substr(0,1) != 7 && value.substr(0,1) != 8 && value.substr(0,1) != 9))) {
					jField.val( value.replace(/\D/g, '') );

					output = {valid: false, error: 'Preencha com um n&uacute;mero v&aacute;lido o campo "' + jField.options.name + '"' };
				}
				else if (type == 'currency' && !value.match(/^([0-9,.]+)$/))
				{
					output = {valid: false, error: 'Coloque valores inteiros sem pontos e centavos separados por v&iacute;rgula em "' + jField.options.name + '". Exemplo 12345,67' };
				}
				else if (type == 'date' && !value.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/))
				{
					output = {valid: false, error: 'O formato da data em "' + jField.options.name + '" deve ser dd/mm/aaaa. Exemplo 04/10/2006' };
				}
				else if (type == 'date-biggest')
				{
					if (!value.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)) {
						output = {valid: false, error: 'O formato da data em "' + jField.options.name + '" deve ser dd/mm/aaaa. Exemplo 04/10/2006' };
					} else {
						var parts = value.split('/');
						var valueDate = new Date(new Number(parts[2]), (new Number(parts[1])) - 1, new Number(parts[0]));
						var atualDate = new Date();
						
						if (valueDate.getTime() < atualDate.getTime()) {
							output = {valid: false, error: 'A data em "' + jField.options.name + '" deve ser maior que a data atual' };
						}
					}
				}
				else if (type == 'float' && !value.match(/^([0-9]+\,?([0-9]{0,}))$/))
				{
					output = {valid: false, error: 'As casas decimais de "' + jField.options.name + '" tem que ser separado por v&iacute;rgula. Exemplo 9,99' };
				}
				else if (type == 'email' && !value.match(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/))
				{
					output = {valid: false, error: 'Preencha o campo "' + jField.options.name + '" com um email v&aacute;lido' };
				}
				else if (type == 'email_confirmation')
				{
					var value2 = $('#' + id.replace('Confirma', '') ).val();
					
					if (value != value2 || !value.match(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/)) {
						output = {valid: false, error: 'O email e sua confirma&ccedil;&atilde;o devem ser iguais' };
					}
				}
				else if (type == 'password')
				{
					var value2 = $('#' + id + 'Confirma').val();
					
					if (value != value2 || value.length < minLength) {
						output = {valid: false, error: 'A senha e sua confirma&ccedil;&atilde;o devem ser iguais' };
						
						$.jForm.activeClass( jField, id + 'Confirma', 'naoValida' );
					} else {
						$.jForm.activeClass( jField, id, 'valida' );
						$.jForm.activeClass( jField, id + 'Confirma', 'valida' );
					}
				}
				else if (type == 'password_confirmation')
				{
					var value2 = $('#' + id.replace('Confirma', '') ).val();
					
					if (value != value2 || value.length < minLength) {
						output = {valid: false, error: 'A senha e sua confirma&ccedil;&atilde;o devem ser iguais' };
						
						//$.jForm.activeClass( jField, id.replace('Confirma', ''), 'naoValida' );
					} else {
						$.jForm.activeClass( jField, id, 'valida' );
						//$.jForm.activeClass( jField, id.replace('Confirma', ''), 'valida' );
					}
				}
				else if (type == 'cnpj' && !value.match(/^([0-9]{2})\.([0-9]{3})\.([0-9]{3})\/([0-9]{4})\-([0-9]{2})$/))
				{
					output = {valid: false, error: 'Preencha o campo "' + jField.options.name + '" com um cnpj v&aacute;lido. No formato 00.000.000/0000-00.' };
				}
				else if (type == 'cnpj' && value.match(/^([0-9]{2})\.([0-9]{3})\.([0-9]{3})\/([0-9]{4})\-([0-9]{2})$/))
				{
					value = value.replace(/\D/g, '');
					
					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] = value.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 ((value.charAt(12) != a[12]) || (value.charAt(13) != a[13])){
						output = {valid: false, error: 'Preencha o campo "' + jField.options.name + '" com um cnpj v&aacute;lido. No formato 00.000.000/0000-00.' };
					}
				}
				
				if ((type == 'tel' || type == 'cel') && telDDD != false) {
					var value2 = $('#' + telDDD).val();
					
					if (value2.match(/[^\d]/) || value2.length != 2 || value.match(/[^\d]/)) {
						output = {valid: false, error: 'Coloque um DDD v&aacute;lido para o campo "' + jField.options.name + '".' };
					}
				}
				
				if (output.valid == false && typeError != false)
					output.error = typeError;				
				
				// Not Empty
				if (empty == 'no' && !value)
				{
					output.error = emptyError || '&Eacute; obrigat&oacute;rio o preenchimento de "' + jField.options.name + '"';
					output.empty = true;
				}
				
				// Min Length
				if (value && value.length < minLength)
				{
					output.error = minLengthError || 'Os caracteres m&iacute;nimos para "' + jField.options.name + '" s&atilde;o ' + minLength;
					output.empty = true;
				}
				
				// Empty
				if (empty == 'yes' && !value)
				{
					output.valid = true;
					output.empty = true;
					output.error = false;
					output.showError = false;
					
					//alert('label#label_' + id + ' - ' + $('label#label_' + id).css('display'));
				}
				//alert( 'label#label_' + id + ' - ' + $('label#label_' + id).css('display') );
				
				// Nao esta visivel
				if ($('label#label_' + id).css('display') == 'none')
				{
					output.valid = true;
					output.empty = true;
					output.error = false;
					output.showError = false;
				}
			}
			
			return output;
		}
	
	// Diz se o campo eh obrigatorio ou nao
	,isRequired:
		function(jField){
			if (jField.options.empty == 'yes')
				return false;
			
			return true;
		}
	
	// Ve se o valor e valido ou nao, muda class do label
	,checkField:
		function( jField, id ){
			var output = $.jForm.isValid( jField, id );
			
			// O campo esta validado, e pode estar vazio
			if (output.showError == false)
			{
				$.jForm.activeClass( jField, id, false );
				
				return output;
			}
			
			// Ocorreu um erro na validacao
			if (output.error != false)
				$.jForm.activeClass( jField, id, 'naoValida' );
			else
				$.jForm.activeClass( jField, id, 'valida' );
			
			return output;
		}
	
	// Para cada jField ve se e valido e retorna o erro no DIV
	,checkFields:
		function( jForm ){
			var error = 'nothing';
			for (id in jForm.jFields)
			{
				var output = $.jForm.checkField( jForm.jFields[id], id );
	
				if (output.error != false && error == 'nothing') {
					error = output.error;
					break;
				}
			}
			
			if (error != 'nothing')
			{
				//if ($('div#' + jForm.config.messageBox + ' p.tipoAvisoDescricao').html() == null)
				//	$('div#' + jForm.config.messageBox).html( error );
				//else
				//	$('div#' + jForm.config.messageBox + ' p.tipoAvisoDescricao').html( error );
				
				//$('div#' + jForm.config.messageBox).fadeIn('fast');
				
				//if (typeof (sobeTopo) == 'function')
				//	sobeTopo(150);
				jFormError( jForm.jFields[id], error );
					
				return false;
			}
			
			return true;
		}
	
	// Para cada jField ve se eh requirido ou nao ... coloca a classe
	,checkRequireds:
		function( jForm ){
			for (id in jForm.jFields)
			{
				var required = $.jForm.isRequired( jForm.jFields[id], id );
				var type = jForm.jFields[id].options.type;
				var value = jForm.jFields[id].val();
				var showIcon = jForm.jFields[id].options.showIcon;

				if (((required && !value && type != 'select') || (type == 'select' && (value == 0 || value == '0'))) && showIcon == 'true') {
					$('input#' + id).parent('label').addClass('obrigatorio');
					//$('label#label_' + id).addClass('obrigatorio');
				}
			}
		}
	
	// Troca virgulas(,) por pontos(.) pro MySQL entender
	,floatlizeFields:
		function( jForm ){
			for (id in jForm.jFields)
			{
				var jField = jForm.jFields[id];
				var type = jField.options.type;
				var value = jField.val();
				
				if (type == 'float' || type == 'currency')
				{
					value = value.replace(/\./g, '');
					value = value.replace(/\,/g, '.');
					jField.val( value );
				}
			}
		}
};


/////// Mascaramento ////////
documentall = document.all;
/*
* fun??o para formata??o de valores monet?rios retirada de
* http://jonasgalvez.com/br/blog/2003-08/egocentrismo
*/

function formatamoney(c) {
	var t = this; if(c == undefined) c = 2;		
	var p, d = (t=t.split("."))[1].substr(0, c);
	for(p = (t=t[0]).length; (p-=3) >= 1;) {
		t = t.substr(0,p) + "." + t.substr(p);
	}
	return t+","+d+Array(c+1-d.length).join(0);
}

String.prototype.formatCurrency=formatamoney

function demaskvalue(valor, currency){
	/*
	* Se currency ? false, retorna o valor sem apenas com os n?meros. Se ? true, os dois ?ltimos caracteres s?o considerados as 
	* casas decimais
	*/
	var val2 = '';
	var strCheck = '0123456789';
	var len = valor.length;
	if (len== 0){
		return 0.00;
	}

	if (currency ==true){	
		/* Elimina os zeros ? esquerda 
		* a vari?vel  <i> passa a ser a localiza??o do primeiro caractere ap?s os zeros e 
		* val2 cont?m os caracteres (descontando os zeros ? esquerda)
		*/
		
		for(var i = 0; i < len; i++)
			if ((valor.charAt(i) != '0') && (valor.charAt(i) != ',')) break;
		
		for(; i < len; i++){
			if (strCheck.indexOf(valor.charAt(i))!=-1) val2+= valor.charAt(i);
		}

		if(val2.length==0) return "0.00";
		if (val2.length==1)return "0.0" + val2;
		if (val2.length==2)return "0." + val2;
		
		var parte1 = val2.substring(0,val2.length-2);
		var parte2 = val2.substring(val2.length-2);
		var returnvalue = parte1 + "." + parte2;
		return returnvalue;
		
	}
	else{
			/* currency ? false: retornamos os valores COM os zeros ? esquerda, 
			* sem considerar os ?ltimos 2 algarismos como casas decimais 
			*/
			val3 ="";
			for(var k=0; k < len; k++){
				if (strCheck.indexOf(valor.charAt(k))!=-1) val3+= valor.charAt(k);
			}			
	return val3;
	}
}

function reais(obj,event){

var whichCode = (window.Event) ? event.which : event.keyCode;
/*
Executa a formata??o ap?s o backspace nos navegadores !document.all
*/
if (whichCode == 8 && !documentall) {	
/*
Previne a a??o padr?o nos navegadores
*/
	if (event.preventDefault){ //standart browsers
			event.preventDefault();
		}else{ // internet explorer
			event.returnValue = false;
	}
	var valor = obj.value;
	var x = valor.substring(0,valor.length-1);
	obj.value= demaskvalue(x,true).formatCurrency();
	return false;
}
/*
Executa o Formata Reais e faz o format currency novamente ap?s o backspace
*/
FormataReais(obj,'.',',',event);
} // end reais


function backspace(obj,event){
/*
Essa fun??o basicamente altera o  backspace nos input com m?scara reais para os navegadores IE e opera.
O IE n?o detecta o keycode 8 no evento keypress, por isso, tratamos no keydown.
Como o opera suporta o infame document.all, tratamos dele na mesma parte do c?digo.
*/

var whichCode = (window.Event) ? event.which : event.keyCode;
if (whichCode == 8 && documentall) {	
	var valor = obj.value;
	var x = valor.substring(0,valor.length-1);
	var y = demaskvalue(x,true).formatCurrency();

	obj.value =""; //necess?rio para o opera
	obj.value += y;
	
	if (event.preventDefault){ //standart browsers
			event.preventDefault();
		}else{ // internet explorer
			event.returnValue = false;
	}
	return false;

	}// end if		
}// end backspace

function FormataReais(fld, milSep, decSep, e) {
var sep = 0;
var key = '';
var i = j = 0;
var len = len2 = 0;
var strCheck = '0123456789';
var aux = aux2 = '';
var whichCode = (window.Event) ? e.which : e.keyCode;

//if (whichCode == 8 ) return true; //backspace - estamos tratando disso em outra fun??o no keydown
if (whichCode == 0 ) return true;
if (whichCode == 9 ) return true; //tecla tab
if (whichCode == 13) return true; //tecla enter
if (whichCode == 16) return true; //shift internet explorer
if (whichCode == 17) return true; //control no internet explorer
if (whichCode == 27 ) return true; //tecla esc
if (whichCode == 34 ) return true; //tecla end
if (whichCode == 35 ) return true;//tecla end
if (whichCode == 36 ) return true; //tecla home

/*
O trecho abaixo previne a a??o padr?o nos navegadores. N?o estamos inserindo o caractere normalmente, mas via script
*/

if (e.preventDefault){ //standart browsers
		e.preventDefault()
	}else{ // internet explorer
		e.returnValue = false
}

var key = String.fromCharCode(whichCode);  // Valor para o c?digo da Chave
if (strCheck.indexOf(key) == -1) return false;  // Chave inv?lida

/*
Concatenamos ao value o keycode de key, se esse for um n?mero
*/
fld.value += key;

var len = fld.value.length;
var bodeaux = demaskvalue(fld.value,true).formatCurrency();
fld.value=bodeaux;

/*
Essa parte da fun??o t?o somente move o cursor para o final no opera. Atualmente n?o existe como mov?-lo no konqueror.
*/
  if (fld.createTextRange) {
    var range = fld.createTextRange();
    range.collapse(false);
    range.select();
  }
  else if (fld.setSelectionRange) {
    fld.focus();
    var length = fld.value.length;
    fld.setSelectionRange(length, length);
  }
  return false;

}