/*GENERIC CHECK BEGIN*/
GenericCheck = new Object();
GenericCheck.prototype = {

  successor: null,

  check: function(el) {
    if(this.successor != null) {
      this.successor.check(el);
    }
  },

  isEmpty: function(v) {
    return (v.search(/\S/) == -1);
  },

  isNumber: function(v, l) {
    if(!l) var l = (v.length > 0) ? v.length : 1;
    return (v.search(new RegExp("\\d{" + l + "}")) > -1) || (this.isEmpty(v));
  }
}
GenericCheck.instance = null;
GenericCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new GenericCheck();
  }
  return this.instance;
}
/*GENERIC CHECK END*/

/*IS EMPTY CHECK BEGIN*/
IsEmptyCheck = Class.create()
Object.extend(Object.extend(IsEmptyCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsInLengthCheck.getInstance();
  },

  check: function(el) {
    var error = "";
    if(el.getAttribute("validation").indexOf("required") > -1) {
      if(!this.isDependencyEmpty(el)) {
        error = this.switchType(el);
      }
    }

    if(this.successor != null) {
      return error + this.successor.check(el);
    }
    return error;
  },

  switchType: function(el) {
    var error;
    switch(el.type) {
      case "file":
      case "password":
      case "text":
      case "textarea":
        error = this.isEmptyText(el);
        break;
      case "select-one":
      case "select-multiple":
        error = this.isEmptySelect(el);
        break;
      default:
        error = this.isEmptyGroup(el);
    }
    return error;
  },

  isDependencyEmpty: function(el) {
    if(el.getAttribute("depends") == null) return false;
    var a = el.getAttribute("depends").split(",");
    for(var i = 0; i < a.length; i++) {
      if(this.switchType(eval("el.form." + a[i])) == "") {
        return false;
      }
    }
    return true;
  },

  isEmptyText: function(el) {
    var str = "";
    if(this.isEmpty(el.value)) {
      str += "\nErro: Campo está vazio";
    }
    return str;
  },

  isEmptyGroup: function(el) {

    var str = "";
    var group = el;
    if(el.name) {
      group = eval("el.form." + el.name);
    }
    if(group.length) {
      for(var i = 0; i < group.length; i++) {
        if(group[i].checked == true) {
          return str;
        }
      }
    } else {
      if(group.checked) {
        return str;
      }
    }
    return "\nErro: Nenhuma opção foi selecionada";
  },

  isEmptySelect: function(el) {
    var str = "";
    if(el.selectedIndex == 0) {
      str += "\nErro: Nenhuma opção foi selecionada";
    }
    return str;
  }
});
IsEmptyCheck.instance = null;
IsEmptyCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsEmptyCheck();
  }
  return this.instance;
}
/*IS EMPTY CHECK END*/

/*IS IN LENGTH CHECK BEGIN*/
IsInLengthCheck = Class.create();
Object.extend(Object.extend(IsInLengthCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsNumberCheck.getInstance();
  },

  check: function(el) {
    var error = "";
    if(el.getAttribute("maxlength") != null || el.getAttribute("minlength") != null) {
      
      switch(el.type) {
        case "file":
        case "password":
        case "text":
        case "textarea":
          error += this.isInLength(el);
          break;
      }
    }

    if(this.successor != null) {
      return error + this.successor.check(el);
    }
    return error;
  },

  isInLength: function(el) {
    var str = "";
    var es = "";
    if (el.value.length > 1) { es += "es"; }
    if(el.getAttribute("maxlength") && el.value.length > parseInt(el.getAttribute("maxlength"))) {
      str += "\nErro: Campo possui " + el.value.length + " caracter"+es+", " + (el.value.length - parseInt(el.getAttribute("maxlength"))) + " a mais do que o permitido. Coloque no máximo " + el.getAttribute("maxlength") + " caracteres";
    }
    if(el.getAttribute("minlength") && el.value.length < parseInt(el.getAttribute("minlength"))) {
      
      str += "\nErro: Campo possui " + el.value.length + " caracter"+es+", " + (parseInt(el.getAttribute("minlength") - el.value.length)) + " a menos do que o permitido. Coloque no mínimo " + el.getAttribute("minlength") + " caracteres";
    }
    return str;
  }
});
IsInLengthCheck.instance = null;
IsInLengthCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsInLengthCheck();
  }
  return this.instance;
}
/*IS IN LENGTH CHECK EBD*/

