ExtJS 4 Form: Exemplo Campos CPF e CNPJ

Neste post vou mostrar como usar campos do tipo CPF ou CNPJ com validação em um Form do Ext JS 4.

Campos de CPF e CNPJ são bem comuns no uso de sistemas brasileiros. E sempre fazer aquele algoritmo de validação é um pouco chato. Existem 2 plugin/extensões do Ext JS 4 para facilitar a inserção desses campos em um form e ainda já faz a validação se o CPF ou CNPJ é válido.

Show me the code!

Campo CPF:

Ext.define('Ux.CpfField', {
   extend: 'Ext.form.field.Text',
   alias: ['widget.cpffield'],

   autocomplete: "off",
   soNumero: false,
   maxLength: (this.soNumero) ? 11 : 14,

   initComponent: function(){
      var me = this;

      Ext.apply(Ext.form.VTypes, {
         cpf: function(b, a) {
            return me.validacpf(b);
         },
         cpfText: "CPF inválido!"
      });

      Ext.apply(me, { vtype: 'cpf' });
      me.callParent();
   },
   initEvents: function() {
      var me = this;
      var el = me.inputEl;

      el.on("keydown", me.stopEventFunction, me);
      el.on("keyup", me.formatCPF, me);
      el.on("keypress", me.stopEventFunction, me);
      el.on("focus", me.startCPF, me);
      el.on("blur", me.clearCPF, me);

      me.callParent();
   },
   KEY_RANGES: {
      numeric: [48, 57],
      padnum: [96, 105]
   },
   isInRange: function(a, b) {
      return a >= b[0] && a <= b[1];
   },
   stopEventFunction: function(a) {
      var me = this;

      var b = a.getKey();
      if (me.isInRange(b, me.KEY_RANGES.padnum)) {
         b -= 48;
      }
      if (((b >= 41 && b <= 122) || b == 32 || b == 8 || b > 186) && (!a.altKey && !a.ctrlKey)) {
         a.stopEvent();
      }
   },
   startCPF: function() {
      var me = this;
      var a = me.inputEl.dom;

      if (a.value == "") {
         a.value = "";
         if (me.soNumero) {
            a.value = "00000000000";
         } else {
            a.value = "000.000.000-00";
         }
      }
   },
   clearCPF: function() {
      var me = this;
      var a = me.inputEl.dom;
      if (a.value == "000.000.000-00" || a.value == "00000000000"){
         a.value = "";
         me.validate();
      }
   },
   formatCPF: function(k) {
      var me = this;
      var j = k.getKey();
      if (me.isInRange(j, me.KEY_RANGES.padnum)) {
         j -= 48;
      }
      var d = (me.isInRange(j, me.KEY_RANGES.numeric) ? String.fromCharCode(j) : "");
      var e = me.inputEl.dom;
      var h = (e.value.replace(/\D/g, "").substr(1) + d).replace(/\D/g, "");
      var a = h.length;
      if (d == "" && a > 0 && j == 8) {
         a--;
         h = h.substr(0, a);
         k.stopEvent();
      }
      if (e.maxLength + 1 && a >= e.maxLength) {
         return false;
      }
      if (a < 11) {
         var b = "";
         for (var c = 0; c < 11 - a; c++) {
            b = b + "0";
         }
         h = b + h;
         a = 11;
      }
      if (me.soNumero) {
         e.value = h;
      } else {
         var l = "";
         l = h.substr(0, 3) + "." + h.substr(3, 3) + "." + h.substr(6, 3) + "-" + h.substr(9);
         e.value = l;
      }
   },
   validacpf: function(e) {
      if (e == "")
         return true;
      var b;
      s = e.replace(/\D/g, "");
      if (parseInt(s, 10) == 0) {
         return false;
      }

      var iguais = true;
      for (i = 0; i < s.length - 1; i++){
         if (s.charAt(i) != s.charAt(i + 1)){
            iguais = false;
         }
      }

      if (iguais)
         return false;

      var h = s.substr(0, 9);
      var a = s.substr(9, 2);
      var d = 0;
      for (b = 0; b < 9; b++) {
         d += h.charAt(b) * (10 - b);
      }
      if (d == 0) {
         return false;
      }
      d = 11 - (d % 11);
      if (d > 9) {
         d = 0;
      }
      if (a.charAt(0) != d) {
         return false;
      }
      d *= 2;
      for (b = 0; b < 9; b++) {
         d += h.charAt(b) * (11 - b);
      }
      d = 11 - (d % 11);
      if (d > 9) {
         d = 0;
      }
      if (a.charAt(1) != d) {
         return false;
      }
      return true;
   }
});

Campo CNPJ:

