Reputation: 11
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
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.
JS Fiddle (I don't know how to embed it to the answer)
Upvotes: 1
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