// *********************************************************************************************************************
// *                                                                                                                   *
// *  Autor: Leandro Fernandes                                                                                         *
// *  Data: 28/01/2005                                                                                                 *
// *                                                                                                                   *
// *  Descrição:                                                                                                       *
// *  Biblioteca de validações cliente.                                                                                *
// *                                                                                                                   *
// *  Protótipo:                                                                                                       *
// *  boolean isInput(string tipo, object obj, string msg, bool requerido, string cor, int min, int max, string mask); *
// *                                                                                                                   *
// *  Parâmetros:                                                                                                      *
// *  - tipo: Tipo do campo que está sendo testado e pode ser:                                                         *
// *          "text"      = Texto comum (também é válido para tipos select)                                            *
// *          "numero"    = Apenas valores numéricos                                                                   *
// *          "moeda"     = Apenas valores monetários                                                                  *
// *          "email"     = Apenas e-mail validos                                                                      *
// *          "cpf"       = CPF válido                                                                                 *
// *          "cnpj"      = CNPJ válido                                                                                *
// *          "data"      = Data no formato dd/mm/aaaa                                                                 *
// *          "login"     = Caracteres aceitáveis para campos dos tipos login e senha                                  *
// *          "http"      = Link web válido, com o início "http://" obrigatório                                        *
// *          "fckeditor" = Verificação especial para campos de edição HTML do FCKeditor                               *
// *                        (www.fckeditor.net)                                                                        *
// *          "mask"      = Campo com formatação especial. Valores aceitáveis para a máscara:                          *
// *                        n= número não obrigatório;                                                                 *
// *                        N= número obrigatório                                                                      *
// *                        c= caracter não obrigatório                                                                *
// *                        C= caracter obrigatório                                                                    *
// *                        <cte1, cte2 ...> = lista constantes aceitáveis para a posição                              *
// *                        Obs.: Qualquer valor diferente destes é encarado como uma constante.                       *
// *  - obj: Objeto do formulário em questão.                                                                          *
// *  - msg: Mensagem que será exibida concatenada num texto padrão. Geralmente é uma referência ao campo (seu nome).  *
// *  - requerido: Indica se o campo é requerido ou não (true/false).                                                  *
// *  - cor: Cor de fundo para o campo com erro.                                                                       *
// *  - min: Valor mínimo de caracteres aceitável (para campos do tipo "numero" este parâmetro refere-se a valor       *
// *         numérico e não a número de caracteres).                                                                   *
// *  - max: Valor máximo de caracteres aceitável (para campos do tipo "numero" este parâmetro refere-se a valor       *
// *         numérico e não a número de caracteres).                                                                   *
// *                                                                                                                   *
// *  Sugestão de utilização no script de validação:                                                                   *
// *  <script>                                                                                                         *
// *    function Confirma(frm)                                                                                         *
// *    {                                                                                                              *
// *      var cor = "#FFA500";                                                                                         *
// *      if (!isInput("text", frm.nome, "Nome", true, cor))                                                           *
// *        return false;                                                                                              *
// *      if (!isInput("mask", frm.cel, "Celular", true, cor))                                                         *
// *        return false;                                                                                              *
// *      return true;                                                                                                 *
// *    }                                                                                                              *
// *  </script>                                                                                                        *
// *                                                                                                                   *
// *  Obs.: chamar a função "Confirma" no evento onSubmit do formulário: onSubmit="return Confirma(this);"             *
// *                                                                                                                   *
// *********************************************************************************************************************

// *************************************************************************
// definição das mensagens de erro
// *************************************************************************

// campo requerido

var msg_req1 = "O campo \"";
var msg_req2 = "\" é requerido.";

// valores de máximo e mínimo de caracteres

var msg_len1 = "O campo \"";
var msg_len2 = "\" deve ter no mínimo ";
var msg_len3 = " e no máximo ";
var msg_len4 = " caracteres."

// valores de máximo e mínimo para campos numéricos