Ext.define('Ux.CnpjField', {
   extend: 'Ext.form.field.Text',
   alias: ['widget.cnpjfield'],

   autocomplete: "off",
   soNumero: false,
   maxLength: (this.soNumero) ? 15 : 19,

   initComponent: function(){
      var me = this;

      Ext.apply(Ext.form.VTypes, {
         cnpj: function(b, a) {
            return me.verificaCNPJ(b);
         },
         cnpjText: "CNPJ não é válido!"
      });

      Ext.apply(me, { vtype: 'cnpj' });

      me.callParent();
   },
   initEvents: function() {
      var me = this;
      var el = me.inputEl;

      el.on("keydown", me.stopEventFunction, me);
      el.on("keyup", me.formatCNPJ, me);
      el.on("keypress", me.stopEventFunction, me);
      el.on("focus", me.startCNPJ, me);
      el.on("blur", me.clearCNPJ, me);

      me.callParent();
   },
   KEY_RANGES: {
      numeric: [48, 57],
      padnum: [96, 105]
   },
   isInRange: function(a, b) {
      return a >= b[0] && a <= b[1];
   },
   stopEventFunction: function(a) {
      var me = this;

      var b = a.getKey();
      if (me.isInRange(b, me.KEY_RANGES.padnum)) {
         b -= 48;
      }
      if (((b >= 41 && b <= 122) || b == 32 || b == 8 || b > 186) && (!a.altKey && !a.ctrlKey)) {
         a.stopEvent();
      }
   },
   startCNPJ: function() {
      var me = this;
      var a = me.inputEl.dom;

      if (a.value == "") {
         a.value = "";
         if (me.soNumero) {
            a.value = "000000000000000";
         } else {
            a.value = "000.000.000/0000-00";
         }
      }
   },
   clearCNPJ: function() {
      var me = this;
      var a = me.inputEl.dom;
      if (a.value == "000.000.000/0000-00" || a.value == "000000000000000"){
         a.value = "";
         me.validate();
      }
   },
   formatCNPJ: function(k) {
      var me = this;
      var e = me.inputEl.dom;

      var j = k.getKey();
      if (me.isInRange(j, me.KEY_RANGES.padnum)) {
         j -= 48;
      }
      var d = (me.isInRange(j, me.KEY_RANGES.numeric) ? String.fromCharCode(j) : "");
      var h = (e.value.replace(/\D/g, "").substr(1) + d).replace(/\D/g, "");

      var a = h.length;
      if (d == "" && a > 0 && j == 8) {
         a--;
         h = h.substr(0, a);
         k.stopEvent();
      }
      if (e.maxLength + 1 && a >= e.maxLength) {
         return false;
      }
      if (a < 15) {
         var b = "";
         for (var c = 0; c < 15 - a; c++) {
            b = b + "0";
         }
         h = b + h;
         a = 15;
      }
      if (me.soNumero) {
         e.value = h;
      } else {
         var l = "";
         l = h.substr(0, 3) + "." + h.substr(3, 3) + "." + h.substr(6, 3) + "/" + h.substr(9, 4) + "-" + h.substr(13);
         e.value = l;
      }
   },
   verificaCNPJ: function(a) {
      var me = this;
      if (a == "") return true;

      a = a.replace(/\D/g, "");
      a = a.replace(/^0+/, "");
      if (parseInt(a, 10) == 0) {
         return false;
      } else {
         g = a.length - 2;
         if (me.testaCNPJ(a, g) == 1) {
            g = a.length - 1;
            if (me.testaCNPJ(a, g) == 1) {
               return true;
            } else {
               return false;
            }
         } else {
            return false;
         }
      }
   },
   testaCNPJ: function(a, d) {
      var b = 0;
      var e = 2;
      var c;
      for (f = d; f > 0; f--) {
         b += parseInt(a.charAt(f - 1),10) * e;
         if (e > 8) {
            e = 2;
         } else {
            e++;
         }
      }
      b %= 11;
      if (b == 0 || b == 1) {
         b = 0;
      } else {
         b = 11 - b;
      }
      if (b != parseInt(a.charAt(d),10)) {
         return (0);
      } else {
         return (1);
      }
   }
});

Arquivo da Aplicação – Form:

Ext.Loader.setConfig({enabled: true});

Ext.require([
	'Ux.CpfField',
	'Ux.CnpjField'
]);

Ext.onReady(function() {
	
	Ext.create('Ext.form.Panel', {
		renderTo: Ext.getBody(),
		title: 'Exemplo Campos CPF e CNPJ',
		width: 250,
		bodyPadding: 5,
		fieldDefaults: {
			labelAlign: 'left',
			labelWidth: 50,
			anchor: '100%',
			msgTarget: 'under'
		},
		defaultType: 'textfield',
		items: [{
			fieldLabel: 'CPF', 
			name: 'campoCPF', 
			xtype: 'cpffield'
		},{
			fieldLabel: 'CNPJ', 
			name: 'campoCNPJ', 
			xtype: 'cnpjfield'
		}]
	});
	
});

HTML:

<html>
<head>
    <link rel="stylesheet" type="text/css" href="ext4/resources/css/ext-all.css" />
    <style type="text/css">
	    body {
			padding:20px;
		}
    </style>

    <script type="text/javascript" src="ext4/ext-all.js"></script>
    <script type="text/javascript" src="app.js"></script>
</head>
<body>
</body>
</html>

Estrutura de diretórios do exemplo:

Obs.: usei um projeto js no Eclipse para desenvolver esse exemplo.

Download do código fonte:

Github:https://github.com/loiane/extjs4-cpf-cnpj-fields

Google Code:https://code.google.com/p/extjs4-cpf-cnpj-fields/downloads/list

Disclaimer: não sou a autora desses plugins de CPF e CNPJ; apenas postei os exemplos de como usá-los aqui no blog. Quaisquer dúvidas em relação ao código do plugin, compatibilidade com outras versões do Ext JS, etc, favor perguntar no fórum do ExtJS BR nos seguintes tópicos:

CPF: http://www.extjs.com.br/forum/index.php?topic=5125.0

CNPJ: http://www.extjs.com.br/forum/index.php?topic=5124.0

Bons códigos!