Prevent Keyboard Layout Change when Applying Money Mask

Asked

Viewed 59 times

2

I am trying to implement a money mask using a Numberformat, but there is an unwanted behavior while running the script in Chrome for Android.

Whenever a new number is inserted, the keyboard layout returns to the default (alphabetic), but would like it to remain with the Numeric layout.

Follows the Script.

var real = document.getElementById("real");
var euro = document.getElementById("euro");
var dollar = document.getElementById("dollar");

var Mascara = function (elemento, localizacao, moeda, digitos) {    
  var self = this;    

  this.target = elemento;
  this.options = {}
  this.options.minimumIntegerDigits = 1;
  this.options.minimumFractionDigits = digitos;
  this.options.maximumFractionDigits = digitos;
  var defaultFormat = new Intl.NumberFormat(localizacao, this.options);

  this.options.style = "currency";
  this.options.currency = moeda;
  this.numberFormat = new Intl.NumberFormat(localizacao, this.options);
  this.base10 = Math.pow(10, digitos);

  var semSimbolo = defaultFormat.format(0);
  var comSimbolo = this.numberFormat.format(0);

  if (comSimbolo.indexOf(semSimbolo) == 0) {
    this.prefix = "";
    this.suffix = comSimbolo.replace(semSimbolo, "");
  } else {
    this.prefix = comSimbolo.replace(semSimbolo, "");
    this.suffix = "";
  }

  elemento.addEventListener("input", function (event) {
    Mascara.onInput(self);
  });
  elemento.addEventListener("focus", function (event) {
    Mascara.onInput(self);
  });
}

Mascara.nonNumericPattern = /[^0-9]/g;

Mascara.onInput = function (self) {   
  var oldLength = self.target.value.length;
  var oldRange = self.target.selectionEnd;
  var minRange = self.prefix.length + 1;
  if (oldRange < minRange)
    oldRange = minRange;

  var value = self.target.value.replace(Mascara.nonNumericPattern, "");
  var numero = value ? parseInt(value) / self.base10 : 0;

  self.target.value = self.numberFormat.format(numero);

  var maxRange = self.target.value.length - self.suffix.length;
  var newRange = oldRange + (self.target.value.length - oldLength);
  if (newRange > maxRange)
    newRange = maxRange;
  self.target.setSelectionRange(newRange, newRange);
}

new Mascara(real, "pt-BR", "BRL", 2);
new Mascara(euro, "pt-PT", "EUR", 2);
new Mascara(dollar, "en-US", "USD", 2);
<div>
  <label>
    Real:
    <input id="real" type="text" />
  </label>
</div>
<div>
  <label>
    Euro:
    <input id="euro" type="text" />
  </label>
</div>
<div>
  <label>
    Dollar:
    <input id="dollar" type="text" />
  </label>
</div>

To test the above code on a device on a mobile device, do the Logon no Jsfiddle, then access the following Jsfiddle, perform the same, then access the Jsfiddle Draft

1 answer

0


I ended up modifying the script to change the input:type for tel, this way the keyboard that emerged was only the numeric and allowed the inclusion of other characters (thing that the input[type='number'] does not allow).

follows the updated version of the script:

var real = document.getElementById("real");
var euro = document.getElementById("euro");
var dollar = document.getElementById("dollar");

var Mascara = function (elemento, localizacao, moeda, digitos) {    
  var self = this;    

  this.target = elemento;
  var options = {}

  options.minimumIntegerDigits = 1;
  options.minimumFractionDigits = digitos;
  options.maximumFractionDigits = digitos;    
  var defaultFormat = new Intl.NumberFormat(localizacao, options);

  options.style = "currency";
  options.currency = moeda;    
  this.numberFormat = new Intl.NumberFormat(localizacao, options);
  this.base10 = Math.pow(10, digitos);

  var semSimbolo = defaultFormat.format(0);
  var comSimbolo = this.numberFormat.format(0);

  if (comSimbolo.indexOf(semSimbolo) == 0) {
    this.prefix = "";
    this.suffix = comSimbolo.replace(semSimbolo, "");
  } else {
    this.prefix = comSimbolo.replace(semSimbolo, "");
    this.suffix = "";
  }

  this.target.type = "tel";
  this.target.addEventListener("input", function (event) {
    Mascara.onInput(self);
  });
  this.target.addEventListener("focus", function (event) {
    Mascara.onInput(self);
  });
}

Mascara.nonNumericPattern = /[^0-9]/g;

Mascara.onInput = function (self) {   
  var oldLength = self.target.value.length;
  var oldRange = self.target.selectionEnd;

  var minRange = self.prefix.length + 1;
  if (oldRange < minRange)
    oldRange = minRange;

  var value = self.target.value.replace(Mascara.nonNumericPattern, "");
  var numero = value ? parseInt(value) / self.base10 : 0;

  self.target.value = self.numberFormat.format(numero);

  var maxRange = self.target.value.length - self.suffix.length;
  var newRange = oldRange + (self.target.value.length - oldLength);
  if (newRange > maxRange)
    newRange = maxRange;

  self.target.setSelectionRange(newRange, newRange);
}

new Mascara(real, "pt-BR", "BRL", 2);
new Mascara(euro, "pt-PT", "EUR", 2);
new Mascara(dollar, "en-US", "USD", 2);
<div>
    <label>
        Real:
        <input id="real" type="text" />
    </label>
</div>
<div>
    <label>
        Euro:
        <input id="euro" type="text" />
    </label>
</div>
<div>
    <label>
        Dollar:
        <input id="dollar" type="text" />
    </label>
</div>

with this, I believe I have a money mask that is friendly with mobile devices.

Browser other questions tagged

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