var msg_num1 = "O campo \"";
var msg_num2 = "\" deve conter um valor numérico.";

var msg_val1 = "O campo \"";
var msg_val2 = "\" deve ter um valor entre ";
var msg_val3 = " e ";
var msg_val4 = "."

// moeda

var msg_moeda1 = "O campo \"";
var msg_moeda2 = "\" deve conter um valor monetário. Utilize a vírgula (,) como separador das casas decimais.";

// campo e-mail

var msg_email1 = "Você deve informar um e-mail válido para o campo \"";
var msg_email2 = "\".";

// campo cpf

var msg_cpf1 = "Você deve informar um CPF válido para o campo \"";
var msg_cpf2 = "\".";

// campo cnpj

var msg_cnpj1 = "Você deve informar um CNPJ válido para o campo \"";
var msg_cnpj2 = "\".";

// campo data

var msg_data1 = "Você deve informar uma data válida no formato \"dd/mm/aaaa\" para o campo \"";
var msg_data2 = "\".";

// campo login e definição de caracteres inválidos para este campo

var login_char_invalidos = ":;<=>?@[\]^`"; // não utilize espaço para separar os caracteres, não é necessário informar outros caracteres neste campos, pois estão fora do limete de 48 <= char <= 122 definidos na função (deve ter pelo menos 1 caracter!!!)
var msg_login1 = "Você deve informar apenas caracteres ASCII válidos para o campo \"";
var msg_login2 = "\" e também não utilize os seguintes caracteres:\n" + login_char_invalidos;

// campo http

var msg_http1 = "Você deve informar um link válido para o campo \"";
var msg_http2 = "\". Utilize \"http://\" no início do link.";

// campo do FCKeditor

var msg_fckeditor1 = "O campo \"";
var msg_fckeditor2 = "\" é requerido.";

// espaço em branco

var msg_espaco1 = "Você não deve inserir espaços em branco no campo \"";
var msg_espaco2 = "\".";

// *************************************************************************
// definição do debug
// *************************************************************************

var msg_debug = "DEBUG\n\n";
var isDebug = true;  // ativa ou desativa as mensagens de debug

// *************************************************************************
// funções auxiliares
// *************************************************************************

// verifica se um valor é número (pode ser val == NULL)
function isNumero(val)
{
  ok = true;
  i = 0;
  while (ok && i < val.length)
  {
    c = val.charAt(i);
    if ((i == 0 && c == "-") ||
        (c == 0 || c == 1 || c == 2 || c == 3 || c == 4 ||
         c == 5 || c == 6 || c == 7 || c == 8 || c == 9))
	  ok = true;
	else
	  ok = false;
	i++;
  }
  return ok;
}

// verifica se um valor é monetário (pode ser val == NULL)
function isMoeda(val)
{
  conta = 0;
  ok = true;
  i = 0;
  while (ok && i < val.length)
  {
    c = val.charAt(i);
	i++;
    if ((c == 0 || c == 1 || c == 2 || c == 3 || c == 4 ||
        c == 5 || c == 6 || c == 7 || c == 8 || c == 9 || c == ",") && conta <= 1)
    {
      if (c == ",")
        conta++;
	  ok = true;
	}
	else
	  ok = false;
  }
  return ok;
}

// validade e-mail
function isEmail(text)
{
  if (!text.length)
    return true; // não verifica, pois e-mail não é necessário
  var arroba = "@";
  var ponto = ".";
  var posponto = 0;
  var posarroba = 0; 
  for (var indice = 0; indice < text.length; indice++)
	if (text.charAt(indice) == arroba)
	{ 
	  posarroba = indice; 
	  break; 
	} 
  for (var indice = posarroba; indice < text.length; indice++)
    if (text.charAt(indice) == ponto)
    { 
      posponto = indice; 
	  break; 
	} 
  if (posponto == 0 || posarroba == 0)
    return false; 
  if (posponto == (posarroba + 1))
    return false; 
  if ((posponto + 1) == text.length)
    return false; 
  return true; 
}

