Cartha
Cartha

Reputation: 11

JavaScript - Accepting only certain values for decimals

I have a number field to which I need to apply certain conditions with pure JS or jQuery:

I managed to do so unless for the last condition that should accept only values .00 or .25 or .50 or .75 Here is my code:

var t_myField   = false;
var myField_min = -30;
var myField_max = 30;
$('#myField').focus(function ()
{
    var $this = $(this)
    t_myField = setInterval(
        function ()
        {
            if (($this.val() < myField_min || $this.val() > myField_max) && $this.val().length != 0)
            {
                if ($this.val() < myField_min)
                {
                    $this.val(myField_min)
                }
                if ($this.val() > myField_max)
                {
                    $this.val(myField_max)
                }
            }
        }, 50)
});

$('#myField').on("keyup", function (e)
{
    // Replacer , by .
    $(this).val($(this).val().replace(/,/g, '.'));

    // Allow only float numeric values (positif & negatif)
    var self = $(this);
    self.val(self.val().replace(/[^0-9\.-]/g, ''));
    if (e.which != 46 && e.which != 45 && e.which != 46 && !(e.which >= 48 && e.which <= 57))
    {
        e.preventDefault();
    }

    // Allow max 2 digits after decimals for certain fields
    match      = (/(\d{0,2})[^.]*((?:\.\d{0,2})?)/g).exec(this.value.replace(/[^\d.]/g, ''));
    this.value = match[1] + match[2];
});
<input type="text" name="myField" id="myField" class="myField">

JSFIDDLE => https://jsfiddle.net/Cartha/vq65Lypj/5/

[EDIT] Control should be on keyup. This is why I can't use html5 attributes like min/max/step...

Upvotes: 0

Views: 192

Answers (3)

Ernesto Stifano
Ernesto Stifano

Reputation: 3130

let myField = document.getElementById('myField');

myField.addEventListener('keypress', onlyNumbers,{passive: false});
myField.addEventListener('change', checkInput);

function onlyNumbers(e) {
    if (!isNumberKey(e)) {
        e.preventDefault();
    }
}

function isNumberKey(e) {
    return (e.which <= 31 || (e.which >= 48 && e.which <= 57) || e.which === 45 || e.which === 46);
}

function checkInput(e) {
    let x = parseFloat(e.target.value);
    if (!isNaN(x)) {
      if (x > 30) {
        x = 30;
      } else if (x < -30) {
        x = -30;
      } else if (x % 0.25 !== 0) {
        x = Math.round(x / 0.25) * 0.25;
      }
      e.target.value = x.toFixed(2);
    }
}

This will allow only numbers with 0.25 steps.

Digit-only algorithm has been improved to completely prevent other type of input to be displayed (your code shows the forbidden input and then erases it).

This is the basic idea, a lot of other improvements can be made. For example, to always show two decimals (EX. 2.00 instead of 2), make an animation, etc. Currently, the check is set to happen after focus ends.

  • NOTE: Little extra improvements made in last edit.

JS Fiddle (I don't know how to embed it to the answer)

Upvotes: 1

connexo
connexo

Reputation: 56853

I would recommend creating a web component here. I'll show you the basic setup for a customized built-in with a component that already works and does not involve fumbling with $(document).ready() or DOMContentLoaded:

class DecimalInput extends HTMLInputElement {
  constructor() {
    super();
    this.addEventListener('input', (e) => {
      const val = parseFloat(this.value),
        min = parseFloat(this.min),
        max = parseFloat(this.max),
        step = parseFloat(this.step);
        
      if (val%step !== 0) {
        this.value = Math.round(val/step) * step
      }
      if (val > max) {
        this.value = max
      }
      if (val < min) {
        this.value = min
      }
      
      this.value = Number(this.value).toFixed(2, 10);
    })
  }
}

customElements.define('decimal-input', DecimalInput, { extends: 'input' })
<input type="number" is="decimal-input" min="-30" max="30" step="0.25" value="0" />

This component is already quite close to your requirements. Use it to do our own refinements based on this.

Upvotes: 0

user3307073
user3307073

Reputation:

You can make use of % operator like x % 0.25 == 0 ? true : false

Upvotes: 1

Related Questions