ExtJS 4 Form: Exemplo Campos CPF e CNPJ

02 Aug 2011
6 mins read

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:

[code lang="js" firstline="1" toolbar="true" collapse="false" wraplines="false"]
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;
}
});
[/code]

Campo CNPJ:

[code lang="js" firstline="1" toolbar="true" collapse="false" wraplines="false"]
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);
}
}
});
[/code]

Arquivo da Aplicação - Form:

[code lang="js" firstline="1" toolbar="true" collapse="false" wraplines="false" highlight="25,29"]
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'
}]
});

});
[/code]

HTML:

[code lang="html" firstline="1" toolbar="true" collapse="false" wraplines="false"]
<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>
[/code]

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!