IPB

Bem-vindo, visitante ( Entrar | Registrar )

> Orientações

Atenção
Este sub-fórum é destinado, exclusivamente, à postagem de códigos prontos. Dúvidas devem ser postadas no fórum principal

 
Reply to this topicStart new topic
> jsMask, Objeto Javascript para Mascarar campos de formulário.
post 11/04/2009 - 22:05
Post #1
KaKarotto



Além de simpático, gostoso e inteligente..modesto, acima de tudo
Ícone do grupo

Grupo: Vencedores de desafio
Posts: 1260
Registrado: 05/04/2007
De: São Paulo, Capital.
Membro nº: 27862
Sexo:



Oi galera happy.gif

Eu queria aproveitar que muita gente pede uma função para mascarar campos de formulário para postar uma solução que eu fiz para este propósito.

Eu encapsulei em um objeto chamado JSM algumas funções para tratar dados em campos de formulário e fiz este objeto de maneira extensível para adicionarmos mais métodos ao mesmo.

Para quem está interessado, o código é este:

CODE

/**
* @author Eduardo Ottaviani
* @example JSM("formulario").mask({ "nome" : "telefone" })
*/

function
JSM (form){ return new JSM.Class(form) }
JSM . add = function(json){ JSM.methods[json.name] = json.method }
JSM . methods = {}

JSM . Class = function(form){
//Private:
var form = document[form]

//Public:
this.inputs = {}
this.form = function(){return form}
this.test = function(object, mask){
var fn = JSM.methods[mask]
setTimeout( function(){ object.value = fn(object.value) },1 )
}
}

JSM . Class.prototype["mask"] = function(json){
var form = this.form()
var self = this
var addEvent = null
try{
if(!window.attachEvent) throw "addEventListener"
addEvent = function(event, obj, fn){ obj.attachEvent( "on"+event, fn ) }
}
catch(eventListener){
if(!window[eventListener]) throw "Não existe a feature no navegador"
addEvent = function(event, obj, fn){ obj.addEventListener( event, fn, false ) }
}
for(var x in json){
self.inputs[x] = json[x]
addEvent("keypress", form[x], function(e){
var name = this.name
if(e.srcElement) name = e.srcElement.name
for (var y = 0; y < self.inputs[name].split("|").length; y++) {
self.test(form[name], self.inputs[name].split("|")[y])
}
})
}
}

// Funções de máscara foram pegas de: http://elcio.com.br/ajax/mascara/

JSM.add({
"name":"digitos",
"method" : function(v){ return v.replace(/\D/g,"")}
})

JSM.add({
"name":"leech",
"method": function(v){
v=v.replace(/o/gi,"0")
v=v.replace(/i/gi,"1")
v=v.replace(/z/gi,"2")
v=v.replace(/e/gi,"3")
v=v.replace(/a/gi,"4")
v=v.replace(/s/gi,"5")
v=v.replace(/t/gi,"7")
return v
}
})

JSM.add({
"name":"telefone",
"method": function(v){
v=v.replace(/\D/g,"") //Remove tudo o que não é dígito
v=v.replace(/^(\d\d)(\d)/g,"($1) $2") //Coloca parênteses em volta dos dois primeiros dígitos
v=v.replace(/(\d{4})(\d)/,"$1-$2") //Coloca hífen entre o quarto e o quinto dígitos
return v
}
})

JSM.add({
"name":"cpf",
"method": function(v){
v=v.replace(/\D/g,"") //Remove tudo o que não é dígito
v=v.replace(/(\d{3})(\d)/,"$1.$2") //Coloca um ponto entre o terceiro e o quarto dígitos
v=v.replace(/(\d{3})(\d)/,"$1.$2") //Coloca um ponto entre o terceiro e o quarto dígitos
//de novo (para o segundo bloco de números)
v=v.replace(/(\d{3})(\d{1,2})$/,"$1-$2") //Coloca um hífen entre o terceiro e o quarto dígitos
return v
}
})

JSM.add({
"name":"cep",
"method": function(v){
v=v.replace(/D/g,"") //Remove tudo o que não é dígito
v=v.replace(/^(\d{5})(\d)/,"$1-$2") //Esse é tão fácil que não merece explicações
return v
}
})