/*IS NUMBER CHECK BEGIN*/
IsNumberCheck = Class.create();
Object.extend(Object.extend(IsNumberCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsCpfCheck.getInstance();
  },

  check: function(el) {
    var error = "";
    if(el.getAttribute("validation").indexOf("integer") > -1) {
      error += this.isInteger(el);
    } else if(el.getAttribute("validation").indexOf("float") > -1) {
      error += this.isFloat(el);
    }

    if(this.successor != null) {
      return error + this.successor.check(el);
    }
    return error;
  },

  isInteger: function(el) {
    var str = "";
    if(!this.isNumber(el.value)) {
      str = "\nErro: O campo deve ter um número inteiro, sem pontos ou vírgulas";
    }
    return str;
  },

  isFloat: function(el) {
    var str = "";
    if(!this.isNumber(el.value)) {
      str = "\nErro: Campo só aceita números. Para separar a casa decimal utilize a vírgula";
    }
    return str;
  }
});
IsNumberCheck.instance = null;
IsNumberCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsNumberCheck();
  }
  return this.instance;
}
/*IS NUMBER CHECK END*/

/*IS CPF CHECK BEGIN*/
IsCpfCheck = Class.create();
Object.extend(Object.extend(IsCpfCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsPasswordCheck.getInstance();
  },

  check: function(el) {
    var error = "";
    if(el.getAttribute("validation").indexOf("cpf") > -1) {
      error += this.checkCpf(el);
    }

    if(this.successor != null) {
      return error + this.successor.check(el);
    }
    return error;
  },
  
  checkCpf: function(el) {
    if(this.isEmpty(el.value)) return "";
    var str = "";
    var sCpf = "";
    switch(parseInt(el.getAttribute("maxlength"))) {
      default: //one field, no format
        sCpf = el.value;
        break;
    }

    if(!this.isCpf(sCpf)) {
      str = "\nErro: Cpf inválido" + str;
    }

    return str;
  },
  
  isCpf: function(v) {
    var ok = false;
    var alg = 0;
    var soma1 = soma2 = 0;
    var var1 = var2 = var3 = var4 = 0;

    for(var i = 1 ; i < 11 ; i++) {
      if(v.charAt(0) != v.charAt(i)) {
        ok = true;
        break;
      }
    }

    if(!ok) {
      return false;
    }

    for(i = 0 ; i < 9 ; i++){	
      if (v.charAt(i) < '0' || v.charAt(i) > '9'){
        return false;
      }

      alg = parseInt(v.charAt(i));
      soma1 = soma1 + alg;
      soma2 = soma2 + alg * (9 - i);
    }

    var1 = 11 - ((soma1 * 1 + soma2 * 1) % 11);
    var3 = (var1 <= 9) ? var1 : 0;
    var2 = 11 - ((2 * (soma1 + var3) + soma2) % 11);
    var4 = (var2 <= 9) ? var2 : 0;

    dv = v.substring(v.length-2);
    if(dv != var3 * 10 + var4) {
      return false;
    }
    return true;
  }
});
IsCpfCheck.instance = null;
IsCpfCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsCpfCheck();
  }
  return this.instance;
}
/*IS CPF CHECK END*/

