Note: This is an updated answer. Comments below refer to an old version which messed around with keycodes.
JavaScript
Try it yourself on JSFiddle.
You can filter the input values of a text <input>
with the following setInputFilter
function (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):
// Restricts input for the given textbox to the given inputFilter function.
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 = "";
}
});
});
}
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
});
See the JSFiddle demo for more input filter examples. Also note that you still must do server side validation!
TypeScript
Here is a TypeScript version of this.
function setInputFilter(textbox: Element, inputFilter: (value: string) => boolean): void {
["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop"].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.selectionEnd;
} else if (Object.prototype.hasOwnProperty.call(this, 'oldValue')) {
this.value = this.oldValue;
if (this.oldSelectionStart !== null &&
this.oldSelectionEnd !== null) {
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
}
} else {
this.value = "";
}
});
});
}
jQuery
There is also a jQuery version of this. See this answer.
HTML 5
HTML 5 has a native solution with <input type="number">
(see the specification), but note that browser support varies:
- Most browsers will only validate the input when submitting the form, and not when typing.
- Most mobile browsers don't support the
step
, min
and max
attributes.
- Chrome (version 71.0.3578.98) still allows the user to enter the characters
e
and E
into the field. Also see this question.
- Firefox (version 64.0) and Edge (EdgeHTML version 17.17134) still allow the user to enter any text into the field.
Try it yourself on w3schools.com.
It looks like Mobile Safari supports the new HTML5 input type attributes of email, number, search, tel, and url. These will switch the keyboard that is displayed. See the type attribute.
So for example, you could do this:
<input type="number" />
And when the input box has focus, the number keyboard is shown (as if the user had the full keyboard and hit the "123" button.
If you really only want numbers, you could specify:
<input type="tel" />
And then the user would get the phone number dialing keypad.
I know this works with Mobile Safari -- I only assume it will work with UIWebView.
Best Solution
You probably want to take a look at this: https://css-tricks.com/finger-friendly-numerical-inputs-with-inputmode/
The
inputmode
will work on the latest Android browsers, and thepattern
is a hack for iOS. Pay special attention to the article where they talk about iOS not allowing the user to change keyboards.Hope it helps.