Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

klonder

Máscara inteligente

Recommended Posts

Olá a todos!

 

Tenho pleno conhecimento que o assunto "Máscaras em JavaScript" já está um pouco batido. Temos vários tópicos sobre isso aqui mesmo no "Laboratório de Scripts", em sua maioria ótimos! Entretanto, não encontrei nenhum que atendesse a todas as minhas necessidades.

 

O meu principal objetivo era obter um código flexível, que pudesse ser inserido em qualquer campo-texto do formulário, sem a necessidade de ter de ficar alterando o script *.js. O script deveria ficar lá, quietinho, sem sofrer qualquer tipo de alteração caso o usuário quisesse trocar de CPF para CNPJ, ou então criar coisas estranhas como: )!(@&%! ###(*)(%!.

 

Além disso, eu queria corrigir um bug que está presente em muitas máscaras, que diz respeito à tecla BACKSPACE. Em alguns casos, o seu uso acabava por corromper toda a máscara, desconfigurando todo o campo.

 

Por isso, resolvi iniciar do zero esse script. Para ser sincero, comecei a desenvolvê-lo no início de 2009, porém por outros motivos abandonei o projeto, esquecendo-o completamente. Contudo, há alguns dias surgiu uma dúvida no fórum em relação ao uso da tecla BACKSPACE, que causava erro de configuração na máscara. Tentei recuperar o backup e hoje, finalmente, terminei o código.

 

Testei, testei e não encontrei erros. Se alguém encontrar, por favor, envie uma MP para eu editar o tópico, ok?

 

Aí vai o código de presente:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Máscaras para formulários - by Klonder</title>
</head>
<body>
<script type="text/javascript">
/*
Script desenvolvido por: Klonder
Postagem exclusiva em: http://www.forum.imasters.com.br
Versão 13.01.2010 - 20:05h;

Esse script poderá ser utilizado sem a necessidade de citação do autor.
Entretanto, não diga que o script é de sua autoria, pois o mesmo será postado nesse fórum, com a data precisa da publicação e com o nome do autor ao lado.
A capacidade em respeitar o trabalho do outro mostra o tipo de indivíduo que você realmente é.
*/

var trava = false;
var iCount1, iCount2, iCount, iTexto, nChar;
/*
iCount1 --> Comprimento da máscara no evento onkeydown (Referência para filtrar teclas de aderência!!!);
iCount2 --> Comprimento da máscara no evento onkeyup;
iTexto --> Texto atual na máscara, antes da função mascara() ser chamada com onkeyup;
nChar --> Variável controle;
*/

//Função chamada a partir do evento onkeydown;
function MaskDown(loc) {
	if(trava == false) {
		//Armazenando a frase em uma variável, para ser utilizada durante o backspace;
		iTexto = document.getElementById(loc).value;
		
		//Armazenando a frase em uma variável, para ser utilizada durante adição de caracteres;
		objCampoMascara = document.getElementById(loc);
		
		//Comprimento da máscara no evento onkeydown;
		iCount1 = objCampoMascara.value.length;
		//Adicionando trava para evitar possível tecla de aderência:
		trava = true;
	}
}

//Função chamada a partir do evento onkeyup;
function MaskUp(loc,msc) {
//Recuperando o local do campo que contém a máscara;
objCampoMascara = document.getElementById(loc);
//Comprimento da máscara no evento onkeyup;
iCount2 = objCampoMascara.value.length;

//Verificando se o usuário inseriu novos caracteres, ou se apertou a tecla DELETE/BACKSPACE:

// -------------------- Caso 1: Inserção de novos caracteres --------------------
//Quantidade caracteres final (onkeydown) maior que a inicial (onkeyup) -> Houve inserção de caracteres;
if (iCount2 > iCount1) {
	
	//Recortando a máscara para filtrar possível tecla de aderência:
	objCampoMascara.value = objCampoMascara.value.substr(0,iCount1+1);
	//Verificando se o comprimento da máscara não é excedido;
	if(objCampoMascara.value.length > msc.length) {
		objCampoMascara.value = objCampoMascara.value.substr(0,msc.length);
	}
	//Antes de mais nada, verificar se a máscara já inicia com caracteres especiais e já inserí-los;
	if(iCount1 == 0) {
		//Contando o número de caracteres especiais (se porventura existirem):
		if (msc.substring(iCount1,iCount1+1) != "#") {
			nChar=1;
			//Contar as ocorrências de símbolos especiais, diferentes de: #, que iniciam a máscara:
			while (msc.substring(iCount1+nChar,iCount1+nChar+1) != "#" && nChar <= msc.length) {
				nChar++;	
			}
			objCampoMascara.value = msc.substring(0,iCount1+nChar) + objCampoMascara.value.substr(0,iCount1+1);
		} 
	//Se não iniciar com caracteres especiais:
	} else {
		//Verificando se existe caracteres especiais à frente do último caractere inserido:
		if (msc.substring(iCount1+1,iCount1+2) != "#") {
			var nChar=1;
			//Contar as ocorrências de símbolos especiais que sucedem o último caractere inserido;
			while (msc.substring(iCount1+nChar,iCount1+nChar+1) != "#" && nChar <= msc.length) {
				nChar++;	
			}
			objCampoMascara.value = objCampoMascara.value.substr(0,iCount1+1) + msc.substring(iCount1+1,iCount1+nChar);
		}
	}

// -------------------- Caso 2: Deleção de caracteres | Backspace --------------------
} else {	
	//Verificando se o caractere apagado é um símbolo especial ou não:
	if (msc.substr(iCount2,1) != "#") {	
		nChar = 1;
		//Looping para percorrer os caracteres especiais retrocedentes:
		while (msc.substring(iCount1-nChar,iCount1-nChar-1) != "#" && nChar <= iTexto.length) {
			nChar++;	
		}
		//Apagando os caracteres retrocedentes, conforme o valor atribuído a nChar:
		objCampoMascara.value = iTexto.substr(0,iCount2-nChar);
	} /*else {
	//Recortando a máscara para filtrar possível tecla de aderência: Default: desabilitado.
	objCampoMascara.value = iTexto.substr(0,iCount1-1);
	}*/
}
//Liberando a trava para possibilitar novo evento onkeydown:
trava = false;
}

</script>
Telefone: <input type="text" id="t1" onkeydown="MaskDown('t1')" onkeyup="MaskUp('t1','(##) ####-####')"> (##) ####-####
<br>Data: <input type="text" id="t2" onkeydown="MaskDown('t2')" onkeyup="MaskUp('t2','##/##/####')"> ##/##/####
<br>CEP: <input type="text" id="t3" onkeydown="MaskDown('t3')" onkeyup="MaskUp('t3','#####-###')"> #####-###
<br>CPF: <input type="text" id="t4" onkeydown="MaskDown('t4')" onkeyup="MaskUp('t4','###.###.###-##')"> ###.###.###-##
<br>CNPJ: <input type="text" id="t5" onkeydown="MaskDown('t5')" onkeyup="MaskUp('t5','##.###.###/####-##')"> ##.###.###/####-##
<br>Placas de automóveis: <input type="text" id="t6" onkeydown="MaskDown('t6')" onkeyup="MaskUp('t6','### ####')"> ### #####

<br><br>Aleatório 1: <input type="text" id="t7" onkeydown="MaskDown('t7')" onkeyup="MaskUp('t7','|$-%  *& «##» .:. «##» (###) %-$|')" size="40"> |$-%  *& «##» .:. «##» (###) %-$|

<br><br>Aleatório 2: <input type="text" id="t8" onkeydown="MaskDown('t8')" onkeyup="MaskUp('t8','<--| ##.### |-->')" size="40"> <--| ##.### |-->

<br><br><br><br>Características principais:
<br>1. Filtro para evitar teclas de aderência;
<br>2. Flexibilidade para qualquer tipo de máscara, com qualquer tipo de caractere especial;
<br>3. Permite correção inteligente quando BACKSPACE for pressionado;
<br>4. Permite o uso de símbolos especiais em sequência, inclusive com espaço;
<br>5. Controlam a quantidade de símbolos na máscara, não havendo necessidade de inserir o "maxlength" em cada um dos campos de texto que forem criados (o "maxlength" pode ser usado a critério do desenvolvedor).
<br>6. Código-fonte reaproveitável para qualquer campo texto do formulário.
<br>7. Código-fonte comentado, para melhor compreensão do processo.
</body>
</html>

Espero que gostem!

 

Abraços a todos usuários e visitantes do fórum! http://forum.imasters.com.br/public/style_emoticons/default/natal_biggrin.gif

Compartilhar este post


Link para o post
Compartilhar em outros sites

O Maujor me enviou uma MP, sugerindo algumas alterações que poderiam tornar o script mais flexível ainda.

 

Segue o novo script:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Máscaras para formulários - by Klonder</title>
</head>
<body>
<script type="text/javascript">
/*
Script desenvolvido por: Klonder
Postagem exclusiva em: http://www.forum.imasters.com.br
Versão 13.01.2010 - 20:05h;

Esse script poderá ser utilizado sem a necessidade de citação do autor.
Entretanto, não diga que o script é de sua autoria, pois o mesmo será postado nesse fórum, com a data precisa da publicação e com o nome do autor ao lado.
A capacidade em respeitar o trabalho do outro mostra o tipo de indivíduo que você realmente é.
*/

var trava = false;
var iCount1, iCount2, iCount, iTexto, nChar;
/*
iCount1 --> Comprimento da máscara no evento onkeydown (Referência para filtrar teclas de aderência!!!);
iCount2 --> Comprimento da máscara no evento onkeyup;
iTexto --> Texto atual na máscara, antes da função mascara() ser chamada com onkeyup;
nChar --> Variável controle;
*/

//Função chamada a partir do evento onkeydown;
function MaskDown(e) {
	if(trava == false) {
		//Armazenando a frase em uma variável, para ser utilizada durante o backspace;
		iTexto = e.value;
		
		//Comprimento da máscara no evento onkeydown;
		iCount1 = e.value.length;
		//alert(iCount1);
		//Adicionando trava para evitar possível tecla de aderência:
		trava = true;
	}
}

//Função chamada a partir do evento onkeyup;
function MaskUp(e,msc) {
//Comprimento da máscara no evento onkeyup;
iCount2 = e.value.length;

//Verificando se o usuário inseriu novos caracteres, ou se apertou a tecla DELETE/BACKSPACE:

// -------------------- Caso 1: Inserção de novos caracteres --------------------
//Quantidade caracteres final (onkeydown) maior que a inicial (onkeyup) -> Houve inserção de caracteres;
if (iCount2 > iCount1) {
	
	//Pequena correção para bug que estava ocorrendo com navegação com tecla TAB;
	//A tecla TAB não dispara keydown, fazendo com que iCount1 seja 0 e iCount2 o valor normal;
	//Por isso, vamos corrigir (Agradecimentos ao -rafael- pela observação do bug) :-)
	if (iCount2-iCount1 > 1) {
		iCount1 = iCount2-1;
		e.select;
	} else {
		//Recortando a máscara para filtrar possível tecla de aderência:
		e.value = e.value.substr(0,iCount1+1);
		//Verificando se o comprimento da máscara não é excedido;
		if(e.value.length > msc.length) {
			e.value = e.value.substr(0,msc.length);
		}
		//Antes de mais nada, verificar se a máscara já inicia com caracteres especiais e já inserí-los;
		if(iCount1 == 0) {
			//Contando o número de caracteres especiais (se porventura existirem):
			if (msc.substring(iCount1,iCount1+1) != "#") {
				nChar=1;
				//Contar as ocorrências de símbolos especiais, diferentes de: #, que iniciam a máscara:
				while (msc.substring(iCount1+nChar,iCount1+nChar+1) != "#" && nChar <= msc.length) {
					nChar++;	
				}
				e.value = msc.substring(0,iCount1+nChar) + e.value.substr(0,iCount1+1);
			} 
		//Se não iniciar com caracteres especiais:
		} else {
			//Verificando se existe caracteres especiais à frente do último caractere inserido:
			if (msc.substring(iCount1+1,iCount1+2) != "#") {
				var nChar=1;
				//Contar as ocorrências de símbolos especiais que sucedem o último caractere inserido;
				while (msc.substring(iCount1+nChar,iCount1+nChar+1) != "#" && nChar <= msc.length) {
					nChar++;	
				}
				e.value = e.value.substr(0,iCount1+1) + msc.substring(iCount1+1,iCount1+nChar);
			}
		}
	}
// -------------------- Caso 2: Deleção de caracteres | Backspace --------------------
} else {	
	//Verificando se o caractere apagado é um símbolo especial ou não:
	if (msc.substr(iCount2,1) != "#") {	

		nChar = 1;
		//alert(msc.substr(iCount2,1));
		//Looping para percorrer os caracteres especiais retrocedentes:
		while (msc.substr(iCount1-nChar,1) != "#" && nChar <= iCount1) {
			//alert(msc.substr(iCount1-nChar,1)+" -- "+nChar);
			nChar++;	
		}
		//Apagando os caracteres retrocedentes, conforme o valor atribuído a nChar:
		e.value = iTexto.substr(0,iCount2-nChar+1);
	} /*else {
	//Recortando a máscara para filtrar possível tecla de aderência: Default: desabilitado.
	objCampoMascara.value = iTexto.substr(0,iCount1-1);
	}*/
}
//Liberando a trava para possibilitar novo evento onkeydown:
trava = false;
}

</script>
Telefone: <input type="text" id="t1" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'(##) ####-####')"> (##) ####-####
<br>Data: <input type="text" id="t2" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'##/##/####')"> ##/##/####
<br>CEP: <input type="text" id="t3" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'#####-###')"> #####-###
<br>CPF: <input type="text" id="t4" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'###.###.###-##')"> ###.###.###-##
<br>CNPJ: <input type="text" id="t5" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'##.###.###/####-##')"> ##.###.###/####-##
<br>Placas de automóveis: <input type="text" id="t6" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'### ####')"> ### #####