JSM.add({
"name":"cnpj",
"method": function(v){
v=v.replace(/\D/g,"") //Remove tudo o que não é dígito
v=v.replace(/^(\d{2})(\d)/,"$1.$2") //Coloca ponto entre o segundo e o terceiro dígitos
v=v.replace(/^(\d{2})\.(\d{3})(\d)/,"$1.$2.$3") //Coloca ponto entre o quinto e o sexto dígitos
v=v.replace(/\.(\d{3})(\d)/,".$1/$2") //Coloca uma barra entre o oitavo e o nono dígitos
v=v.replace(/(\d{4})(\d)/,"$1-$2") //Coloca um hífen depois do bloco de quatro dígitos
return v
}
})

JSM.add({
"name":"romanos",
"method": function(v){
v = v . toUpperCase() //Maiúsculas
v = v . replace(/[^IVXLCDM]/g,"") //Remove tudo o que não for I, V, X, L, C, D ou M
//Essa é complicada! Copiei daqui: http://www.diveintopython.org/refactoring/refactoring.html
while(v . replace(/^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/,"")!="")
v = v . replace(/.$/,"")
return v
}
})

JSM.add({
"name":"site",
"method":function(v){
//Esse sem comentarios para que você entenda sozinho ;-)
v=v.replace(/^http:\/\/?/,"")
var dominio=v
var caminho=""
if(v.indexOf("/")>-1)
dominio = v.split("/")[0]
caminho = v.replace(/[^\/]*/,"")
dominio = dominio.replace(/[^\w\.\+-:@]/g,"")
caminho = caminho.replace(/[^\w\d\+-@:\?&=%\(\)\.]/g,"")
caminho = caminho.replace(/([\?&])=/,"$1")
if(caminho!="")
dominio = dominio.replace(/\.+$/,"")
v = "http://" + dominio + caminho
return v
}
})

JSM.add({
"name" : "data",
"method" : function (v){
v=v.replace(/\D/g,"")
v=v.replace(/(\d{2})(\d)/,"$1/$2")
v=v.replace(/(\d{2})(\d)/,"$1/$2")
return v
}
})


O JSM é uma função que recebe como parâmetro o nome do formulário em questão e tem dois métodos que nos interessam:

Object JSM: JSM.mask(Object json)

Este método retorna o próprio objeto JSM e recebe um objeto do tipo json, com os pares de valores {"name":"mascara"}. "name" é o nome do campo e mascara o tipo de máscara a ser usado naquele campo.

Ex:

CODE
<form id="formulario" name="formulario">
     <input type = "text" name = "numeros" />
     <input type = "text" name = "tel" />
     <button type="submit">Botão</button>
</form>



CODE
JSM("formulario").mask({
     "numeros" : "digitos",
     "tel" : "telefone"        
})


void: JSM.add( Object json )

Este método não retorna nada e é usado para ESTENDER o objeto JSM com mais métodos de máscara.
Ele recebe um objeto json com pares de valores {"name": "nomeDaMascara", "method":function(valor){return valor}}

A chave "name" terá o valor do nome da mascara, para ser usado na chamada de mask.

A chave "method" terá como valor uma função que terá um argumento definido pelo desenvolvedor que será o valor do campo digitado. Esta função irá tratar o valor do campo e SEMPRE retornar um novo valor ( Sempre do tipo STRING ) que será o substituído pela máscara.

Ex:

CODE
JSM.add({
         "name":"cep",
         "method": function(v){
             v=v.replace(/D/g,"")                //Remove tudo o que não é dígito
             v=v.replace(/^(\d{5})(\d)/,"$1-$2") //Esse é tão fácil que não merece explicações
             return v
         }
     })


Embora o objeto JSM seja de minha autoria, obviamente as funções não são, e foram retiradas daqui: http://elcio.com.br/ajax/mascara/
Apenas aproveitei as funções do Elcio e adaptei para este script com o propósito de facilitar seu uso e de estende-lo.

Deixarei um link para o download aqui e o espaço aberto para sugestões e/ou críticas.

Ficaria muito feliz se alguém aproveitasse para postar adições de novos métodos que não tenha neste. smile.gif

