How to create a mask for Brazilian currency with character limit?

Asked

Viewed 1,203 times

0

I have a code that formats the values for Brazilian currency (BRL) that works very well, but I need it to limit the number to 15 digits. Where do I put this validation?

// parâmetros da função moeda (pelo que entendi)
// a = objeto do input // e = separador milésimo
// r = separador decimal // t = evento

function moeda(a, e, r, t) {
   let n = "",
      h = j = 0,
      u = tamanho2 = 0,
      l = ajd2 = "",
      o = window.Event ? t.which : t.keyCode;
   if (13 == o || 8 == o)
      return !0;
   if (n = String.fromCharCode(o),
      -1 == "0123456789".indexOf(n))
      return !1;
   for (u = a.value.length,
      h = 0; h < u && ("0" == a.value.charAt(h) || a.value.charAt(h) == r); h++);
   for (l = ""; h < u; h++) - 1 != "0123456789".indexOf(a.value.charAt(h)) && (l += a.value.charAt(h));
   if (l += n, 0 == (u = l.length) && (a.value = ""), 1 == u && (a.value = "0" + r + "0" + l), 2 == u && (a.value = "0" + r + l), u > 2) {
      for (ajd2 = "",
         j = 0,
         h = u - 3; h >= 0; h--)
         3 == j && (ajd2 += e,
            j = 0),
         ajd2 += l.charAt(h),
         j++;
      for (a.value = "",
         tamanho2 = ajd2.length,
         h = tamanho2 - 1; h >= 0; h--)
         a.value += ajd2.charAt(h);
      a.value += r + l.substr(u - 2, u)
   }
   return !1
}
<ul class="nav">
   <li>
      <label>Valor Renda no Período (R$)</label><br />
      <input type="text" required maxlength="15" style="border: solid 0.5px #000; width: 200px;" onkeypress="return(moeda(this,'.',',',event))">
   </li>
</ul>

  • 1

    The variable you are looking for is "a", with the code" a.value.replace(/[ d]+/g,') " you get the numbers, then you need to handle it.-

2 answers

4


Place at the beginning of function one if with the replace indicated by the friend @Null in the comments, adding the method .length that will return the number of digits in the input.

Just need a.value.replace(/[^\d]/g, '').length, where the regex /[^\d]/g will delete everything that is not number. Then you will compare with the attribute maxlength:

if(a.value.replace(/[^\d]/g, '').length > a.getAttribute("maxlength")-1)
    return

The code a.getAttribute("maxlength") will return 15 (of the attribute maxlength="15") subtracting 1, that is, if the amount of numbers in the input is greater than 14, will enter the return of if leaving the function, and thus allowing a maximum of 15 numbers.

Behold:

function moeda(a, e, r, t) {

   if(a.value.replace(/[^\d]/g, '').length > a.getAttribute("maxlength")-1)
    return

   let n = ""
     , h = j = 0
     , u = tamanho2 = 0
     , l = ajd2 = ""
     , o = window.Event ? t.which : t.keyCode;
   if (13 == o || 8 == o)
       return !0;
   if (n = String.fromCharCode(o),
   -1 == "0123456789".indexOf(n))
       return !1;
   for (u = a.value.length,
   h = 0; h < u && ("0" == a.value.charAt(h) || a.value.charAt(h) == r); h++)
       ;
   for (l = ""; h < u; h++)
       -1 != "0123456789".indexOf(a.value.charAt(h)) && (l += a.value.charAt(h));
   if (l += n,
   0 == (u = l.length) && (a.value = ""),
   1 == u && (a.value = "0" + r + "0" + l),
   2 == u && (a.value = "0" + r + l),
   u > 2) {
       for (ajd2 = "",
       j = 0,
       h = u - 3; h >= 0; h--)
           3 == j && (ajd2 += e,
           j = 0),
           ajd2 += l.charAt(h),
           j++;
       for (a.value = "",
       tamanho2 = ajd2.length,
       h = tamanho2 - 1; h >= 0; h--)
           a.value += ajd2.charAt(h);
       a.value += r + l.substr(u - 2, u)
       
   }
   return !1
}
<ul class="nav">
   <li>
      <label>Valor Renda no Período (R$)</label><br/>
      <input type="text" required maxlength="15" style="border: solid 0.5px #000; width: 200px;" onkeypress="return(moeda(this,'.',',',event))">
   </li>
</ul>

  • Perfect, man, gosh, it worked perfectly!!! Thank you so much!!

  • Códigozinho, although large, is functional. Thanks, Lopes Gabiroba. Rs

1

An alternative with a smaller code.

function mascaraMoeda(event) {
  const onlyDigits = event.target.value
    .split("")
    .filter(s => /\d/.test(s))
    .join("")
    .padStart(3, "0")
  const digitsFloat = onlyDigits.slice(0, -2) + "." + onlyDigits.slice(-2)
  event.target.value = maskCurrency(digitsFloat)
}

function maskCurrency(valor, locale = 'pt-BR', currency = 'BRL') {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency
  }).format(valor)
}
<input type="text" onInput="mascaraMoeda(event);" />

  • It is not exactly "what the author wants", but congratulations for the refactoring of the code, greatly reduced the lines and as the ES6 follow-up.. batter!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.