/**********************************************************
Função apelidade de coração do framework: Cria um array
dos forms e chama função para verificar campo a campo
**********************************************************/
function kfn_framework()
{
  var formNodes = document.getElementsByTagName("form");
  for(var i=0; i<formNodes.length; i++)
  {
    formNodes[i].kfn_validator = new kfn_formValidator(formNodes[i]);
    if(typeof formNodes[i].onsubmit != "function")
    {
      formNodes[i].onsubmit = function()
      {
        return kfn_validForm(this);
      }
    }
    else
    {
      formNodes[i].kfn_oldSubmit = formNodes[i].onsubmit;
      formNodes[i].onsubmit = function()
      {
        if(this.kfn_oldSubmit())
        {
          return kfn_validForm(this);
        }
        return false;
      }
    }
  }
}
/**********************************************************
kfn_validForm: apresenta a mensagem de erro caso tenha
**********************************************************/
function kfn_validForm(formNode)
{
  var errorMsg = "";
  var formValidator = formNode.kfn_validator;
  if(formValidator)
  {
    var focusGiven = false;
    var invalidFields = new Array();
    for(var i=0; i<formValidator.validators.length; i++)
    {
      if(formValidator.validators[i].validate())
      {
        errorMsg += formValidator.validators[i].message+"\n";
        invalidFields[invalidFields.length] = formValidator.validators[i];
        if(!focusGiven && (formValidator.validators[i].type == "text"))
        {
          formValidator.validators[i].getFocus();
          focusGiven = true;
        }
      }
    }
    if(errorMsg != "")
    {
      var error = new alertError(errorMsg);
    }
  }
  return errorMsg.length==0;
}

/**********************************************************
kfn_formValidator: chama as funções apartir dos atributos
**********************************************************/
function kfn_formValidator(formNode)
{
  this.validators = new Array();
  var fieldsArray = kfn_getTextfieldNodes(formNode);
  for(var i=0;i<fieldsArray.length;i++)
  {
    this.validators[this.validators.length] = kfn_textValidator(fieldsArray[i]);
    if(fieldsArray[i].getAttribute("kfn:filterInfo"))
    {
      addEvent(fieldsArray[i],"keyup",function(){kfn_filterField(this);});
      addEvent(fieldsArray[i],"blur",function(){kfn_filterField(this);});
    }
    if(fieldsArray[i].getAttribute("kfn:maskFormat"))
    {
      addEvent(fieldsArray[i],"keyup",function(){kfn_maskFormat(this);});
      addEvent(fieldsArray[i],"blur",function(){kfn_maskFormat(this);});
    }
  }
}

/**********************************************************
kfn_getTextfieldNodes: cria um array com os input type=text
**********************************************************/
function kfn_getTextfieldNodes(startNode)
{
  var inputsArray = new Array();
  var inputNodes = startNode.getElementsByTagName("input");
  for(var i=0; i<inputNodes.length; i++)
  {
    if(!inputNodes[i].getAttribute("type"))
    {
      inputNodes[i].setAttribute("type","text");
    }
    var fieldType = inputNodes[i].getAttribute("type").toLowerCase();
    if(fieldType == "text")
    {
      inputsArray[inputsArray.length] = inputNodes[i];
    }
  }
  return inputsArray;
}

/**********************************************************
kfn_textValidator: ver se é requerido ou passa pelas regras
de validações (ao submeter o formulario)
**********************************************************/
function kfn_textValidator(fieldNode)
{
  var obj = new kfn_abstractValidator(fieldNode);
  obj.type = "text";
  var required = false;
  if(fieldNode.getAttribute("kfn:required"))
  {
    required = fieldNode.getAttribute("kfn:required");
  }
  obj.getFocus = function()
  {
    try
    {
      fieldNode.focus();
      fieldNode.select();
    }
    catch(exception)
    {
    }
  }
  obj.isEmpty = function()
  {
    return fieldNode.value == "";
  }
  obj.isRequired = function()
  {
    return required;
  }
  obj.isValid = function()
  {
    if(obj.isEmpty())
    {
      if(obj.isRequired())
      {
        return false;
      }
      else
      {
        return true;
      }
    }
    else
    {
      for(var rule in kfn_globalRules)
      {
        if(fieldNode.getAttribute("kfn:" + rule))
        {
          if(!eval("kfn_globalRules." + rule + "(fieldNode)"))
          {
            return false;
          }
        }
      }
    }
    return true;
  }
  return obj;
}

