//////////////////////////////////////////////////////////////////////////////////
//                             Form Checker
//
//  Versao: 5.3
//  Autor: Rodrigo Silva (rodrigosilva@rodrigosilva.com)
//
//	Última Modificacao: type PASSOWORD
//                      custom type CPF, CNPJ, DATE
//                      mudança no comportamento CONFIRM
//
//////////////////////////////////////////////////////////////////////////////////

// Error Messages of the Form Checker
// The @@@ will be substituted by the filedName when necessary
var cfErrorMsg_HEADER     = "Os seguintes erros foram encontrados no preenchimento deste formulário:\n\n" ;
var cfErrorMsg_TEXT       = "- Campo \"@@@\" não foi preenchido.\n" ;
var cfErrorMsg_FILE       = "- Arquivo \"@@@\" não foi selecionado.\n" ;
var cfErrorMsg_SELECT     = "- Campo \"@@@\" não foi escolhido.\n" ;
var cfErrorMsg_RADIO      = "- Campo \"@@@\" não foi escolhido.\n" ;

var cfErrorMsg_INTEIRO    = "- Campo \"@@@\" não é um número inteiro válido.\n" ;
var cfErrorMsg_ZERO       = "- Campo \"@@@\" deve ser maior que zero.\n" ;
var cfErrorMsg_NUMERICO   = "- Campo \"@@@\" não é um número válido.\n" ;
var cfErrorMsg_CPF        = "- CPF fornecido não é válido. (Formato correto: XXX.XXX.XXX-XX)\n" ;
var cfErrorMsg_CNPJ       = "- CNPJ fornecido não é válido. (Formato correto: XX.XXX.XXX/XXXX-XX)\n" ;
var cfErrorMsg_CEP        = "- CEP fornecido está preenchido de forma incorreta. (Formato correto: XXXXX-XXX)\n" ;
var cfErrorMsg_DATA       = "- Data do campo \"@@@\" está incorreta.\n" ;
var cfErrorMsg_EMAIL      = "- E-mail fornecido não é válido.\n" ;
var cfErrorMsg_CONFERE    = "- O campo \"@@@\" e sua confirmação não conferem.\n" ;

var cfErrorMsg_HORA       = "- Hora do campo \"@@@\" está incorreta.\n" ;
var cfErrorMsg_MINUTOS    = "- Minutos do campo \"@@@\" estão incorretos.\n" ;
var cfErrorMsg_DOUBLEDATE = "- A data inicial deve ser menor do que a data final.\n" ;
var cfErrorMsg_NASC       = "- Data de nascimento inválida!\n" ;
var cfErrorMsg_PASSWORD   = "- Campo \"@@@\" e sua confirmação devem ser iguais.\n" ;
var cfErrorMsg_SENHA      = "- Senha fornecida está diferente da Confirmação da senha\n" ;

////////////////////////////////////////////////////////////////////////////////
//
// Function which Checks the form
// @input:	frm - objeto Form a ser validado
// 			msg - mensagem de resultado de validacao de dados externa (customizada).
//                Caso msg = "" (ou NULL/Ausente), nao houve validação externa ou essa foi bem sucedida
//
// @output:	true/false, caso submitForm seja false, indicando o resultado da validacao
//
function checkForm( frm, msg ) {

	var iCont ;
	var errorBuff = "" ;
	var errorField = "" ;
	var campoFocus ;
    
	// Permite validaçoes customizadas
    if (msg != null) errorBuff = msg ;

	// Loops through all inputs of the form
	for ( iCont = frm.elements.length - 1 ; iCont > (-1) ; iCont-- ) {

		if ((frm.elements[iCont].getAttribute("fieldName") != null) || (frm.elements[iCont].getAttribute("fieldType") != null) && frm.elements[iCont].getAttribute("fieldTemplate") == null) {

			errorField = CheckField( frm.elements[iCont] ) 
			errorBuff =  errorField + errorBuff ;

			if ( errorField != "" ) {
				if( frm.elements[iCont].type!="hidden" && !frm.elements[iCont].disabled ) 
					campoFocus = frm.elements[iCont];
			} // if
		} // if
	} // for

	if ( errorBuff == "" ) {
		return true;
	}
	else {
		if ( campoFocus != null ){
			try { campoFocus.focus() ; }
			catch (erro){}
		}
		alert( cfErrorMsg_HEADER + errorBuff ) ;
		return false;
	}	
}


