Por que eu devo ler este artigo:Este artigo demonstra a criação de um componente CPF/CNPJ pela ferramenta Adobe Flash Builder 4.5, que permite ao digitar o CPF ou CNPJ que a respectiva máscara seja inserida automaticamente.

O referido componente tem como pai um TextInput, uma propriedade ActualText, através da qual será possível buscar o valor do campo digitado sem formatação de CPF ou CNPJ, como pode ser observado nas possibilidades apresentadas na tabela 1.

Exemplos
Valor do campo com máscara de CPF 999.999.999-99
Valor do campo sem máscara de CPF 99999999999
Valor do campo com máscara de CNPJ 99.999.999/9999-99
Valor do campo sem máscara de CNPJ 99999999999999
Tabela 1. Exemplos de apresentação para o CPF e CNPJ

O artigo Criação de componentes no adobe flash builder, publicado nesse portal, auxilia leitores iniciantes, por abordar passo a passo a criação de componentes.

Abaixo será detalhado o processo de criação do componente CPF/CNPJ. Lembrando que a definição do nome e caminho de localização do projeto do componente (ou pacote) fica a critério pessoal de você leitor.

Na figura 1 pode-se observar a definição do nome do projeto e sua localização:

  • Project Name (Nome do Projeto): CpfCnpjInput;
  • Folder (Localização do projeto): D:\WWW\CpfCnpjInput;
Criação do Projeto
Figura 1. Criação do Projeto

As demais opções devem respeitar as configurações padrão.

Um pacote que deverá conter as classes do componente deve ser criado, conforme exemplificado na figura 2.

  • Name: br.com.input
Novo Pacote
Figura 2. Novo Pacote

Dentro da pasta “br.com.input” deve ser criada a nova classe, no caso “CpfCnpjInput”, onde define-se os campos ‘Name’ e ‘Superclass’, ilustrados na Figura 3.

  • Name: CpfCnpjInput.
  • SuperClass: spark.components.TextInput.
Criação da Classe
Figura 3. Criação da Classe

Os passos realizados foram necessários para criar a estrutura de pacotes no Flash e a classe principal. Agora vamos para codificação.

Explicando a codificação do componente

Dentro do método construtor da classe, devem ser inseridos os eventos do componente.

  • O evento FlexEvent.CREATION_COMPLETE será disparado quando o componente for criado.
  • O evento FocusEvent.FOCUS_OUT será disparado sempre quando o usuário sair do foco do componente.
  • Já o evento KeyboardEvent.KEY_DOWN será disparado quando o usuário acionar alguma tecla no teclado.
  • Pela variável ActualText será possível buscar o valor do componente CPF/CNPJ sem formatação.

A codificação dos eventos pode ser observada na listagem 1.


[Bindable] public var actualText : String = ''; // Txt Sem Formatacao

public function CpfCnpjInput()
{
	super();
		
	// events listener
	this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreateComplete);
	this.addEventListener(FocusEvent.FOCUS_OUT, onFocusOut);
	this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
Listagem 1. Definição da variável actualText e Método construtor

Na listagem 2 apresenta o método Create Complete, pelo qual define-se que o componente irá receber apenas números e o máximo de caracteres que o componente pode aceitar, neste caso 18.


// on Create Complete
private function onCreateComplete(event: FlexEvent) : void 
{
	this.restrict="0-9"; // somente números
	this.maxChars=18; // máximo chars 18			
}
Listagem 2. Método do Evento Create Complete

Pelo método do evento Focus Out, apresentado na listagem 3, apenas é chamada a função que valoriza a variável ActualText, referente ao texto digitado sem formatação.


// on Focus Out
private function onFocusOut(event: FocusEvent): void 
{
	this.getActualText();
}
Listagem 3. Método do Evento Focus Out

Pelo evento Key Down é chamado o método que busca o texto digitado sem formatação e realiza as seguintes verificações:

  • Se a tecla acionada for um BACKSPACE retorna para a máscara CPF;
  • Se o texto atual sem formatação for menor ou igual a 11, é inserida a máscara de CPF no componente;
  • Se o texto atual for maior que 11 é inserida a mascara de CNPJ no componente.

A listagem 4 apresenta a codificação do evento Key Down.