/**********************************************************
kfn_abstractValidator: pega o texto kfn:message, e coloca o
texto flutuante no input com erro
**********************************************************/
function kfn_abstractValidator(fieldNode)
{
  this.message = "";
  this.name = fieldNode.name;
  if(fieldNode.getAttribute("kfn:message"))
  {
    this.message = fieldNode.getAttribute("kfn:message");
  }
  this.flagInvalid = function()
  {
    fieldNode.setAttribute("title", this.message);
    fieldNode.setAttribute("alt", this.message);
  }
  this.flagValid = function()
  {
    fieldNode.removeAttribute("title");
    fieldNode.removeAttribute("alt");
  }
  this.validate = function()
  {
    if(fieldNode.disabled)
    {
      this.flagValid();
      return false;
    }
    if(!this.isValid())
    {
      this.flagInvalid();
      return true;
    }
    else
    {
      this.flagValid();
      return false;
    }
  }
}

/**********************************************************
kfn_filterField: pegas as filtragens em uso
**********************************************************/
function kfn_filterField(fieldNode)
{
  var filtersArray = fieldNode.getAttribute("kfn:filterInfo").split(",");
  for(var i=0; i<filtersArray.length; i++)
  {
    var filtObj = kfn_globalFilters[filtersArray[i]];
    if(filtObj)
    {
      fieldNode.value = fieldNode.value.replace(filtObj.rex,filtObj.str)
    }
  }
}

/**********************************************************
kfn_globalFilters: regras de filtragem
**********************************************************/
var kfn_globalFilters = new Object;
kfn_globalFilters.alphanumericonly = kfn_filterInfo("[^\\w]", "");
kfn_globalFilters.alphatextonly = kfn_filterInfo("[^\\w\\s]", "");
kfn_globalFilters.numbersonly = kfn_filterInfo("[^\\d]", "");
kfn_globalFilters.lettersonly = kfn_filterInfo("[^a-zA-Z]", "");
kfn_globalFilters.nospaces = kfn_filterInfo("\\s*", "");
kfn_globalFilters.nocommas = kfn_filterInfo(",", "");
kfn_globalFilters.nodots = kfn_filterInfo("\\.", "");

/**********************************************************
kfn_filterInfo: executa a filtragem
**********************************************************/
function kfn_filterInfo(rex,replaceStr)
{
  var infoObj = new Object;
  infoObj.rex = new RegExp(rex,"g");
  infoObj.str = replaceStr;
  return infoObj;
}

/**********************************************************
kfn_globalRules.validField: executa o validField
**********************************************************/
var kfn_globalRules = new Object;
kfn_globalRules.validField = function(fieldNode)
{
  var reg = kfn_globalValids[fieldNode.getAttribute("kfn:validField")];
  if(reg)
  {
    return reg.test(fieldNode.value);
  }
  else
  {
    return true;
  }
}

/**********************************************************
kfn_globalValids: regras de validação
**********************************************************/
var kfn_globalValids = new Object;
kfn_globalValids.email = new RegExp("^[\\w\\.=-]+@[\\w\\.-]+\\.[\\w\\.-]{2,4}$");
kfn_globalValids.cpf = new RegExp("\\d{3}\\.\\d{3}\\.\\d{3}\\-\\d{2}");

/**********************************************************
kfn_alertError: mensagem de erro
**********************************************************/
function alertError(errorMsg)
{
  alert(errorMsg);
}

/**********************************************************
kfn_maskFormat: executa a formatação da mascara
**********************************************************/
function kfn_maskFormat(fieldNode)
{
  var mask = fieldNode.getAttribute("kfn:maskFormat");
  var src = fieldNode;
  var i = fieldNode.value.length;
  var endText = mask.substring(0,1);
  var text = mask.substring(i);
  if(text.substring(0,1) != endText)
  {
    src.value += text.substring(0,1);
  }
}

/**********************************************************
Função apelidade de ouvido do framework: Verifica os eventos
ocorridos na pagina visitada para chamar uma determinada função
**********************************************************/
function addEvent(obj, type, fn)
{
  if(obj.addEventListener)
  {
    obj.addEventListener(type, fn, false);
  }
  else if(obj.attachEvent)
  {
    obj["e" + type + fn] = fn;
    obj[type + fn] = function()
    {
      obj["e" + type + fn](window.event);
    }
    obj.attachEvent("on" +type, obj[type+fn]);
  }
}

addEvent(window, "load", kfn_framework);