/*IS PASSWORD CHECK BEGIN*/
IsPasswordCheck = Class.create();
Object.extend(Object.extend(IsPasswordCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsEmailCheck.getInstance();
  },

  MIN: 6,
  NUMBERS: 1,      // -1 for undefined
  CHARS: 1,        // -1 for undefined
  UPPER_CASES: 1,  // Must be lower or equal to CHARS.
                   // -1 for undefined
  LOWER_CASES: 1,  // Must be lower or equal to CHARS.
                   // -1 for undefined
  check: function(el) {
    var error = "";
    if(el.type == "password" || el.getAttribute("validation").indexOf("password") > -1) {
      error += this.isValidPassword(el.value);
    }
    if(el.getAttribute("validation").indexOf("passwordcheck") > -1) {
      error += this.passwordMatch(el);
    }

    if(this.successor != null) {
      return error + this.successor.check(el);
    }
    return error;
  },

  isValidPassword: function(v) {
    if(this.isEmpty(v)) return "";
    var str = "";
    var totalN = 0;
    var totalC = 0;
    var totalU = 0;
    var totalL = 0;
    
    for(var i = 0; i < v.length; i++) {
      if(v.charAt(i).search(/\d/) > -1) {
        totalN++;
      } else {
        totalC++;
        if(v.charAt(i).search(/[A-Z]/) > -1) {
          totalU++;
        } else if(v.charAt(i).search(/[a-z]/) > -1) {
          totalL++;
        }
      }
    }

    if(totalC + totalN < this.MIN) {
      str += "\nErro: Coloque no mínimo " + this.MIN + " caracteres";
    }
    if(totalN < this.NUMBERS) {
      str += "\nErro: Coloque no mínimo " + this.NUMBERS + " número(s)";
    }
    if(totalC < this.CHARS) {
      str += "\nErro: Coloque no mínimo " + this.CHARS + " letra(s)";
    }
    /*if(totalU < this.UPPER_CASES) {
      str += "\nErro: Coloque no mínimo " + this.UPPER_CASES + " letra(s) maiúscula(s)";
    }
    if(totalL < this.LOWER_CASES) {
      str += "\nErro: Coloque no mínimo " + this.LOWER_CASES + " letra(s) minúscula(s)";
    }*/

    return str;
  },

  passwordMatch: function(el) {
    var str = "";
    if(el.value != eval("el.form." + el.name.replace("check", "")).value && !this.isEmpty(el.value)) {
      str += "\nErro: Senhas não conferem";
    }
    return str;
  }
});
IsPasswordCheck.instance = null;
IsPasswordCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsPasswordCheck();
  }
  return this.instance;
}
/*IS PASSWORD CHECK END*/

/*IS EMAIL CHECK BEGIN*/
IsEmailCheck = Class.create();
Object.extend(Object.extend(IsEmailCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsCepCheck.getInstance();
  },

  check: function(el) {
    var error = "";
    if(el.getAttribute("validation").indexOf("email") > -1) {
      error += this.checkEmail(el.value);
    }

    if(this.successor != null) {
      return error + this.successor.check(el);
    }
    return error;
  },

  checkEmail: function(v) {
    var str = "";
    if(v.search(/^([a-z\d]+[\.\_\-]?)*[a-z\d]+@(([a-z\d]+[\_\-]?)*[a-z\d]+\.)+[a-z]{2,3}$/i) == -1 && !this.isEmpty(v)) {
      str += "\nErro: Email inválido";
    }
    return str;
  }
});
IsEmailCheck.instance = null;
IsEmailCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsEmailCheck();
  }
  return this.instance;
}
/*IS EMAIL CHECK END*/

/*IS CEP CHECK BEGIN*/
IsCepCheck = Class.create();
Object.extend(Object.extend(IsCepCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsDateCheck.getInstance();
  },

  check: function(el) {
    var error = "";
    if(el.getAttribute("validation").indexOf("cep") > -1) {
      error += this.checkCep(el);
    }

    if(this.successor != null) {
      return error + this.successor.check(el);
    }
    return error;
  },

  checkCep: function(el) {
    if(this.isEmpty(el.value)) return "";
    var str = "";

    switch(parseInt(el.getAttribute("maxlength"))) {
      case 5:  //two separate fields
        if(!this.isNumber(el.value, 5) || !this.isNumber(el.form.elements[el.index + 1].value), 3) {
          str += "\nErro: O CEP deve conter apenas números"
        }
        break;
      case 9: //one field, format = 99999-999
        if(!this.isNumber(el.value.replace("-", ""), 8) || el.value.charAt(5) != "-") {
          str += "\nErro: O CEP deve estar no formato: \"99999-999\""
        }
        break
      default:  //one field no format
        if(!this.isNumber(el.value, 8) ) {
          str += "\nErro:  O CEP deve conter 8 números sem traço nem ponto"
        }
        break;
    }

    return str;
  }
});
IsCepCheck.instance = null;
IsCepCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsCepCheck();
  }
  return this.instance;
}
/*IS CEP CHECK END*/