<br><br>Aleatório 1: <input type="text" id="t7" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'|$-%  *& «##» .:. «##» (###) %-$|')" size="40"> |$-%  *& «##» .:. «##» (###) %-$|

<br><br>Aleatório 2: <input type="text" id="t8" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,'<--| ##.### |-->')" size="40"> <--| ##.### |-->

<br><br><br><br>Características principais:
<br>1. Filtro para evitar teclas de aderência;
<br>2. Flexibilidade para qualquer tipo de máscara, com qualquer tipo de caractere especial;
<br>3. Permite correção inteligente quando BACKSPACE for pressionado;
<br>4. Permite o uso de símbolos especiais em sequência, inclusive com espaço;
<br>5. Controlam a quantidade de símbolos na máscara, não havendo necessidade de inserir o "maxlength" em cada um dos campos de texto que forem criados (o "maxlength" pode ser usado a critério do desenvolvedor).
<br>6. Código-fonte reaproveitável para qualquer campo texto do formulário.
<br>7. Código-fonte comentado, para melhor compreensão do processo.
</body>
</html>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eis a nova versão, com correção de uns pequenos bugs:

 

Versão 09.04.2010 - 21:05h;

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Máscaras para formulários - by Klonder</title>
</head>
<body>
<script type="text/javascript">
/*
Script desenvolvido por: Klonder
Postagem exclusiva em: http://www.forum.imasters.com.br
Versão 09.04.2010 - 21:05h;

Esse script poderá ser utilizado sem a necessidade de citação do autor.
Entretanto, não diga que o script é de sua autoria, pois o mesmo será postado nesse fórum, com a data precisa da publicação e com o nome do autor ao lado.
A capacidade em respeitar o trabalho do outro mostra o tipo de indivíduo que você realmente é.
*/

