Formatar moeda no onblur – javascript sem jQuery

Diferente das demais máscaras de moeda em javascript, assim como essa minha que formata usando Expressão Regular no onkeyUp do campo, a máscara que apresento agora, formata no evento onblur.

Aceita as entradas:

,1 = 0,10
,10 = 0,10
1 = 1,00
10 = 10,00
100 = 100,00

money-blur.js

'use strict';
function _signalFirst(v) {
  return /^(,|\.)/.test(v);
}
function _signalOne(v) {
  return /,|\.+\d$/.test(v);
}
function _onlyNumber(v) {
  return /^\d+$/.test(v);
}
function _rightPosition(v) {
  return /(,|\.)\d{2}$/.test(v);
}
function _format(v) {
  var length = v.length;

  if (_signalFirst(v)) {
    console.log('_signalFirst');

    v = v.replace(/[,.]/, '');
    if (length===2) v = '0,' + v + '0';
    else v = '0,' + v;
  } else if (_onlyNumber(v)) {
    console.log('_onlyNumber');

    v = v + ',00';
  } else if (_rightPosition(v)) {
    console.log('_rightPosition');

    v = v.replace(/[,.]/, '');
    v = v.replace(/(\d)(\d{2})$/, '$1,$2');
  } else if (_signalOne(v)) {
    console.log('_signalOne');

    v = v.replace(/[,.]/, '');
    v = v + '0';
    v = v.replace(/(\d)(\d{2})$/,"$1,$2");
  } else {
    v = v.replace(/[,.]/, '');
    v = v.replace(/(\d{1,3})$/g,"$1,00");
    v = v.replace(/(\d{1,3})(\d{3},00)$/,"$1.$2");
  }
  return v;
}

if (typeof exports !== 'undefined') {
  if (typeof module !== 'undefined' && module.exports) {
    exports = module.exports = _format;
  }
  exports._format = _format;
}

usando no teu html..

<script type="text/javascript">
function id(el){
  return document.getElementById(el);
}
window.onload = function(){
  id('moeda').onkeyup = function() {
      var v = this.value;
      v = v.replace(/[^\d,.]/, '');
      this.value = v;
  };
  id('moeda').onblur = function() {
    var v = this.value;
    this.value = _format(v);
  }
};
</script>
<input type="text" name="moeda" id="moeda" />

É isso galera. Comente caso usem =)

Demonstração no Github

http://wbruno.github.io/examples/money-blur/