/*IS DATE/HOUR CHECK BEGIN*/
IsDateCheck = Class.create();
Object.extend(Object.extend(IsDateCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsTelephoneCheck.getInstance();
  },

  daysInMonth: [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
  MIN_Y: 1900,
  MAX_Y: 2010,

  check: function(e) {
    var error = "";
    var val = e.getAttribute("validation");
    if(val.indexOf("dateddmmyyyy") > -1) {
      error += this.isDdMmYyyy(e);
    } else if(val.indexOf("datehhmm") > -1) {
      error += this.isHhMm(e);
    } else if(val.indexOf("datemmddyyyy") > -1) {
      error += this.isMmDdYyyy(e);
    } else if(val.indexOf("yearyyyy") > -1) {
      error += this.isDateYyyyMmDd(e.value, "01", "01");
    }

    if(this.successor != null) {
      return error + this.successor.check(e);
    }
    return error;
  },
  
  isDdMmYyyy: function(e) {
    var d, m, y;
    var str = "";
    if(e.getAttribute("maxlength") == 2) {
        d = e.value;
        m = e.form.elements[e.index + 1].value;
        y = e.form.elements[e.index + 2].value;
    } else {
      if(e.value.search(/\d{2}\/\d{2}\/\d{4}/) == -1 && !this.isEmpty(e.value)) {
        str = "\nErro: Formato de data inválido. O formato precisa ser: dd/mm/yyyy";
      }
      d = e.value.substring(0, e.value.indexOf("/"));
      m = e.value.substring(e.value.indexOf("/")+1, e.value.lastIndexOf("/"));
      y = e.value.substring(e.value.lastIndexOf("/")+1, e.value.length);
    }

    str = this.isDateYyyyMmDd(y, m, d) + str;

    return str;
  },

  isHhMm: function(e) {
    var h, m;
    var str = "";
      if(e.value.search(/\d{2}\:\d{2}/) == -1 && !this.isEmpty(e.value)) {
        str = "\nErro: Formato de hora inválido. O formato precisa ser: hh:mi";
      }
      h = e.value.substring(0, e.value.indexOf(":"));
      m = e.value.substring(e.value.lastIndexOf(":")+1, e.value.length);
      if(!this.isHour(h) && !this.isEmpty(h)) {
        str += "\nErro: Hora inválida. A hora deve ter dois dígitos numéricos entre 00 e 23";
      }
      if(!this.isMinute(m) && !this.isEmpty(m)) {
        str += "\nErro: Minuto inválido. O minuto deve ter dois dígitos numéricos entre 00 e 59";
      }
    return str;
  },

  isMmDdYyyy: function(e) {
    var d, m, y;
    var str = "";
    if(e.getAttribute("maxlength") == 2) {
        m = e.value;
        d = e.form.elements[e.index + 1].value;
        y = e.form.elements[e.index + 2].value;
    } else {
      if(e.value.search(/\d{2}\/\d{2}\/\d{4}/) == -1 && !this.isEmpty(e.value)) {
        str = "\nErro: Formato de data inválido. O formato precisa ser: mm/dd/yyyy";
      }
      m = e.value.substring(0, e.value.indexOf("/"));
      d = e.value.substring(e.value.indexOf("/")+1, e.value.lastIndexOf("/"));
      y = e.value.substring(e.value.lastIndexOf("/")+1, e.value.length);
    }

    str = this.isDateYyyyMmDd(y, m, d) + str;

    return str;
  },

  isDateYyyyMmDd: function(y, m, d) {
    var str = "";

    if(!this.isDayDd(y, m, d) && !this.isEmpty(d)) {
      str += "\nErro: Dia inválido para o mês informado. O Dia deve ter dois dígitos numéricos";
    }
    if(!this.isMonthMm(m) && !this.isEmpty(m)) {
      str += "\nErro: O Mês deve estar entre 01 e 12. O Mês deve ter dois dígitos numéricos";
    }
    if(!this.isYearYyyy(y) && !this.isEmpty(y)) {
      str += "\nErro: Os anos devem estar entre " + this.MIN_Y + " e " + this.MAX_Y + ". Anos devem ter quatro dígitos";
    }

    return str;
  },

  isHour: function(m) {
    return (m >= 0 && m <= 23);
  },

  isMinute: function(m) {
    return (m >= 0 && m <= 59);
  },

  isDayDd: function(y, m, d) {
    return (this.isDay(y, parseInt(m,10), d) && d.length == 2);
  },

  isMonthMm: function(m) {
    return (this.isMonth(m) && m.length == 2);
  },

  isYearYyyy: function(y) {
    return (this.isYear(y) && y.length == 4);
  },

  isDay: function(y, m, d) {
    if(m == 2) {
      if(((y % 4 == 0) && ((!(y % 100 == 0)) || (y % 400 == 0))) && d <= 29) {
        return true;
      }
    }
    return (d >= 1 && d <= this.daysInMonth[m]);
  },

  isMonth: function(m) {
    return (m >= 1 && m <= 12);
  },

  isYear: function(y) {
    return (y >= this.MIN_Y && y <= this.MAX_Y);
  }
});
IsDateCheck.instance = null;
IsDateCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsDateCheck();
  }
  return this.instance;
}
/*IS DATE CHECK END*/

