Reputation: 393
I want to make an Input-Field in which you can only write natural numbers. (Yes, I know this can be a bad practice, as the user doesn't get any feedback). If you type anything else than a digit, it should not appear in the input. I want to use plain JavaScript (no JQuery).
This is how I'd do it normally:
<input oninput="this.value = this.value.replace(/\D+/g, '')">
But I found out, that <input type="number">
is much preferred for mobile devices, as it doesn't show the whole keyboard, but just digits.
So my question is, how can I combine type="number"
with the filtering (and make it compatible with Cut/Copy/Paste)?
The value of the <input type="number">
-element is always an empty String if any non-number-character is entered. So my filtering method from above doesn't work. Is there any workaround?
If not, I'd have to listen for keydown, paste, cut, and possibly many more events. Which events would I have to consider, how would I implement it, and is there any easier way I have overlooked?
Upvotes: 8
Views: 39988
Reputation: 376
<input onkeydown=this.isNumberInputOnly />
and the function
function isNumberOnlyInput(event) {
if (!parseInt(event.key) && event.key != 'Backspace') {
event.preventDefault();
}
}
can roughly do the trick
Upvotes: 1
Reputation: 1519
Here is a solution using HTML and vanilla JS:
function setInputFilter(textbox, inputFilter) {
["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop"].forEach(function(event) {
textbox.addEventListener(event, function() {
if (inputFilter(this.value)) {
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
} else if (this.hasOwnProperty("oldValue")) {
this.value = this.oldValue;
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
} else {
this.value = "";
}
});
});
}
setInputFilter(document.getElementById("numTxtBox"), function(value) {
return /^-?\d*$/.test(value); });
<tr><td>Number Only </td><td><input id="numTxtBox"></td></tr>
UPDATE:
The above code does malfunction in Firefox and Chrome.
Here is an alternate solution that works across all browsers!
function validate(num) {
var theEvent = num || window.event;
// Handle paste
if (theEvent.type === 'paste') {
var key = event.clipboardData.getData('text/plain');
} else {
// Handle key press
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
}
var regex = /[0-9]|\./;
if( !regex.test(key) ) {
theEvent.returnValue = false;
if(theEvent.preventDefault) theEvent.preventDefault();
}
}
<input type='number' onkeypress='validate(event)' onpaste='validate(event)' />
Upvotes: 3
Reputation: 178413
Tested in Chrome (cannot enter anything else than numbers, - and e
In Firefox you can type but not submit
Try typing anything and then hit enter
<form>
<input type="number" required />
</form>
Let's try this then - if it is ok to clear the field when typing a char, we do not need keyUp or such
Firefox will return empty string if you type a char anywhere, Chrome will not allow the char
document.querySelector("form").addEventListener("input",function(e) {
const tgt = e.target;
if (tgt.type && tgt.type==="number") {
const val = tgt.value;
const nums = val.replace(/[^\d.-]/g, '');
if (!/\d+/.test(val)) tgt.value="";
}
})
Try typing anything and then hit enter
<form>
<input type="number" required />
</form>
Upvotes: 3
Reputation: 20039
Try using inputmode
attribute
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode
<input inputmode="numeric" oninput="this.value = this.value.replace(/\D+/g, '')" />
References
https://css-tricks.com/finger-friendly-numerical-inputs-with-inputmode
Upvotes: 14