// verifica espaços
function isEspaco(text)
{ 
  var espaco = " ";
  for (var i = 0; i < text.length; i++)
    if (text.charAt(i) == espaco)
      return true;
  return false; 
}

// checa CPF ou CNPJ
function isCPFCNPJ(campo, pType)
{ 
  var campo_filtrado = "", valor_1 = " ", valor_2 = " ", ch = ""; 
  var valido = false; 
  for (i = 0; i < campo.length; i++)
  {
    ch = campo.substring(i, i + 1); 
    if (ch >= "0" && ch <= "9")
    { 
      campo_filtrado = campo_filtrado.toString() + ch.toString() 
      valor_1 = valor_2; 
      valor_2 = ch; 
    } 
    if ((valor_1 != " ") && (!valido))
      valido = !(valor_1 == valor_2); 
  } 
  if (!valido)
    campo_filtrado = "12345678912"; 
  if (campo_filtrado.length < 11)
    for (i = 1; i <= (11 - campo_filtrado.length); i++)
      campo_filtrado = "0" + campo_filtrado; 
  if (pType <= 1)
    if ((campo_filtrado.substring(9,11) == checkCPF(campo_filtrado.substring(0,9))) && (campo_filtrado.substring(11,12) == ""))
      return true;
  if ((pType == 2) || (pType == 0))
    if (campo_filtrado.length >= 14)
      if (campo_filtrado.substring(12,14) == checkCNPJ(campo_filtrado.substring(0,12)))
        return true;
  return false; 
}
	
function checkCNPJ(vCNPJ)
{ 
  var mControle = ""; 
  var aTabCNPJ = new Array(5,4,3,2,9,8,7,6,5,4,3,2); 
  for (i = 1 ; i <= 2 ; i++)
  { 
    mSoma = 0; 
    for (j = 0 ; j < vCNPJ.length ; j++) 
      mSoma = mSoma + (vCNPJ.substring(j,j+1) * aTabCNPJ[j]); 
    if (i == 2 )
      mSoma = mSoma + ( 2 * mDigito ); 
    mDigito = ( mSoma * 10 ) % 11; 
    if (mDigito == 10 )
      mDigito = 0; 
    mControle1 = mControle ; 
    mControle = mDigito; 
    aTabCNPJ = new Array(6,5,4,3,2,9,8,7,6,5,4,3); 
  } 
  return ((mControle1 * 10) + mControle); 
} 
	
function checkCPF(vCPF)
{
  var mControle = "";
  var mContIni = 2, mContFim = 10, mDigito = 0; 
  for (j = 1 ; j <= 2 ; j++)
  { 
    mSoma = 0; 
    for (i = mContIni ; i <= mContFim ; i++) 
      mSoma = mSoma + (vCPF.substring((i-j-1),(i-j)) * (mContFim + 1 + j - i)); 
    if (j == 2 )
      mSoma = mSoma + ( 2 * mDigito ); 
    mDigito = ( mSoma * 10 ) % 11; 
    if (mDigito == 10)
      mDigito = 0; 
    mControle1 = mControle; 
    mControle = mDigito; 
    mContIni = 3; 
    mContFim = 11; 
  } 
  return ((mControle1 * 10) + mControle); 
}

// verifica se um valor é uma data válida no formato "dd/mm/aaaa"
function isData(vData)
{
  if (vData == 0)
    return false;
  var Parte = vData.split("/"); 
  Ano = Parte[2];
  Mes = Parte[1];
  Dia = Parte[0];
  if (Parte.join("").length != 8)
    return false;
  if (isNaN(Parte.join("")))
    return false;
  if (Ano < 1900)
    return false;
  Data1 = new Date(Ano, Mes-1, Dia);
  if (Mes < 1 || Mes > 12)
    return false;
  if (Dia < 1 || Dia > 31)
    return false;
  if (Dia > 30 || (Dia > 28 && Mes == 02 ))
  {
    D = Data1.getDate();
    if (D < Dia)		
      return false;  // dia maior que 30 em mes indevido ou fevereiro com dia 29 em ano não bissexto
  }
  Hoje = new Date();
  Ano2 = Hoje.getFullYear();
  Mes2 = Hoje.getMonth();
  Dia2 = Hoje.getDate();
  Hoje = new Date(Ano2, Mes2, Dia2);
  Data1 = Data1.getTime();
  Hoje = Hoje.getTime(); 
  /*
  if (Hoje < Data1)
    return false;  // data não deve ser maior que a data atual
  */
  return true;
}

