HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptCritical

HTML text input allow only numeric input

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
inputnumerictextallowonlyhtml

Problem

Is there a quick way to set an HTML text input (``) to only allow numeric keystrokes (plus '.')?

Solution

JavaScript

Update: easier solution seems to use beforeinput event.

You can filter the input values of a text ` with the following setInputFilter function (supports Copy+Paste, Drag+Drop, keyboard shortcuts, context menu operations, non-typeable keys, the caret position, different keyboard layouts, validity error message, and all browsers since IE 9):
// Restricts input for the given textbox to the given inputFilter function.
function setInputFilter(textbox, inputFilter, errMsg) {
[ "input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout" ].forEach(function(event) {
textbox.addEventListener(event, function(e) {
if (inputFilter(this.value)) {
// Accepted value.
if ([ "keydown", "mousedown", "focusout" ].indexOf(e.type) >= 0){
this.classList.remove("input-error");
this.setCustomValidity("");
}

this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
}
else if (this.hasOwnProperty("oldValue")) {
// Rejected value: restore the previous one.
this.classList.add("input-error");
this.setCustomValidity(errMsg);
this.reportValidity();
this.value = this.oldValue;
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
}
else {
// Rejected value: nothing to restore.
this.value = "";
}
});
});
}


You can now use the
setInputFilter function to install an input filter:
setInputFilter(document.getElementById("myTextBox"), function(value) {
return /^\d\.?\d$/.test(value); // Allow digits and '.' only, using a RegExp.
}, "Only digits and '.' are allowed");


Apply your preferred style to the
input-error class. Here’s a suggestion:
.input-error{
outline: 1px solid red;
}


Note that you still must do server side validation!

Another caveat is that this will break the undo stack since it sets
this.value directly.
This means that CtrlZ will not work to undo inputs after typing an invalid character.
Demo

See the JSFiddle demo for more input filter examples or run the Stack snippet below:



// Restricts input for the given textbox to the given inputFilter.
function setInputFilter(textbox, inputFilter, errMsg) {
[ "input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout" ].forEach(function(event) {
textbox.addEventListener(event, function(e) {
if (inputFilter(this.value)) {
// Accepted value.
if ([ "keydown", "mousedown", "focusout" ].indexOf(e.type) >= 0) {
this.classList.remove("input-error");
this.setCustomValidity("");
}

this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
}
else if (this.hasOwnProperty("oldValue")) {
// Rejected value: restore the previous one.
this.classList.add("input-error");
this.setCustomValidity(errMsg);
this.reportValidity();
this.value = this.oldValue;
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
}
else {
// Rejected value: nothing to restore.
this.value = "";
}
});
});
}

// Install input filters.
setInputFilter(document.getElementById("intTextBox"), function(value) {
return /^-?\d*$/.test(value);
}, "Must be an integer");
setInputFilter(document.getElementById("uintTextBox"), function(value) {
return /^\d*$/.test(value);
}, "Must be an unsigned integer");
setInputFilter(document.getElementById("intLimitTextBox"), function(value) {
return /^\d*$/.test(value) && (value === "" || parseInt(value)
.input-error {
outline: 1px solid red;
}

JavaScript input filter showcase

Supports Copy+Paste, Drag+Drop, keyboard shortcuts, context menu operations, non-typeable keys, the caret position, different keyboard layouts, and all browsers since IE 9.

There is also a jQuery version of this.


Integer



Integer >= 0



Integer >= 0 and <= 500



Float (use . or , as decimal separator)



Currency (at most two decimal places)



A-Z only



Hexadecimal






TypeScript

Here is a TypeScript version of this.
`function setInputFilter(textbox: Element, inputFilter: (value: string) => boolean, errMsg: string): void {
["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout" ].forEach(function(event) {
textbox.addEventListener(event, function(this: (HTMLInputElement | HTMLTextAreaElement) & { oldValue: string; oldSelectionStart: number | null, oldSelectionEnd: number | null }) {
if (inputFilter(this.value)) {
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this

Context

Stack Overflow Q#469357, score: 1362

Revisions (0)

No revisions yet.