/*IS TELEPHONE CHECK BEGIN*/
IsTelephoneCheck = Class.create();
Object.extend(Object.extend(IsTelephoneCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsDualSelectCheck.getInstance();
  },

  check: function(e) {
    var error = "";
    if(e.getAttribute("validation").indexOf("telephone") > -1) {
      error += this.checkTelephone(e);
    }

    if(this.successor != null) {
      return error + this.successor.check(e);
    }
    return error;
  },

  checkTelephone: function(e) {
    if(this.isEmpty(e.value)) return "";
    var str = "";
    switch(parseInt(e.getAttribute("maxlength"))) {
      case 2:  //two separate fields
        if(!this.isNumber(e.value + "" + e.form.elements[e.index + 1].value, 10)) {
          str += "\nErro: Deve conter 2 números para o prefíxo do estado e 8 números para o telefone";
        }
        break;
      case 10: //one field with prefix, format = 0099999999
        if(!this.isNumber(e.value, 10)) {
          str += "\nErro: O campo deve conter 10 números, sendo os 2 primeiros o prefíxo do estado";
        }
        break;
      case 11: //one field, format = 00-99999999
        if(e.value.search(/\d{9}-\d{2}/) == -1) {
          str = "\nErro: O campo deve conter 10 números nesse formato: \"00-99999999\", sendo os dois zeros o prefíxo do estado";
        }
        break;
      default:  //one field no prefix
        if(!this.isNumber(e.value, 8)) {
          str += "\nErro: O campo deve conter 8 números";
        }
        break;
    }

    return str;
  }
});
IsTelephoneCheck.instance = null;
IsTelephoneCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsTelephoneCheck();
  }
  return this.instance;
}
/*IS TELEPHONE CHECK END*/

/*IS DUAL SELECT CHECK BEGIN*/
IsDualSelectCheck = Class.create();
Object.extend(Object.extend(IsDualSelectCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = IsCnpjCheck.getInstance();
  },

  check: function(e) {
    var error = "";
    if(e.getAttribute("validation").indexOf("dualselect") > -1) {
      error += this.checkDualSelect(e);
    }

    if(this.successor != null) {
      return error + this.successor.check(e);
    }
    return error;
  },

  checkDualSelect: function(e) {
    var str = "";
    if(e.options.length<1){
      str += "Nenhuma opção foi selecionada";
    }
    return str;
  }
});
IsDualSelectCheck.instance = null;
IsDualSelectCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new IsDualSelectCheck();
  }
  return this.instance;
}
/*IS DUAL SELECT CHECK END*/

/*IS CNPJ CHECK BEGIN*/
IsCnpjCheck = Class.create();
Object.extend(Object.extend(IsCnpjCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = NoSpecialCharCheck.getInstance();
  },

  check: function(e) {
    var error = "";
    switch(e.getAttribute("datatype")) {
      case "cnpj":
        error += this.checkCnpj(e);
        break;
    }

    if(this.successor != null) {
      return error + this.successor.check(e);
    }
    return error;
  },

  checkCnpj: function(e) {
    var str = "";
    if(!IsEmptyCheck.getInstance().isEmpty(e.value)) {
      switch(parseInt(e.getAttribute("maxlength"))) {
        case 18:  //one field, format = 99.999.999/9999-99
        if(!this.isCnpj(e.value.replace(/-/g, "").replace(/\./g, "").replace(/\//g, ""))) {
          str += "\nErro: CNPJ inválido";
        }
        if(e.value.search(/\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}/) == -1) {
          str += "\nErro: O CNPJ precisa estar nesse formato: \"99.999.999/9999-99\""
        }
        break;
      }
    } else if(e.getAttribute("r") == "true") {
      str += "\nErro: Campo vazio";
    }
    return str;
  },

  isCnpj: function(v) {
  	var alg1 = 0;
    var ok = false;
    var size = v.length;

    size--;

    alg1 = v.substr(1,1);
    for (i=2; i<size-1; ++i) {
      if (alg1 != v.charAt(i)) {
        ok = true;
        break;
      }
    }
	
    if (!ok) {
      return false;
    }
	
   	if(this.modulus(v.substring(0,v.length - 2)) + "" + this.modulus(v.substring(0,v.length - 1)) != v.substring(v.length - 2,v.length)) {
   		return false;
   	}

   	return true;
  },

  modulus: function(str) {
      var sum = 0;
      var ind = 2;

      for(pos=str.length-1;pos>-1;pos=pos-1) 
          {
        sum = sum + (parseInt(str.charAt(pos)) * ind);
        ind++;
        if(str.length>11) 
                  {
          if(ind>9) ind=2;
        }
    }

      rest = sum - (Math.floor(sum / 11) * 11);

      return (rest < 2)?0:(11 - rest);
  }
});
IsCnpjCheck.instance = 0;
IsCnpjCheck.getInstance = function() {
  if(this.instance == 0) {
    this.instance = new IsCnpjCheck();
  }
  return this.instance;
}
/*IS CNPJ CHECK END*/