// *************************************************************************
// funções de validação
// *************************************************************************

// insere cor no campo com erro

function colore(obj, cor)
{
  if (cor != null)
    obj.style.backgroundColor = cor; 
}

// retira cor do campo com erro

function descolore(obj)
{
  obj.style.backgroundColor = "transparent";
}

// valida campo requerido

function isRequerido(obj, msg, requerido, cor)
{
  if (requerido && !obj.value.length)
  {
    colore(obj, cor);
    alert(msg_req1 + msg + msg_req2);
    obj.focus();
    return false
  }
  else
    descolore(obj);
  return true;
}

// valida limite de caracteres

function isLimite(obj, msg, cor, min, max)
{
  if ((min != null && obj.value.length < min) || (max != null && obj.value.length > max))
  {
    colore(obj, cor);
    alert(msg_len1 + msg + msg_len2 + min + msg_len3 + max + msg_len4);
    obj.focus();
    return false;
  }
  else
    descolore(obj);
  return true;
}

// verifica se o campo NÃO tem espaço em branco
function isSemEspaco(obj, msg, cor)
{
  if (isEspaco(obj.value))
  {
    colore(obj, cor);
    alert(msg_espaco1 + msg + msg_espaco2);
    obj.focus();
    return false;
  }
  else
    descolore(obj);
  return true;
}

// verifica tamanho do conteúdo não HTML de um campo do FKCeditor (código fonte não conta)
function GetLength(nome)
{
  var oEditor = FCKeditorAPI.GetInstance(nome);
  var oDOM = oEditor.EditorDocument;
  var iLength;
  if (document.all) // Internet Explorer
  {
    iLength = oDOM.body.innerText.length;
  }
  else  // Gecko
  {
    var r = oDOM.createRange();
    r.selectNodeContents(oDOM.body);
    iLength = r.toString().length;
  }
  return iLength;
}

// função principal