Abraço.

Arquivo(s) anexado(s)
Arquivo anexado  jsMask.zip ( 1.7KB ) Downloads: 14
 


--------------------



Javiani
Desafiadores:
Mestre SAM - Fiote - Raficcha - Flavio - Romerito

Go to the top of the page
 
+Quote Post
post 12/04/2009 - 13:25
Post #2
Jonathan Queiroz




Ícone do grupo

Grupo: Administradores
Posts: 3615
Registrado: 10/07/2008
De: Salvador - BA
Membro nº: 37857
Sexo:



Parabéns pela ótima iniciativa !
Ainda não testei todas as máscaras, mas creio que devem estar funcionando perfeitamente
A única coisa que acho que poderia ser melhorada na parte das máscaras seria o limite de tamanho
Exemplo para máscara de telefone:
CODE
v=v.substring(0,14)                   //Limita o número de dígitos do telefone


Quanto ao programa em si, uma sugestão seria dar a liberdade ao usuário de passar o próprio elemento para a função, ao invés de passar seu nome no formulário.Exemplo:
CODE
JSM("formulario").mask({'campo':'document.getElementById("campo1")','mask':'telefone'})

Infelizmente isso não seria possível sem modificar o objeto JSM (já que no JSM está sendo atribuído o nome da máscara a uma propriedade com o nome do campo)
Sendo assim, fiz algumas modificações no código
Por exemplo, é possível criar uma página dessa forma:
HTML
<html>
<head>
<title>Untitled Page</title>
<script type="text/javascript" src="JSMask.js"></script>
<script type="text/javascript">
onload=function(){
JSM("formulario").mask({'campos':'document.getElementById("campo1")|campo2|document.forms[0].campo_cep','masks':'telefone|cpf|cep'})
}
</script>
</head>
<body>
<form name="formulario">
Telefone: <input type="text" id="campo1"><br />
CEP: <input type="text" name="campo_cep" /><br />
</form>
<!--
Note que o CPF está fora do formulário.
Como não foi encontrado um campo com atributo "name" setado como CPF no formulário
o programa irá buscar o elemento pelo ID (que é campo2).
Se o ID não for encontrado (o que não é o caso), o programa irá executar a própria expressão.
Exemplo: JSM("formulario").mask({'campos':'document.getElementsByTagName("input")[0]','masks':'digitos'})
OBS.:
<<<<<<< A mesma coisa é válida para o parâmetro "form" que é passado para o objeto JSM
<<<<<<< Por exemplo: Ao invés de JSM("formulario"), você pode utilizar JSM(document.forms[0])
-->
CPF: <input type="text" id="campo2"><br />
</body>
</html>


O script modificado ficou assim:
CODE
/**
* @author Eduardo Ottaviani
* @example JSM("formulario").mask({ "nome" : "phone" })
*/

function
JSM (form){ return new JSM.Class(form) }
JSM . add = function(json){ JSM.methods[json.name] = json.method }
JSM . methods = {}

JSM . Class = function(form){
ProcuraElemento=function(x,frm){
var e
if(frm){
e=frm[e]
}
if(!e){
e=document.getElementById(x)
if(!e){
try{
e=eval(x)
}catch(er){
e=x
}
}
}
return e
}
//Private:
var form = ProcuraElemento(form)

//Public:
this.inputs = {}
this.form = function(){return form}
this.test = function(object, mask){
var fn = JSM.methods[mask]
setTimeout( function(){ object.value = fn(object.value) },1 )
}
}
JSM.Class.prototype["mask"] = function(json){
var form = this.form()
var self = this
var addEvent = null
try{
if(!window.attachEvent) {throw "addEventListener"}
addEvent = function(event, obj, fn){ obj.attachEvent( "on"+event, fn )}
}
catch(eventListener){
if(!window[eventListener]) {throw "Não existe a feature no navegador"}
addEvent = function(event, obj, fn){obj.addEventListener(event, fn, false )}
}
name=json["campos"]
mask=json["masks"]
var nome_atual //Nome do elemento no loop corrente
var mask_atual //Nome da máscara no loop corrente
var elmt_atual //Armazena o elemento no loop corrente
var mascaras=[]
for(y=0;y<Math.min(name.split("|").length,mask.split("|").length);y++){
nome_atual=name.split("|")[y]
mask_atual=mask.split("|")[y]
elmt_atual=ProcuraElemento(nome_atual,form)
if(elmt_atual.id==""){
var elmt_id
elmt_id="JSM_mask_"
do{
elmt_id=parseInt(Math.random*1000)
}while(document.getElementById(elmt_id))
elmt_atual.id=elmt_id
}
mascaras[elmt_atual.id]=mask_atual
addEvent("keypress", elmt_atual, function(e){
self.test(this,mascaras[this.id])
})
}
}

