quarta-feira, 13 de março de 2013

Máscara para valores decimais negativos

Máscaras para valores decimais negativos é sempre algo bem chato e complicado de achar, nas minhas pesquisas na net não achei nada que me ajudasse, o plugin maskedinput não pode me ajudar nessa situação pois, ele se encaixa muito bem para valores fixos tipo, datas, horários, cpf/cnpj, rg e por ai vai.

Outro plugin que achei que talvez fosse me ajudar era o maskedmoney(ou alguma coisa assim) mas, também não era o que eu queria. Então pensei:

"Porque não faço a minha própria máscara ?"

Mãos à obra.

Já sabia que iria ter d fazer uma regex em javascript se queria uma solução limpa e eficaz, só que ai surgia um outro grande problema, como fazer a tal Regex ? Depois de quebrar muito a cabeça e ter ajuda de um guru do javascript, Leonardo Dutra, conseguimos construir uma regex que pudesse validar campos decimais negativos e positivos.

/^-?[0-9]{1,3}(?:\.[0-9]{2})?$/

Ai está a obra prima mas, agora precisamos entender o que isso faz para que possamos construir outras no futuro. Em javascript, a barra / no início e no fim é obrigatório, isso é próprio da linguagem pois, quando você constrói uma regex um objeto RegExp é gerado, logo você deverá sempre por.

O símbolo ^ denota início de sentença, logo estamos construindo uma regex que vai validar inícios de sentença.

Os símbolos -? significam que eu posso ter 1 ou nenhuma ocorrência do sinal negativo(-), o ? dá esse significado de 1 ou 0 ocorrências.

[0-9] significa que eu posso ter um número de 0 à 9. {1,3} significa que você pode ter de 1 à três ocorrências mas, de que ? Note que o [0-9] e o {1,3} estão juntos, logo eu posso ter de 1 à 3 ocorrências de números que vão de 0 à 9.

O segredo de entender uma regex é saber avaliar as partes mas, também saber avaliar o todo.

Os parênteses () significam agrupamento e, o ?: significa que realizo um agrupamento sem guardar dados em um vetor interno mas, hein ? Quando você monta uma regex agrupada os valores capturados por ela são guardados em um vetor para utilização futura.

A contra barra \ significa caracter de escape, por que usei isso ?A máscara deve aceitar ponto como separador decimal mas, o caracter . têm significado próprio no contexto da regex, logo uso a contra barra para dizer ao javascript que o caracter ponto não deve ser levado em conta como sendo uma regex. Logo, após o ponto encontramos outro [0-9], já sabemos o que significa.

O {2} significa que só posso ter duas ocorrências de ?:\.[0-9], ou seja, eu só posso ter duas casas depois da vírgula. Logo, após o fecha parênteses ) encontramos um ?. Isso significa que 1 ou nenhuma ocorrência de (?:\.[0-9]{2}), ou seja, que eu posso ter duas casas depois da vírgula ou não para que tais valores sejam aceitos:

-7
-85
-856
85
99
2
856.55
-856.55

O sinal de $ denota fim de sentença, logo estamos validando também o fim da sentença também. Podemos notar que construimos uma regex fechada. Para por em prática essa regex podemos usar métodos especiais para isso, como o test() que valida se um valor passado como parâmetro está de acordo com a regex ou não, retornando true ou false.

Qualquer dúvida é só comentar.

3 comentários:

Cleiton disse...

Muito boa sua explicação, realmente me ajudou muito!

Vlw!

Anônimo disse...

Parabéns... me ajudou muito, segue minha contribuição... fiz algumas alterações para aceitar tanto o ponto como a vírgula como separador de sinal e também para aceitar 1 ou 2 casas decimais depois do ponto, e também desmembrei a regex de forma que pelo menos pra mim ficou mais fácil de entender:

"/" ==> Em uma regex e obrigatório iniciar e terminar com uma barra
"^" ==> A regex vai validar inicio de sentença
"-?" ==> Posso ter uma ou nenhuma ocorrência do sinal negativo "-"
"\d" ==> Pode ter dígitos de 0 a 9, o mesmo que "[0-9]"
"{1,2}" ==> Pode ter de 1 a 2 ocorrências de números de 0 a 9 "\d", portanto serao validos valores de 0 a 99
"(?:)" ==> Agrupamento, o "?:" indica que os valores nao serao guardados no vetor interno da regex
"[\.\,]" ==> Deve aceitar ponto ou virgula como separador de decimal, a barra invertida serve de caracter de escape já que o ponto e a virgula tem significado dentro da sintaxe do regex
"\d" ==> Pode ter dígitos de 0 a 9, o mesmo que "[0-9]"
"{1,2}" ==> Podem existir 1 a 2 ocorrências de 0 a 9 depois do ponto
"()?" ==> A interrogação indica que a expressão no parenteses, pode ou não existir, ou seja, depois do ponto, pode ou não existir números
"$" ==> Fim da sentença

regex = /^-?\d{1,2}(?:[\.\,]\d{1,2})?$/;

Preciso estudar sempre disse...

Meu nobre amigo, te agradeço imensamente pelo seu comentário, explicação e nova regex. É muito bom saber que existem pessoas que gostam de compartilhar suas idéias, isso é muito legal e motiva quem se esforça para por um conteúdo de qualidade na internet. Você gostou do post ? Estava bem explicado ? O texto estava bem escrito ? Se puder e quiser, inscreva-se por email e fique por dentro das novidades. Sinta-se a vontade para sugerir temas.

:D

Preciso Estudar Sempre