// Function checks an element of the form
// @input: Element which will be validated
// @output: Empty string or error message
function CheckField( campo ) {

	var tipo ;
    
	// Checking field type
	if ( campo.getAttribute("fieldType") != null )
		tipo = campo.getAttribute("fieldType") ;
	else
		tipo = campo.type ;

	// Switch between different types of FIELDS
    switch ( tipo ) {
      
		// Field TEXT ( DEFAULT )
		case "text" :
		
			if ( trim(campo.value)==""  )
				return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;
		

		// Field PASSWORD ( DEFAULT )
		case "password" :
		
			if ( trim(campo.value)==""  )
				return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;
		

		// Field TEXTAREA ( DEFAULT )
		case "textarea" :

			if ( trim(campo.value)==""  )
				return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;
				


		// Field HIDDEN ( DEFAULT )
		case "hidden" :

			if ( trim(campo.value)==""  )
				return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;


		// Field SELECT without multiple ( DEFAULT )
		case "select-one" : 
			if ( campo.selectedIndex <= 0 )
				return cfErrorMsg_SELECT.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;
		  


		// Field SELECT with multiple ( DEFAULT )
		case "select-multiple" : 
			if ( campo.selectedIndex < 0 )
				return cfErrorMsg_SELECT.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;
		  


		// Field RADIO ( DEFAULT )  
		case "radio" :

			var check = false;
			var radio = campo.form.elements[campo.name];

			if ( !radio.length ) 
				check = radio.checked ;

			for ( var j = 0 ; j < radio.length ; j++ ) {
				if ( radio[j].checked ) {
					check = true ;
					break ;
				}
			}
			
			if ( !check )
				return cfErrorMsg_RADIO.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;



		// Field CHECKBOX ( DEFAULT )  
		case "checkbox" :

			var check = false;
			var checkbox = campo.form.elements[campo.name];

			if ( !checkbox.length ) 
				check = checkbox.checked ;

			for ( var j = 0 ; j < checkbox.length ; j++ ) {
				if ( checkbox[j].checked ) {
					check = true ;
					break ;
				}
			}
			
			if ( !check )
				return cfErrorMsg_RADIO.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;



		// Field FILE ( DEFAULT )  
		case "file" :

			if ( trim(campo.value)==""  )
				return cfErrorMsg_FILE.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;
				

		// Field INTEGER ( fieldType )
		// INPUT TEXT representing a positive, integer number
		case "integer" :
		
			if ( trim(campo.value) == "" ) {
				if ( campo.getAttribute("fieldRequired") != null )
					return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
				else
					return "";
			}
			else
			{
				if ( checkInt(campo.value) )
				{
					if ( (parseInt(campo.value)==0) && (campo.getAttribute("fieldParam")=="nozero") )
						return cfErrorMsg_ZERO.replace( "@@@", campo.getAttribute("fieldName") ) ;
					else
						return "";
				}
				else
					return cfErrorMsg_INTEIRO.replace( "@@@", campo.getAttribute("fieldName") ) ;
			}


		// Field NUMERIC ( fieldType )
		// INPUT TEXT representing a positive number (may be fractionary)
		case "numeric" :
		
			if ( trim(campo.value) == "" ) {
				if ( campo.getAttribute("fieldRequired") != null )
					return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
				else
					return "";
			}
			else {
				
				// Testa se não contem ponto
				if ( campo.value.indexOf(".") != (-1) )
					return cfErrorMsg_NUMERICO.replace( "@@@", campo.getAttribute("fieldName") ) ;
				
				// Substitui virgula por ponto
				var valor = campo.value;
				while( valor.indexOf( "," ) != (-1) )
					valor = valor.replace("," , ".") ;
	
				// Testa se há no máximo um separador decimal
				if ( valor.split(".").length > 2 )
					return cfErrorMsg_NUMERICO.replace( "@@@", campo.getAttribute("fieldName") ) ;

				// Testa se é numero
				if ( isNaN(parseFloat(valor, 10)) )
					return cfErrorMsg_NUMERICO.replace( "@@@", campo.getAttribute("fieldName") ) ;
	
				// Testa se é positivo
				if ( parseFloat(valor,10) < 0 )
					return cfErrorMsg_NUMERICO.replace( "@@@", campo.getAttribute("fieldName") ) ;
	
				return "" ;
			}


		// Field EMAIL (fieldType)
		// INPUT TEXT representing an e-mail
		case "email" :
			if ( trim(campo.value) == "" )
			{
				if ( campo.getAttribute("fieldRequired") != null )
					return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
				else
					return "";
			}
			else
			{
				var oRegExp = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ ;
	
				if ( oRegExp.test( campo.value ) )
					return "" ;
				else
					return cfErrorMsg_EMAIL ;
			}
        



		// Field CONFIRM ( fieldType )
		// Two INPUT TEXT representing an expression and a confirmation that must match
		// Colocar o fieldType no 2o campo, e em fieldParam passsar o nome do 1o
		case "confirm" :

			if ( (campo.getAttribute("fieldRequired")!=null) && (trim(campo.value)=="") )
				return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;

			if ( trim(campo.value) != trim(campo.form[campo.getAttribute("fieldParam")].value) )
				return cfErrorMsg_CONFERE.replace( "@@@", campo.getAttribute("fieldName") ) ;

			return "" ;
			


		// CNPJ ( fieldType )
		// Um INPUT TEXT contendo apenas numeros (14 caracteres)
		case "cnpj" : // ( fieldType )
		
			if ( trim(campo.value) == "" )
			{
				if ( campo.getAttribute("fieldRequired") != null )
					return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
				else
					return "";
			}
			else
			{
				// Testa se é inteiro
				if ( ! checkInt(campo.value) )
					return cfErrorMsg_CNPJ ;
				
				// Testa se é do tamanho correto
				if ( campo.value.length != 14 )
					return cfErrorMsg_CNPJ ;
				
				return "";
				
				var numero = trim(campo.value);
				var dig_1 = 0;
				var dig_2 = 0;
				var dig_ver = 0;
				var controle_1 = 5;
				var controle_2 = 6;
				var resto = 0;
		
				for ( var j = 0 ; j < 12 ; j++ )
				{
					dig_1 = dig_1 + parseFloat( numero.substring( j, j+1 ) * controle_1 ) ;
					controle_1 = controle_1 - 1 ;
					if (j == 3)
						controle_1 = 9 ;
				}
				resto = dig_1 % 11 ;
				dig_1 = 11 - resto ;
				
				if ((resto == 0) || (resto == 1))
					dig_1 = 0 ;

				for ( j = 0 ; j < 12 ; j++) {
					dig_2 = dig_2 + parseInt(numero.substring(j, j+1) * controle_2) ;
					controle_2 = controle_2 - 1 ;
					if (j == 4)
						controle_2 = 9 ;
				}

				dig_2 = dig_2 + (2 * dig_1) ;
				resto = dig_2 % 11 ;
				dig_2 = 11 - resto ;

				if ((resto == 0) || (resto == 1))
					dig_2 = 0;
	
				dig_ver = (dig_1 * 10) + dig_2;

				if ( dig_ver != parseInt( numero.substring(12, 13) , 10 ) )
					return cfErrorMsg_CNPJ ;
				else
					return "" ;  

			}




		// Field CPF (fieldType)
		// One INPUT TEXT representing a CPF (apenas numeros)
		case "cpf" :
			if ( trim(campo.value) == "" )
			{
				if ( campo.getAttribute("fieldRequired") != null )
					return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
				else
					return "";
			}
			else
			{
				// Testa se é inteiro
				if ( ! checkInt(campo.value) )
					return cfErrorMsg_CPF ;
				
				// Testa se é do tamanho correto
				if ( campo.value.length != 11 )
					return cfErrorMsg_CPF ;
				
				var numero = trim(campo.value);
				var dv;
				
				for ( i=0 ; i <= 1 ; i++ )
				{
					dv = 0;
					
					for ( j=0 ; j < (9+i) ; j++)
						dv += parseInt( numero.substring( j, j+1 ) * ( (10+i) - j) ) ;				
						
					dv = 11 - (dv % 11);				
					if ( (dv == 10) || (dv == 11) )
						dv = 0;
	
					if ( dv != parseInt( numero.substring( (9+i), (10+i) ) ) )
						return i + " " + cfErrorMsg_CPF ;
				}
				
				return "" ;  
			}

		// Field CEP (fieldType)
		// One INPUT TEXT representing a CEP. 5 or 8 ccharacters, all numeric
		case "cep" :
			if ( trim(campo.value) == "" )
			{
				if ( campo.getAttribute("fieldRequired") != null )
					return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
				else
					return "";
			}
			else
			{
				if ( (campo.value.length != 8) && (campo.value.length != 5) )
						return cfErrorMsg_CEP.replace( "@@@", campo.getAttribute("fieldName") ) ;
				
				if ( ! checkInt(campo.value) )
					return cfErrorMsg_CEP.replace( "@@@", campo.getAttribute("fieldName") ) ;
					
				return "" ;
			}
		

		// Field DATE (fieldName )
		// Three INPUT TEXT representing a date
		case "date" :
			if ( trim(campo.value) == "" )
			{
				if ( campo.getAttribute("fieldRequired") != null )
					return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
				else
					return "";
			}
			else
			{
				var aData = campo.value.split("/");
				
				if ( aData.length !=3 )
					return cfErrorMsg_DATA.replace( "@@@", campo.getAttribute("fieldName") ) ;
				
				if ( ! (checkInt(aData[0]) && checkInt(aData[1]) && checkInt(aData[2])) )
					return cfErrorMsg_DATA.replace( "@@@", campo.getAttribute("fieldName") ) ;
				
				var data = new Date( aData[2] , aData[1] - 1 , aData[0] );
				
				if ( (data.getFullYear()!=parseInt(aData[2])) || (data.getMonth()!=parseInt(aData[1])-1) || (data.getDate()!=parseInt(aData[0])) )
					return cfErrorMsg_DATA.replace( "@@@", campo.getAttribute("fieldName") ) ;
				
				return "" ;
			}

		// DEPRECATED
		

		// Field HORA ( fieldName )
		// Two INPUT TEXT representing time in the format HH:MM
		case "hora" :
		
			if ( parseInt( eval( campo.form.name + "." + campo.getAttribute("fieldName") + "Hour.value" ) ) > 23 || eval( campo.form.name + "." + campo.getAttribute("fieldName") + "Hour.value.length" ) != 2  )
				return cfErrorMsg_HORA.replace( "@@@", campo.getAttribute("fieldName") ) ;

			if ( parseInt( eval( campo.form.name + "." + campo.getAttribute("fieldName") + "Minute.value" ) ) > 59 ||  eval( campo.form.name + "." + campo.getAttribute("fieldName") + "Minute.value.length" ) != 2  )
				return cfErrorMsg_MINUTOS.replace( "@@@", campo.getAttribute("fieldName") ) ;
			
			return "" ;



		// Field DOUBLEDATE_DP (fieldType)
		// Two INPUT TEXT representing dates generated from a DatePicker
		case "doubledate_dp" :
		
			var firstField  = campo.value ;
			var secondField = eval( campo.form.name + "." + campo.name + "_end.value" ) ;

			if ( firstField.length != dpDateFormat.length )
				return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") + " Inicial" ) ;
			
			if ( secondField.length != dpDateFormat.length )
				return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") + " Final" ) ;

			var firstDate  = generateDate( firstField, dpDateFormat ) ;
			var secondDate = generateDate( secondField, dpDateFormat ) ;

			if ( secondDate < firstDate )
				return cfErrorMsg_DOUBLEDATE.replace( "@@@", campo.getAttribute("fieldName") ) ;
			else
				return "" ;


		// exige que a data inicial seja menor que a final
		// NAO faz a validacao das datas em si, apenas compara uma com a outra
		// Exige que o campo esteja formatado no foramto brasileiro, DD/MM/YYYY
		// Para usar, basta acrescentar fieldType="doubledate" e fieldParam="<nome_do_campo_da_data_final>"
		// na 1a data (data inicial)
		case "doubledate" :
		
			// Verifica antes de tudo se o campo inicio esta preenchido
			if (campo.value==""){
				// esta vazio. Verifica se é obrigatorio
				if(campo.getAttribute("fieldName") != null)
					return cfErrorMsg_TEXT.replace( "@@@", campo.getAttribute("fieldName") ) ;
				else
					return "";
			}
			else {
			
				// verifica se a 2a data esta preenchida
				if(campo.form.elements[campo.fieldParam].value=="")
					return "";
				else {
				
					// Faz a validacao
					var IsoDate1 = "b";
					var IsoDate2 = "a";
					
					var aData1 = campo.value.split("/");
					var aData2 = campo.form.elements[campo.fieldParam].value.split("/");
					
					if ((aData1.length==3) && ((aData2.length==3))) {
						IsoDate1 = aData1[2] + "-" + aData1[1] + "-" + aData1[0];
						IsoDate2 = aData2[2] + "-" + aData2[1] + "-" + aData2[0];
					}
					
					if (IsoDate2 < IsoDate1)
						return cfErrorMsg_DOUBLEDATE;
					else
						return "";
				}
			}


		// Debug
		default :
			return "- Tipo inválido - " + tipo + "\n"; //Modo de depuração

	}
}  

// Trim function: removes leading and trailing white spaces
function trim( texto ) {
	return texto.replace(/^\s*|\s*$/g, "");
}


function checkInt(valor)
{
	var i = 0
	
	// Testa se é numero inteiro
	for ( ; i < valor.length ; i++)
	{
		if ( isNaN(parseInt(valor.substring(i,i+1))) )
			return false;
	}

	// Testa se é negativo
	if ( parseFloat(valor) < 0 )
		return false;

	return true;
}


// Function which generates a Date based on a received format
// @input: Date in string format
// @input: Date format
// @output: Date object
function generateDate( field, dateFormat ) {
	var dia, mes, ano ;
	dia = field.substring( dateFormat.indexOf( "D" ), dateFormat.lastIndexOf( "D" )+1 ) ;
	mes = field.substring( dateFormat.indexOf( "M" ), dateFormat.lastIndexOf( "M" )+1 ) ;
	ano = field.substring( dateFormat.indexOf( "Y" ), dateFormat.lastIndexOf( "Y" )+1 ) ;
//	alert( "[" + dia + "] [" + mes + "] [" + ano + "]" ) ;
	
	var date = new Date( ano, mes, dia )
	
	return date ;
}

/////////////////////////////////////////////////////////////////////////////