// Funções de máscara foram pegas de: http://elcio.com.br/ajax/mascara/
JSM.add({
"name":"digitos",
"method" : function(v){ return v.replace(/\D/g,"")}
})

JSM.add({
"name":"leech",
"method": function(v){
v=v.replace(/o/gi,"0")
v=v.replace(/i/gi,"1")
v=v.replace(/z/gi,"2")
v=v.replace(/e/gi,"3")
v=v.replace(/a/gi,"4")
v=v.replace(/s/gi,"5")
v=v.replace(/t/gi,"7")
return v
}
})

JSM.add({
"name":"telefone",
"method": function(v){
v=v.replace(/\D/g,"") //Remove tudo o que não é dígito
v=v.replace(/^(\d\d)(\d)/g,"($1) $2") //Coloca parênteses em volta dos dois primeiros dígitos
v=v.replace(/(\d{4})(\d)/,"$1-$2") //Coloca hífen entre o quarto e o quinto dígitos
v=v.substring(0,14) //Limita o número de dígitos do telefone
return v
}
})

JSM.add({
"name":"cpf",
"method": function(v){
v=v.substring(0,14) //Limite de caracteres para o CPF
v=v.replace(/\D/g,"") //Remove tudo o que não é dígito
v=v.replace(/(\d{3})(\d)/,"$1.$2") //Coloca um ponto entre o terceiro e o quarto dígitos
v=v.replace(/(\d{3})(\d)/,"$1.$2") //Coloca um ponto entre o terceiro e o quarto dígitos
//de novo (para o segundo bloco de números)
v=v.replace(/(\d{3})(\d{1,2})$/,"$1-$2") //Coloca um hífen entre o terceiro e o quarto dígitos
return v
}
})

JSM.add({
"name":"cep",
"method": function(v){
v=v.replace(/D/g,"") //Remove tudo o que não é dígito
v=v.replace(/^(\d{5})(\d)/,"$1-$2") //Esse é tão fácil que não merece explicações
v=v.substring(0,9) //Limita o número de caracteres do CEP
return v
}
})

JSM.add({
"name":"cnpj",
"method": function(v){
v=v.replace(/\D/g,"") //Remove tudo o que não é dígito
v=v.replace(/^(\d{2})(\d)/,"$1.$2") //Coloca ponto entre o segundo e o terceiro dígitos
v=v.replace(/^(\d{2})\.(\d{3})(\d)/,"$1.$2.$3") //Coloca ponto entre o quinto e o sexto dígitos
v=v.replace(/\.(\d{3})(\d)/,".$1/$2") //Coloca uma barra entre o oitavo e o nono dígitos
v=v.replace(/(\d{4})(\d)/,"$1-$2") //Coloca um hífen depois do bloco de quatro dígitos
v=v.substring(0,18) //Limita o número de caracteres do CNPJ
return v
}
})

JSM.add({
"name":"romanos",
"method": function(v){
v = v . toUpperCase() //Maiúsculas
v = v . replace(/[^IVXLCDM]/g,"") //Remove tudo o que não for I, V, X, L, C, D ou M
//Essa é complicada! Copiei daqui: http://www.diveintopython.org/refactoring/refactoring.html
while(v . replace(/^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/,"")!="")
v = v . replace(/.$/,"")
return v
}
})