function isInput(tipo, obj, msg, requerido, cor, min, max, mask)
{
    
  // testes iniciais
  
  if (isDebug && tipo == null)
  {
    alert(msg_debug + "O parâmetro \"tipo\" é obrigatório.");
    return false;
  }
  
  if (isDebug && obj == null)
  {
    alert(msg_debug + "O parâmetro \"obj\" é obrigatório.");
    return false;
  }
  
  if (isDebug && tipo == "fckeditor" && typeof(obj) != "string")
  {
    alert(msg_debug + "O parâmetro \"obj\" deve ser do tipo string quando for usado o tipo \"fckeditor\", onde a string é o nome deste campo.");
    return false;
  }
  
  if (isDebug && tipo != "fckeditor" && typeof(obj) != "object")
  {
    alert(msg_debug + "O parâmetro \"obj\" deve ser do tipo object.");
    return false;
  }
  
  if (isDebug && msg == null)
  {
    alert(msg_debug + "O parâmetro \"msg\" é obrigatório.");
    return false;
  }
  
  if (isDebug && requerido == null)
  {
    alert(msg_debug + "O parâmetro \"requerido\" é obrigatório.");
    return false;
  }
  
  if (isDebug && typeof(requerido) != "boolean")
  {
    alert(msg_debug + "O parâmetro \"requerido\" deve ser do tipo boolean.");
    return false;
  }
  
  if (isDebug && min != null && !isNumero(min))
  {
    alert(msg_debug + "O valor mínimo deve ser numérico.");
    return false;
  }
    
  if (isDebug && max != null && !isNumero(max))
  {
    alert(msg_debug + "O valor máximo deve ser numérico.");
    return false;
  }
    
  if (isDebug && requerido && min != null)
  {
    alert(msg_debug + "O campo deve ser definifo como não requerido quando forem informados valores mínimos e máximos para ele.");
    return false;
  }
  
  if (isDebug && mask != null && typeof(mask) != "string")
  {
    alert(msg_debug + "O parâmetros \"mask\" deve ser uma string.");
    return false;
  }
  
  // validação do campo

  switch (tipo)
  {
  
    // *************************************************************************
    // tipo TEXT
    // *************************************************************************
    
    case "text":    
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      //2° teste: limite de caracteres
      if (!isLimite(obj, msg, cor, min, max))
        return false;
      // tudo ok
      return true;      
      
      break
      
    // *************************************************************************
    // tipo NUMERO (para campos do tipo TEXT)
    // *************************************************************************
    
    case "numero":    
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      // 2° teste: limite de valores numéricos
      if ((min != null && obj.value < min) || (max != null && obj.value > max))
      {
        colore(obj, cor);
        alert(msg_val1 + msg + msg_val2 + min + msg_val3 + max + msg_val4);
        obj.focus();
        return false;
      }
      else
        descolore(obj);
      // 3° teste: valor numérico
      if (obj.value.length && !isNumero(obj.value))
      {
        colore(obj, cor);
        alert(msg_num1 + msg + msg_num2);
        obj.focus();
        return false
      }
      else
        descolore(obj);
      // tudo ok
      return true;      
      
      break
    
    // *************************************************************************
    // tipo MOEDA (para campos do tipo TEXT)
    // *************************************************************************
    
    case "moeda":    
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      // 2° teste: limite de valores numéricos
      if ((min != null && obj.value < min) || (max != null && obj.value > max))
      {
        colore(obj, cor);
        alert(msg_val1 + msg + msg_val2 + min + msg_val3 + max + msg_val4);
        obj.focus();
        return false;
      }
      else
        descolore(obj);
      // 3° teste: valor monetário
      if (obj.value.length && !isMoeda(obj.value))
      {
        colore(obj, cor);
        alert(msg_moeda1 + msg + msg_moeda2);
        obj.focus();
        return false
      }
      else
        descolore(obj);
      // tudo ok
      return true;      
      
      break
      
    // *************************************************************************
    // tipo EMAIL (para campos do tipo TEXT)
    // *************************************************************************
    
    case "email":    
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      // 2° teste: limite de caracteres
      if (!isLimite(obj, msg, cor, min, max))
        return false;
      // 3° teste: campo e-mail válido
      if (obj.value.length && !isEmail(obj.value))
      {
        colore(obj, cor);
        alert(msg_email1 + msg + msg_email2);
        obj.focus();
        return false
      }
      else
        descolore(obj);
      // tudo ok
      return true;      
      
      break
      
    // *************************************************************************
    // tipo CPF
    // *************************************************************************
    
    case "cpf":
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      //2° teste: limite de caracteres
      if (!isLimite(obj, msg, cor, min, max))
        return false;
      // 3° teste: cpf válido
      if (obj.value.length && !isCPFCNPJ(obj.value, 1))
      {
        colore(obj, cor);
        alert(msg_cpf1 + msg + msg_cpf2);
        obj.focus();
        return false;
      }
      else
        descolore(obj);
      // tudo ok
      return true;      
      
      break
      
    // *************************************************************************
    // tipo CNPJ
    // *************************************************************************
    
    case "cnpj":
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      //2° teste: limite de caracteres
      if (!isLimite(obj, msg, cor, min, max))
        return false;
      // 3° teste: cpf válido
      if (obj.value.length && !isCPFCNPJ(obj.value, 2))
      {
        colore(obj, cor);
        alert(msg_cnpj1 + msg + msg_cnpj2);
        obj.focus();
        return false;
      }
      else
        descolore(obj);
      // tudo ok
      return true;      
      
      break
      
    // *************************************************************************
    // tipo DATA (para campos do tipo TEXT)
    // *************************************************************************
    
    case "data":    
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      // 2° teste: limite de valores numéricos
      if ((min != null && obj.value < min) || (max != null && obj.value > max))
      {
        colore(obj, cor);
        alert(msg_val1 + msg + msg_val2 + min + msg_val3 + max + msg_val4);
        obj.focus();
        return false;
      }
      else
        descolore(obj);
      // 3° teste: valor numérico
      if (obj.value.length && !isData(obj.value))
      {
        colore(obj, cor);
        alert(msg_data1 + msg + msg_data2);
        obj.focus();
        return false
      }
      else
        descolore(obj);
      // tudo ok
      return true;      
      
      break
    
    // *************************************************************************
    // tipo HTTP
    // *************************************************************************
    
    case "http":
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      // 2° teste: limite de valores numéricos
      if ((min != null && obj.value < min) || (max != null && obj.value > max))
      {
        colore(obj, cor);
        alert(msg_val1 + msg + msg_val2 + min + msg_val3 + max + msg_val4);
        obj.focus();
        return false;
      }
      else
        descolore(obj);
      // 3° teste: string iniciando com "http://"
      if (obj.value.length && obj.value.indexOf("http://") != 0)
      {
        colore(obj, cor);
        alert(msg_http1 + msg + msg_http2);
        obj.focus();
        return false
      }
      else
        descolore(obj);
      // tudo ok
      return true;      
      
      break
      
    // *************************************************************************
    // tipo LOGIN
    // *************************************************************************
    
    case "login":
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      //2° teste: limite de caracteres
      if (!isLimite(obj, msg, cor, min, max))
        return false;
      // 3° teste: verifica se login ou senhas possue espaço
      if (obj.value.length && !isSemEspaco(obj, msg, cor))
        return false;
      // 4° teste: verifica se login ou senhas possue caracter inválido
      if (obj.value.length)
      {
        for (var i = 0; i < login_char_invalidos.length; i++)
          for (var j = 0; j < obj.value.length; j++)
            if (login_char_invalidos.charAt(i) == obj.value.charAt(j) || obj.value.charCodeAt(j) < 48 || obj.value.charCodeAt(j) > 122)
            {
              colore(obj, cor);
              alert(msg_login1 + msg + msg_login2);
              obj.focus();
              return false;
            }
            else
              descolore(obj);
      }
      // tudo ok
      return true;      
      
      break
    
    // *************************************************************************
    // tipo FCKEDITOR
    // *************************************************************************
    
    case "fckeditor":
    
      caracteres = GetLength(obj);
    
      // 1° teste: campo requerido
      if (requerido && !caracteres)
      {
        alert(msg_fckeditor1 + msg + msg_fckeditor2);
        return false;
      }
      //2° teste: limite de caracteres
      if ((min != null && caracteres < min) || (max != null && caracteres > max))
      {
        alert(msg_len1 + msg + msg_len2 + min + msg_len3 + max + msg_len4);
        return false;
      }
      // tudo ok
      return true;
      
      break
    
    // *************************************************************************
    // tipo MASK (função incompleta!!!!!!!!!!!!!!!!!!)
    // *************************************************************************
    
    case "mask":    
    
      // 1° teste: campo requerido
      if (!isRequerido(obj, msg, requerido, cor))
        return false;
      //2° teste: limite de caracteres
      if (!isLimite(obj, msg, cor, min, max))
        return false;
      // tudo ok
      return true;      
      
      break
    
    // *************************************************************************
    // erro: nenhum tipo escolhido
    // *************************************************************************
    
    default:
      if (isDebug)
        alert(msg_debug + "O tipo \"" + tipo + "\" é inexistente.");
      return false;
  }
  
}