Ir para conteúdo
Fórum Script Brasil
  • 0

jsMask


KaKarotto

Pergunta

Oi galera ^_^

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:


/**
* @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:


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:
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
}
})
[/codebox]

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]
[code]
JSM("formulario").mask({      "numeros" : "digitos",      "tel" : "telefone"         })
[/code]
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          }      })
[/code]

Embora o objeto
JSM
seja de minha autoria, obviamente as funções não são, e foram retiradas daqui:

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. :)

Abraço.
[/indent]

Link para o comentário
Compartilhar em outros sites

3 respostass a esta questão

Posts Recomendados

  • 0

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:

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:
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>
<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:

/**
* @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
}
})[/codebox]

Link para o comentário
Compartilhar em outros sites

  • 0

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.

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.

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 =).

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,1k
    • Posts
      651,8k
×
×
  • Criar Novo...