Keyboard Input Filtering

JavaScript FAQ | Keyboard & Mouse Events FAQ  

Question: Can I use JavaScript to allow digits only in a TEXT or TEXTAREA input field?

Answer: First, the usual word of caution: full form validation must occur on the server side because the users can always circumvent the client-side validation, e.g. by disabling JavaScript in the browser. Also, keyboard is not the only input device used in forms: some users might drag or cut-and-paste values into forms using the mouse alone! Now, assuming that we perform the keyboard input filtering (or, for that matter, any other kind of form validation) on the client-side in addition to the server-side validation, below we present a couple of examples showing how to filter out all non-digit input in a cross-browser fashion.

Example 1: onkeypress and onkeyup event handlers within the form markup.

Type something: <input type=text>
Type something: <textarea>
This example has been tested in Internet Explorer 8.0, Firefox 3.6, Opera 11, Safari 5.0.3, and Chrome 10 - and everywhere the validation works as expected. The code of Example 1 is short and self-explanatory. However, there are several drawbacks with this solution:
(1) Non-digit characters may briefly show up (one at a time) until the user releases the "offending" key. This is a usability issue, albeit a minor one.
(2) The onkeypress and onkeyup event handlers are present as HTML attributes of the form elements, cluttering the form markup. A better alternative would be to register the event handlers programmatically.
(3) Instead of just one event handler, we are using two: onkeypress and onkeyup. (If we try onkeypress only, testing shows that one "offending" character may survive our filtering. If we try onkeyup only, then a string of "offending" characters may appear on autorepeat if the user presses and holds a non-digit key. That's because keypress events do occur on autorepeat, while keyup events do not.) Example 2 below addresses all these issues.

Source code of Example 1:

<form action=# name=f1 id=f1 onsubmit="return false">
<input type=text name=t1 id=t1 value="" size=25 style="width:300px;"
 onkeypress="if(this.value.match(/\D/)) this.value=this.value.replace(/\D/g,'')"
 onkeyup   ="if(this.value.match(/\D/)) this.value=this.value.replace(/\D/g,'')"
>
<br><textarea  name=t2 id=t2 cols=25 rows=2 style="width:300px;"
 onkeypress="if(this.value.match(/\D/)) this.value=this.value.replace(/\D/g,'')"
 onkeyup   ="if(this.value.match(/\D/)) this.value=this.value.replace(/\D/g,'')"
>
</textarea>
</form>

Example 2: one keypress per form element, registered programmatically.

Type something: <input type=text>
Type something: <textarea>

Just like Example 1, this code also works in all browsers listed above. Left and right arrows, Home, End, Delete, Backspace keys, select-all (Ctrl+A), copy (Ctrl+C) and other common operations work as expected within the input field.

Source code of Example 2:

<form action=# name=f2 id=f2 onsubmit="return false">
<input type=text name=t1 id=t1f2 value="" size=25 style="width:300px;">
<br><textarea    name=t2 id=t2f2 cols=25 rows=2 style="width:300px;">
</textarea>
</form>

<script type="text/javascript" language=JavaScript>
function inputDigitsOnly(e) {
 var chrTyped, chrCode=0, evt=e?e:event;
 if (evt.charCode!=null)     chrCode = evt.charCode;
 else if (evt.which!=null)   chrCode = evt.which;
 else if (evt.keyCode!=null) chrCode = evt.keyCode;

 if (chrCode==0) chrTyped = 'SPECIAL KEY';
 else chrTyped = String.fromCharCode(chrCode);

 //[test only:] display chrTyped on the status bar 
 self.status='inputDigitsOnly: chrTyped = '+chrTyped;

 //Digits, special keys & backspace [\b] work as usual:
 if (chrTyped.match(/\d|[\b]|SPECIAL/)) return true;
 if (evt.altKey || evt.ctrlKey || chrCode<28) return true;

 //Any other input? Prevent the default response:
 if (evt.preventDefault) evt.preventDefault();
 evt.returnValue=false;
 return false;
}

function addEventHandler(elem,eventType,handler) {
 if (elem.addEventListener) elem.addEventListener (eventType,handler,false);
 else if (elem.attachEvent) elem.attachEvent ('on'+eventType,handler); 
 else return 0;
 return 1;
}

// onload: Call the init() function to add event handlers!
function init() {
 addEventHandler(self.document.f2.elements[0],'keypress',inputDigitsOnly);
 addEventHandler(self.document.f2.elements[1],'keypress',inputDigitsOnly);
}

</script>

Copyright © 1999-2011, JavaScripter.net.