// on Key Down
private function onKeyDown(event: KeyboardEvent):void {
	this.getActualText();

if ( event.keyCode == Keyboard.BACKSPACE ) 
	{
		Format.returnCPF( this );
	}
	else if ( this.actualText.length <= 11 ) 
	{
		Format.CPF( this );	
	} 
	else if ( this.actualText.length > 11 ) 
	{
		Format.CNPJ( this );								} 
}
Listagem 4. Método do Evento Key Down

Na listagem 5, fazendo uso de expressões regulares, é removida a máscara do campo retornando a String sem formatação.


// Busca o texto atual sem mascara
private function getActualText():void {
	var ponto : RegExp = /\./g;
	var hifen : RegExp = /\-/g;
	var barra : RegExp = /\//g;
	
	var str : String = '';
	str = this.text.replace(ponto, ""); // remove pontos
	str = str.replace(hifen, ""); // remove hifen
	str = str.replace(barra, ""); // remove barra
	
	this.actualText = str;				
}
Listagem 5. Método que retorna o texto digitado sem máscara

A codificação completa da Classe CpfCnpjInput é apresentada na listagem 6.


package br.com.input
{
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
	
	import mx.events.FlexEvent;
	
	import spark.components.TextInput;
	
	public class CpfCnpjInput extends TextInput
	{
		[Bindable] public var actualText : String = ''; // Txt sem formatacao
		
		public function CpfCnpjInput()
		{
			super();
			
			// events listener
			this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreateComplete);
			this.addEventListener(FocusEvent.FOCUS_OUT, onFocusOut);
			this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
		}
		
		// on Create Complete
		private function onCreateComplete(event: FlexEvent) : void 
		{
			this.restrict="0-9"; // somente nros
			this.maxChars=18; 	 // maximo chars 18			
		}
		
		// on Focus Out
		private function onFocusOut(event: FocusEvent): void 
		{
			this.getActualText();
		}
		
		// on Key Down
		private function onKeyDown(event: KeyboardEvent):void {
			this.getActualText();

			if ( event.keyCode == Keyboard.BACKSPACE ) 
			{
				Format.returnCPF( this );
			}
			else if ( this.actualText.length <= 11 ) 
			{
				Format.CPF( this );	
			} 
			else if ( this.actualText.length > 11 ) 
			{
				Format.CNPJ( this );								
			} 
		}
		
		// busca o texto atual sem mascara
		private function getActualText():void {
			var ponto : RegExp = /\./g;
			var hifen : RegExp = /\-/g;
			var barra : RegExp = /\//g;
			
			var str : String = '';
			str = this.text.replace(ponto, ""); // remove pontos
			str = str.replace(hifen, ""); 		// remove hifen
			str = str.replace(barra, ""); 		// remove barra
			
			this.actualText = str;				
		}		
	}
}
Listagem 6. Código completo da classe CpfCnpjInput

Prosseguindo com a criação do componente, deve ser declaradas as variáveis da classe Format que será responsável pela formatação da máscara, como pode ser observado na listagem 7.


// var genericas
private static var ponto : RegExp = /\./g;		
private static var hifen : RegExp = /\-/g;		
private static var barra : RegExp = /\//g;		
		
// var cpf
private static var dig3 : RegExp = /^\d{3}$/;
private static var dig9 : RegExp = /^\d{3}.\d{3}.\d{3}$/;
		
// var cnpj
private static var cnpj : RegExp = /^\d{2}.\d{3}.\d{3}\/\d{4}-\d{2}$/;		
		
// var return cpf
public static var returnMaskCPF : RegExp = /^\d{2}.\d{3}.\d{3}\/\d{3}$/;
Listagem 7. Variáveis da classe Format