/*HAS SPECIAL CHARCHECK BEGIN*/
NoSpecialCharCheck = Class.create();
Object.extend(Object.extend(NoSpecialCharCheck.prototype, GenericCheck.prototype), {
  initialize: function() {
    this.successor = null;
  },

  check: function(el) {
    var error = "";
    if(el.getAttribute("validation").indexOf("nospecialchar") > -1) {
      error += this.checkSpecialChar(el.value);
    }

    if(this.successor != null) {
      return error + this.successor.check(el);
    }
    return error;
  },

  checkSpecialChar: function(v) {
    var str = "";
    if(v.search(/^([a-z\d]+[\.\_\-]?)*[a-z\d]$/i) == -1 && !this.isEmpty(v)) {
      str += "\nErro: Somente letras e números";
    }
    return str;
  }
});
NoSpecialCharCheck.instance = null;
NoSpecialCharCheck.getInstance = function() {
  if(this.instance == null) {
    this.instance = new NoSpecialCharCheck();
  }
  return this.instance;
}
/*HAS SPECIAL CHAR CHECK END*/


FormCheck = {
  RETURN_ALL_ERRORS: 1,
  RETURN_FIELD_ERRORS: 2,

  firstCheck: IsEmptyCheck.getInstance(),
  elError: "",
  allErrors: "",
  returnErrors: this.RETURN_FIELD_ERRORS,

  checkForm: function(f, s, a, t) {
    return (this.check(f.elements, f, s, a, t));
  },

  checkElements: function(eA, f, a, t) {
    s = (f) ? true : false;
    return (this.check(eA, f, s, a, t));
  },

  check: function(eA, f, s, a, t) {
    var e, label;
    for(var i = 0; i < eA.length; i++) {
      this.elError = "";
      el = eA[i];
      //console.debug(el.name);
      if(el.disabled || el.getAttribute("validation") == undefined) {
        continue;
      }
      switch(el.type) {
        case "hidden":
        case "submit":
        case "button":
        case "reset":
        case "image":
          continue;
          break;
        default:
          this.elError = this.firstCheck.check(el);
      }

      if(this.elError == "") {
        continue;
      }

      label = el.name;
      if(el.getAttribute("label") != null) {
        label = el.getAttribute("label");
      }
      this.elError = "\nCampo: " + label + this.elError;
      this.allErrors += this.elError;
      if(this.returnErrors == this.RETURN_FIELD_ERRORS) {
        break;
      }
    }

    if(this.allErrors != "") {
      this.alertStrategy("Erros encontrados:\n" + this.allErrors);
    } else {
      if(s) {
        if(a) f.action = a;
        if(t) f.target = t;
        f.submit();
      }
      return (true);
    }

    this.elError = "";
    this.allErrors = "";
    return (false);
  },

//default alert strategy
  BasicAlert: {
    alert: function(s) {
      alert(s);
    }
  },

  alertStrategy: function(s) {top.alertbox(s)}
}

formcheck = function(f, s, a, t) {
  return (FormCheck.checkForm(f, s, a, t));
}
checkElements = function(eA, f, a, t) {
  return (FormCheck.checkElements(eA, f, a, t));
}