var trava = false;
var iCount1, iCount2, iCount, iTexto, nChar;
function MaskDown(e) {
        if(trava == false) {
                iTexto = e.value;
                iCount1 = e.value.length;
                trava = true;
        }
}

function MaskUp(e,evt,msc) {
iCount2 = e.value.length;
var key_code = evt.keyCode ? evt.keyCode : evt.charCode ? evt.charCode : evt.which ? evt.which : void 0;
if (key_code == 9) {
                iCount1 = iCount2-1;
                e.select;
                
} else {
if (iCount2 > iCount1) {
        e.value = e.value.substr(0,iCount1+1);
        if(e.value.length > msc.length) {
                e.value = e.value.substr(0,msc.length);
        }
        if(iCount1 == 0) {
                if (msc.substring(iCount1,iCount1+1) != "#") {
                        nChar=1;
                        while (msc.substring(iCount1+nChar,iCount1+nChar+1) != "#" && nChar <= msc.length) {
                                nChar++;        
                        }
                        e.value = msc.substring(0,iCount1+nChar) + e.value.substr(0,iCount1+1);
                } 
        } else {
                if (msc.substring(iCount1+1,iCount1+2) != "#") {
                        var nChar=1;
                        while (msc.substring(iCount1+nChar,iCount1+nChar+1) != "#" && nChar <= msc.length) {
                                nChar++;        
                        }
                        e.value = e.value.substr(0,iCount1+1) + msc.substring(iCount1+1,iCount1+nChar);
                }
        }
} else if (iCount2 == iCount1) {
        e.value = e.value;
} else {        
        if (msc.substr(iCount2,1) != "#") {     

                nChar = 1;
                while (msc.substr(iCount1-nChar,1) != "#" && nChar <= iCount1) {
                        nChar++;        
                }
                e.value = iTexto.substr(0,iCount2-nChar+1);
        }

}
trava = false;
}}
</script>
Telefone: <input type="text" id="t1" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,event,'(##) ####-####')"> (##) ####-####
<br>Data: <input type="text" id="t2" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,event,'##/##/####')"> ##/##/####
<br>CEP: <input type="text" id="t3" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,event,'#####-###')"> #####-###
<br>CPF: <input type="text" id="t4" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,event,'###.###.###-##')"> ###.###.###-##
<br>CNPJ: <input type="text" id="t5" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,event,'##.###.###/####-##')"> ##.###.###/####-##
<br>Placas de automóveis: <input type="text" id="t6" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,event,'### ####')"> ### #####

<br><br>Aleatório 1: <input type="text" id="t7" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,event,'|$-%  *& «##» .:. «##» (###) %-$|')" size="40"> |$-%  *& «##» .:. «##» (###) %-$|

<br><br>Aleatório 2: <input type="text" id="t8" onkeydown="MaskDown(this)" onkeyup="MaskUp(this,event,'<--| ##.### |-->')" size="40"> <--| ##.### |-->

<br /><br /><br /><br />Características principais:
<br />1. Filtro para evitar teclas de aderência;
<br />2. Flexibilidade para qualquer tipo de máscara, com qualquer tipo de caractere especial;
<br />3. Permite correção inteligente quando BACKSPACE for pressionado;
<br />4. Permite o uso de símbolos especiais em sequência, inclusive com espaço;
<br />5. Controlam a quantidade de símbolos na máscara, não havendo necessidade de inserir o "maxlength" em cada um dos campos de texto que forem criados (o "maxlength" pode ser usado a critério do desenvolvedor).
<br />6. Código-fonte reaproveitável para qualquer campo texto do formulário.
</body>
</html>

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.