Prevent Change of Keyboard Layout When Applying Money Mask

2

I'm trying to implement a money mask using a NumberFormat, but an unwanted behavior is occurring when running the script on Chrome for Android.

Whenever a new number is entered, the keyboard layout returns to the default (alphabetic), however you would like it to remain with the numeric layout.

Follow 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, Log in to JSFiddle , then go to the following < a href="https://jsfiddle.net/TobyMosque/h8s5qq1h/"> JSFiddle , run it, then go to the JSFiddle Draft

    
asked by anonymous 15.10.2015 / 16:52

1 answer

0

I ended up modifying the script to change the input:type to tel , so the keyboard that came up was only the numeric and allowed the inclusion of other characters (something that 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 user friendly with mobile devices.

    
15.10.2015 / 19:02