Após a codificação das variáveis, deve-se implementar o primeiro método responsável pela formatação da máscara de CPF, com as seguintes características:

  1. Se a quantidade de caracteres digitados pelo usuário for menor que 3, apenas retorna para o método que chamou, não sendo necessário colocar a máscara.
  2. Verifica se o tamanho do texto é maior ou igual a 3 e menor que 9.
  3. Em seguida localiza o último ponto se existir, copia 3 posições e realiza um teste utilizando expressão regular, se o tamanho da string copiada for de 3 caracteres então insere um ponto no final da string (está parte do código é responsável por inserir a máscara no formato ###.###.###).
  4. Outra verificação que deve ser realizada é se o tamanho do texto é igual a 9 caracteres, quando essa condição for verdadeira, deve ser inserido o traço.

Na listagem 8 é apresentado o método responsável pela formatação da mascara de CPF.


public static function CPF(txt:CpfCnpjInput):void {
	// não é necessário colocar a mascara!
	if ( txt.text.length < 3 ) 
	{
		return;
	}
			
	if ( txt.text.length >= 3 && txt.text.length < 9 ) 
	{
		// encontra o último ponto se existir 
		var ponto : int = txt.text.lastIndexOf(".", txt.text.length);  
				
		var start : int = ponto + 1;
		var tam   : int = 3;
				
		// copia apenas 3 dígitos
		var substr : String = txt.text.substr(start, tam);
				
		if ( dig3.test(substr) ) 
		{
			// insere o ponto
			txt.text += "."; 
		}
	}
	else  
	{
		if ( dig9.test(txt.text) ) 
		{
			// insere o traço
			txt.text += "-";	
		}
	}			

	posicionaCursorFinal(txt);
}
Listagem 8. Método responsável pela formatação de máscara de CPF

A listagem 9 apresenta o método pela formatação da máscara de CNPJ. Basicamente neste método é removida a máscara atual do componente, criando à máscara e retornando o CNPJ formatado.

 
public static function CNPJ(txt:CpfCnpjInput):void {
	var str : String = "";
			
	str = txt.text.replace(ponto, ""); // remove pontos
	str = str.replace(hifen, ""); // remove hifen
			
	var doisDigitosPonto : String = str.substr(0, 2);  // copia 2 digitos
	var tresDigitosPonto : String = str.substr(2, 3);  // copia 3 digitos 
	var tresDigitosBarra : String = str.substr(5, 3);  // copia 3 digitos
	var quatDigitosTraco : String = str.substr(8, 4);  // copia 4 digitos
	var doisDigitosFim   : String = str.substr(12, 2); // copia 2 digitos
			
	// novo cnpj
	var newCNPJ : String = 
	doisDigitosPonto + "." + 
	tresDigitosPonto + "." + 
	tresDigitosBarra + "/" + 
	quatDigitosTraco + "-" + 
	doisDigitosFim; 
			
	if ( cnpj.test(newCNPJ) ) 
	{
		txt.text = newCNPJ;
	}
		
	posicionaCursorFinal(txt);
}
Listagem 9. Método responsável pela formatação de máscara de CNPJ

Na listagem 10 é realizado o retorno da máscara do CPF. Neste método verifica se o texto digitado pelo usuário possui a quantidade de caracteres para inserir a máscara de CPF novamente.


// ** Exemplo.: 01.622.347/996
public static function returnCPF(txt:CpfCnpjInput):void {
	if ( returnMaskCPF.test(txt.text) ) 	
	{
		var str : String = "";
		str = txt.text.replace(ponto, ""); // remove pontos
		str = str.replace(barra, ""); // remove barra
				
		var tresDigitosPonto0 : String = str.substr(0, 3); // copia 3 digitos 
		var tresDigitosPonto3 : String = str.substr(3, 3); // copia 3 digitos 
		var tresDigitosTraco6 : String = str.substr(6, 3); // copia 3 digitos 
		var doisDigitosTraco9 : String = str.substr(9, 2); // copia 2 digitos 
				
		// novo cnpj
		var newCPF : String = 
			tresDigitosPonto0 + "." +
			tresDigitosPonto3 + "." +
			tresDigitosTraco6 + "-" +
			doisDigitosTraco9; 				
		
			txt.text = newCPF;
		}	
			
	posicionaCursorFinal(txt);
}
Listagem 10. Método responsável retorno da mascara de CPF

O método que posiciona o cursor no final do campo pode ser observado na listagem 11.


// posiciona o cursor no final	
private static function posicionaCursorFinal(txt:CpfCnpjInput):void {
	txt.selectRange(txt.text.length+1, txt.text.length+1); 
}
Listagem 11. Método responsável por posicionar o cursor no final do campo

A listagem 12 apresenta a codificação completa da classe Format.


package br.com.input
{
	import mx.controls.TextInput;
	
	// classe Static Para Formatar as Mask
	public class Format
	{
		// var genericas
		private static var ponto : RegExp = /\./g;		
		private static var hifen : RegExp = /\-/g;		
		private static var barra : RegExp = /\//g;		
		
		// var cpf
		private static var dig3 : RegExp = /^\d{3}$/;
		private static var dig9 : RegExp = /^\d{3}.\d{3}.\d{3}$/;
		
		// var cnpj
		private static var cnpj : RegExp = /^\d{2}.\d{3}.\d{3}\/\d{4}-\d{2}$/;		
		
		// var return cpf
		public static var returnMaskCPF : RegExp = /^\d{2}.\d{3}.\d{3}\/\d{3}$/; 
		
		// ******************************************* //
		// **	Format Mask CPF						** //
		// ******************************************* //
		
		public static function CPF(txt:CpfCnpjInput):void {
			// não é necessario colocar a mascara!
			if ( txt.text.length < 3 ) 
			{
				return;
			}
			
			if ( txt.text.length >= 3 && txt.text.length < 9 ) 
			{
				// acha o último ponto se existir 
				var ponto : int = txt.text.lastIndexOf(".", txt.text.length);  
				
				var start : int = ponto + 1;
				var tam   : int = 3;
				
				// copia apenas 3 digitos
				var substr : String = txt.text.substr(start, tam);
				
				if ( dig3.test(substr) ) 
				{
					// insere o ponto
					txt.text += "."; 
				}
			}
			else  
			{
				if ( dig9.test(txt.text) ) 
				{
					// insere o traco
					txt.text += "-";	
				}
			}			

			posicionaCursorFinal(txt);
		}
	
		// ******************************************* //
		// **	Format Mask CNPJ					** //
		// ******************************************* //

		public static function CNPJ(txt:CpfCnpjInput):void {
			var str : String = "";
			
			str = txt.text.replace(ponto, ""); // remove pontos
			str = str.replace(hifen, ""); 	   // remove hifen
			
			var doisDigitosPonto : String = str.substr(0, 2);  // copia 2 digitos
			var tresDigitosPonto : String = str.substr(2, 3);  // copia 3 digitos 
			var tresDigitosBarra : String = str.substr(5, 3);  // copia 3 digitos
			var quatDigitosTraco : String = str.substr(8, 4);  // copia 4 digitos
			var doisDigitosFim   : String = str.substr(12, 2); // copia 2 digitos
			
			// novo cnpj
			var newCNPJ : String = 
				doisDigitosPonto + "." + 
				tresDigitosPonto + "." + 
				tresDigitosBarra + "/" + 
				quatDigitosTraco + "-" + 
				doisDigitosFim; 
			
			if ( cnpj.test(newCNPJ) ) 
			{
				txt.text = newCNPJ;
			}
			
			posicionaCursorFinal(txt);
		}
		
		// ******************************************* //
		// **	Return Mask CPF						** //
		// ******************************************* //		
		
		// ** Exemplo.: 01.622.347/996
		public static function returnCPF(txt:CpfCnpjInput):void {
			if ( returnMaskCPF.test(txt.text) ) 
			{
				var str : String = "";
				str = txt.text.replace(ponto, ""); // remove pontos
				str = str.replace(barra, "");  	   // remove barra
				
				var tresDigitosPonto0 : String = str.substr(0, 3); // copia 3 digitos 
				var tresDigitosPonto3 : String = str.substr(3, 3); // copia 3 digitos 
				var tresDigitosTraco6 : String = str.substr(6, 3); // copia 3 digitos 
				var doisDigitosTraco9 : String = str.substr(9, 2); // copia 2 digitos 
				
				// novo cnpj
				var newCPF : String = 
					tresDigitosPonto0 + "." +
					tresDigitosPonto3 + "." +
					tresDigitosTraco6 + "-" +
					doisDigitosTraco9; 				
				
				txt.text = newCPF;
			}	
			
			posicionaCursorFinal(txt);
		}		
		
		// posiciona o cursor no final	
		private static function posicionaCursorFinal(txt:CpfCnpjInput):void {
			txt.selectRange(txt.text.length+1, txt.text.length+1); 
		}		
	}
}
Listagem 12. Código completo da classe Format

Neste artigo foi apresentada de forma prática e didática a criação de um componente CPF/CNPJ, a fim de que leitores possam utilizar em suas aplicações.

Bom pessoal por hoje é isso, espero que tenham gostando da Criação deste Componente e possam utilizar ele em suas aplicações.

Clique aqui se quiser baixar o projeto do componente, com os códigos fontes.