JSM.add({
"name":"site",
"method":function(v){
//Esse sem comentarios para que você entenda sozinho ;-)
v=v.replace(/^http:\/\/?/,"")
var dominio=v
var caminho=""
if(v.indexOf("/")>-1)
dominio = v.split("/")[0]
caminho = v.replace(/[^\/]*/,"")
dominio = dominio.replace(/[^\w\.\+-:@]/g,"")
caminho = caminho.replace(/[^\w\d\+-@:\?&=%\(\)\.]/g,"")
caminho = caminho.replace(/([\?&])=/,"$1")
if(caminho!="")
dominio = dominio.replace(/\.+$/,"")
v = "http://" + dominio + caminho
return v
}
})

JSM.add({
"name" : "data",
"method" : function (v){
v=v.replace(/\D/g,"")
v=v.replace(/(\d{2})(\d)/,"$1/$2")
v=v.replace(/(\d{2})(\d)/,"$1/$2")
return v
}
})


--------------------
Go to the top of the page
 
+Quote Post
post 12/04/2009 - 20:10
Post #3
KaKarotto



Além de simpático, gostoso e inteligente..modesto, acima de tudo
Ícone do grupo

Grupo: Vencedores de desafio
Posts: 1260
Registrado: 05/04/2007
De: São Paulo, Capital.
Membro nº: 27862
Sexo:



Oi Jonathan! obrigado por comentar!!! é raro isso, é muito bom essa interação

Eu vou rebater o seu comentário, antes de elaborar o código eu já havia pensado em tudo isso que disse.

QUOTE

Parabéns pela ótima iniciativa !
Ainda não testei todas as máscaras, mas creio que devem estar funcionando perfeitamente
A única coisa que acho que poderia ser melhorada na parte das máscaras seria o limite de tamanho
Exemplo para máscara de telefone:
Não se deve misturar os propósitos e também não é bom presumir nada. Isto é, se por algum motivo eu quisesse botar o telefone de outro país, ou se fosse alguma enquete, e o usuário precisasse inputar um telefone como 0800, o seu script quebraria. Fora que o script cresceria em todas as funções para esta tarefa, teria de adicionar isso à todas as funções.

MAXLENGTH é um atributo html e portanto deve ser definido no próprio html.

QUOTE

Quanto ao programa em si, uma sugestão seria dar a liberdade ao usuário de passar o próprio elemento para a função, ao invés de passar seu nome no formulário.Exemplo


Na maioria das vezes esta forma de pensar é muito válida. Neste caso não é necessário, em javascript é mais rápido pegar os elementos pelo "." do que pelo id. No caso de formulário, o seu formulário sempre vai ter um nome e seus campos sempre terão um nome, caso contrário você não consegue enviar por post ou get seus dados.

Não é necessário aumentar seu código colocando getElementById, ou usar document.forms, é uso desnecessário sendo que o jsMask já tem um objeto encapsulado guardando estas informações, seu código fica redundante e diz adeus a reutilização do código.

Além de tudo isso, você induz o desenvolvedor a escrever um código desorganizado, porque ele não precisa especificar o formulario que está usando...
Em um código grande, você pode demorar um bom tempo procurando aquele campo que mascarou, sem contar que a chamada em si da função fica gambiarrosa, nada elegante.

Eu utilizei alguns conceitos do jquery.validate, por isso, estas questões já foram pensadas =).



--------------------



Javiani
Desafiadores:
Mestre SAM - Fiote - Raficcha - Flavio - Romerito

Go to the top of the page
 
+Quote Post
post 13/04/2009 - 17:17
Post #4
Jonathan Queiroz




Ícone do grupo

Grupo: Administradores
Posts: 3615
Registrado: 10/07/2008
De: Salvador - BA
Membro nº: 37857
Sexo:



Realmente, muitas dessas modificações modificariam totalmente o objetivo inicial do script

Estava pensando aqui...
Acho que seria interessante uma validação para e-mail's também
Vou ver se faço uma aqui e posto quando terminar !


--------------------
Go to the top of the page
 
+Quote Post

Fast ReplyReply to this topicStart new topic
1 usuário(s) está(ão) lendo este tópico (1 visitantes e 0 usuários anônimos)
0 membros:

 

Modos de Exibição: Padrão · Mudar para: Linear+ · Mudar para: Outline


Versão Simples Horário: 02/09/2010 - 21:58