24 Comments

  1. Bruno,

    Pelo pouco que conheço de desenvolvimento web e javascript, não acho interessante construir uma função de máscara utilizando o id de uma tag. Acho mais aconselhável a utilização de get por class.

    E acho que esse tipo de construção de máscara já está um pouco atrasada com relação aos framework como o jquery.

    • Hum… não tem nada atrasado Alan.. =)
      Essa construção de máscara funciona perfeitamente bem, e é infinitamente mais leve do que alguma que for feita com jQuery.

      A possibilidade, é ter jQuery no teu projeto, e mesmo assim usar essa ótima máscara em js puro e Expressão Regular.
      Tanto faz, se vc invocar por class ou por ID. A minha proposta não é limitada. Você pode invocar por class sim, sem problemas.

      Obrigado pelo comentário.. mas dá uma estudada melhor antes, ok ? =)

  2. Bruno Salvouu minha vida ‘-‘… vou tentar fazer com keypress para que enquanto o usuario digite já seja aplicado (pra ficar tipo máscara sem ter que usar plugin… meu chefe n gosta de plugin rsrsrs)u.u’

  3. esta parada ai nao funciona nao cara.

  4. Boa tarde,

    Estou com um problema pra usar esse script, o meu script esta pra calcular o valor total como auto soma, porem quando coloco um valor no input por exemplo 0,01 o input já esta formatado pra moeda, a saida no valor total esta saindo assim 0,001 e assim sucessivamente, sabe me dizer o porque?

  5. Boa tarde Bruno. Obrigado pela grande colaboração. Estou com um problema para usar o seu código. O que mais gostei é não ter de digitar os zeros à direita para os valores inteiros. Espero que possa me ajudar. Veja o que acontece:
    1) Não impede a digitação de caracteres não numéricos;
    2) Quando digito 100.10 (ponto) retorna 100.10,00
    Quando digito 100,10 (vírgula) retorna 100,10,00
    Quando digito .10 (ponto) retorna .10,00
    Obrigado!

    • Oi João, eu editei o post.

      Teste agora por favor.

      • Bom dia William Bruno. Agradeço a atenção e ainda mais a prontidão. Pessoas como você disseminam o conhecimento. Parabéns.
        Quero lhe fazer um novo pedido, se não for demais.
        Com a nova versão, o código perdeu, o que penso, o diferencial entre os demais que é a desnecessidade de digitar “,00” para os valores inteiros. Exemplificando:
        Digitando 111 responde 1,11 e não 111,00
        Também ocorre:
        Digitando 111,4 responde 11,14 e não 111,40
        A ideia, se me permite é a da utilizada no site do banco do brasil
        Se não digitar vírgula, o código interpreta como inteiro
        Se digitar vírgula ele o formata com duas casas decimais, mesmo que o usuário digite parte das duas casas.
        Agradeço a sua postura.

      • Cara.. haha vamos fazer direito isso!
        Escrevi testes automáticos e cobri os seguintes cenários.

            ✓ ,10 -> 0,10
            ✓ .10 -> 0,10
            ✓ 100 -> 100,00
            ✓ 10,10 -> 10,10
            ✓ 10.10 -> 10,10
            ✓ 10,1 -> 10,10
            ✓ 10.1 -> 10,10
        

        Se faltar algum, por favor reporte, que ai eu adiciono no script.
        Agora está hospedado no github, juntamente com o teste para garantir que não quebre um comportamento antigo.

        http://wbruno.github.io/examples/money-blur/

  6. Bom dia Bruno. Muito bom, vou testar e aviso. Agradeço mais uma vez a grande ajuda!!!!!!!!!!!!!

  7. Boa tarde Bruno.

    Testei com sucesso. Obrigado. Um último pedido: onde eu teria de alterar o código para 4 casas decimais?

    Obrigado!

  8. Oi Bruno.

    Testei com sucesso o exemplo de http://wbruno.github.io/examples/money-blur/

    Poderia me ajudar ampliando o código para 4 casas decimais? Onde eu teria de alterar?

    Obrigado!

  9. Oi Bruno.

    Descobri mais um pequeno equívoco no código.

    Se digitar ,111 responde corretamente 0,111
    Já se digitar 0,111 responde 011,10 (deveria finalizar 0,111

    Se puder corrigir… Obrigado.!

    • Ae João, tudo bem?
      vc conseguiu fazer isso funcionar em uma página xhtml com o jsf/ primefaces ?
      Abraço!
      Marcao

      • Boa tarde Marcão.

        Usei o código numa página html para servir de máscara de um input numérico com 2 casas decimais.

    • O código não foi feito para 3 dígitos após a vírgula, precisa mudar bastante coisa lá.

      Escreve um cenário de teste.

      • Boa tarde William Bruno.

        Sim, sem dúvida, não foi feito para 3 dígitos. Porém o usuário pode digitar como exemplifiquei e aí fica com erro. Imagino se seria possível impedir que digitasse ou corrigir após o evento onblur, eliminando a 3a casa decimal porventura digitada.
        Os exemplos onde vi os erros são:
        Se digitar ,111 responde 0,111 (deveria eliminar o 3° dígito retornando 0,11 ou avisar do erro)
        Já se digitar 0,111 responde 011,10 (deveria eliminar o 3° dígito, retornando 0,11 ou avisar do erro)

        Obrigado pela sua disposição em ajudar.

  10. Rodrigo Barbosa

    maio 16, 2016 at 20:03

    Boa noite, William B.

    Há condição de se obter a funcionalidade desse script em saída de valor? Ou seja, ao invés de input, ser no tipo output?

    A propósito, estou iniciando nessa jornada…sempre buscando auto-ajuda para desenvolver meus projetos, são desafios de superações alcançáveis , graças a minha persistência e engajamento. Com isso, quero agradecer a você, pelo excelente trabalho , parabéns!

  11. Cara, salvou minha vida! Muito obrigada 😉

  12. Perfeito, exatamente o que precisava, leve e não formata o campo enquanto o usuário esta digitando, só precisei pegar por class ao invés de id pois uso vários desses campos em uma única tela.
    Muito obrigado.

Deixe uma resposta

Your email address will not be published.

*