50

The problem:

  • Limit allowed characters in a HTML input to a-z A-Z only.
  • For business requirements this needs to be done on KeyPress so that the character simply isnt allowed to even appear in the input.
  • Tab, enter, arrows, backspace, shift are all allowed. The user must be able to freely move in and out of the textbox, delete characters etc etc.

This is the starting point of my code...

var keyCode = (e.keyCode ? e.keyCode : e.which);

However every value that I get in keyCode doesnt correspond to any of the character charts I have seen on the web. For example the character "h" gives me a return code of 104.

Is KeyCode different to CharCode? Which code contains the control characters? Do I need to convert?

How can I restrict the input to a-z A-Z and allow the keys I need in JavaScript?

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
Remotec
  • 10,304
  • 25
  • 105
  • 147
  • `keyCode` does not exist in all browsers. Be careful with that. – jwueller Nov 26 '10 at 13:25
  • 3
    @elusive: For a `keypress` event, you're correct. For a `keydown` event, `keyCode` exists in all major browsers. – Tim Down Nov 26 '10 at 13:46
  • Refer my previous answer [http://stackoverflow.com/questions/2859587/javascript-keycode-46-is-del-function-key-or-period-sign/28295546#28295546][1] [1]: http://stackoverflow.com/questions/2859587/javascript-keycode-46-is-del-function-key-or-period-sign/28295546#28295546 – muTheTechie Feb 03 '15 at 09:38

8 Answers8

70

The answers to all your questions can be found on the following page.

...but in summary:

  • The only event from which you can reliably obtain character information (as opposed to key code information) is the keypress event.
  • In the keypress event, all browsers except IE <= 8 store the character code in the event's which property. Most but not all of these browsers also store the character code in the charCode property.
  • In the keypress event, IE <= 8 stores the character code in the keyCode property.

This means to get the character code corresponding to the keypress, the following will work everywhere, assuming a keypress event object is stored in a variable called e:

var charCode = (typeof e.which == "number") ? e.which : e.keyCode

This will generally return you a character code where one exists and 0 otherwise. There are a few cases where you'll get a non-zero value when you shouldn't:

  • In Opera < 10.50 for keys Insert, Delete, Home and End
  • In recent versions of Konqueror for non-character keys.

The workaround for the first problem is a little involved and requires using the keydown event as well.

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Thanks for the detailed response. I presume I can take the value of charCode and filter that to allow the keys I want and to disallow the characters I dont want? – Remotec Nov 26 '10 at 14:33
  • 1
    @RemotecUk: Exactly. It's a simple character code. You can do `String.fromCharCode(charCode)` and do string or regex comparisons if you want. – Tim Down Nov 26 '10 at 14:42
  • Think I am getting confused about what I should check. So with the String.fromCharCode(...) that will return a character e.g. "A", "B" etc and I can check if it is in the allowed range and then return false if it is not. Will this allow backspace, arrow keys etc to get through? – Remotec Nov 26 '10 at 15:26
  • 1
    Backspace will actually give a character code of 8. Arrow keys will give you zero where they're actually detected: IE doesn't generate keypresses for arrow keys and other non-printable keys. – Tim Down Nov 26 '10 at 15:41
  • The 'String.fromCharCode(charCode)' part doesn't seem to work for me. On Firefox, the Left Arrow key is charCode 37, and String.fromCharCode(37) == '%'. – Kylotan Nov 08 '14 at 19:53
  • @Kylotan: You're using the wrong event then. Only `keypress` has character information. I guess you're using `keydown` or `keyup`. – Tim Down Nov 08 '14 at 22:10
  • Using KeyboardEvent.key we can get the character in other key events as well – chetan Jul 10 '21 at 21:22
10

Good grief. KeyboardEvent.[key, char, keyCode, charCode, which] are all deprecated or currently have outstanding bugs according to Mozilla's API docs - https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent. Even JQuery passes the buck on this one and lets the user figure it out https://api.jquery.com/keydown/.

nicopolyptic
  • 227
  • 3
  • 5
5

Actually, 104 is the ASCII code for lowercase 'h'. To get the ASCII code of the typed character onkeypress, you can just use e.which || e.keyCode, and you don't need to worry about held down keys because for typed text, keypress is auto-repeated in all browsers (according to the excellent http://unixpapa.com/js/key.html).

So all you really need is:

<input id="textbox">

<script type="text/javascript">
document.getElementById('textbox').onkeypress = function(e){
  var c = e.which || e.keyCode;
  if((c > 31 && c < 65) || (c > 90 && c < 97) || (c > 122 && c !== 127))
    return false;
};
</script>

Try it: http://jsfiddle.net/wcDCJ/1/

(The ASCII codes are from http://en.wikipedia.org/wiki/Ascii)

Han Seoul-Oh
  • 1,237
  • 1
  • 12
  • 20
2

onKeyPress has different codes for upper and lower case letters. You'd probably find that turning on the cap-lock and then typing your letter would give you the code you expect

onKeyUp and onKeyDown have the same character codes for upper and lower-case letters. It'd recommend using onKeyUp because it's the closest to onKeyPress

James Long
  • 4,629
  • 1
  • 20
  • 30
  • Interesting. How can I capture and allow the required keys though? – Remotec Nov 26 '10 at 13:34
  • 5
    *recommend using onKeyUp because it's the closest to onKeyPress* - no, it's not. `onkeydown` is closer to `onkeypress`, because they both fire when a key is pushed, `onkeyup` doesn't fire until the key is lifted and is terrible for text input because a typed character will appear in the input before the event fires, resulting in an unprofessional feel. – Andy E Nov 26 '10 at 13:35
0

Here is example markup:

<form id="formID">
    <input type="text" id="filteredInput">
    <input type="text" id="anotherInput">
</form>

The following logic can be used to trap for keyboard input (in this case, via a jQuery document ready wrapper).

It may read a little goofy, but basically, I check for everything I want to allow for (in your case, the letters A through Z case insensitive) and do nothing. In other words, the default action is allowed, but any input other than alpha is prevented.

Standard keyboard navigation, such as arrow keys, Home, End, Tab, Backspace, Delete and so forth are checked for and allowed.

NOTE: This code was originally written to satisfy user input permitting only alphanumeric values (A - Z, a - z, 0 - 9), and I left those lines intact as comments.

        <script>
            jQuery( document ).ready( function() {

                // keydown is used to filter input
                jQuery( "#formID input" ).keydown( function( e ) {
                    var _key = e.which
                        , _keyCode = e.keyCode
                        , _shifted = e.shiftKey
                        , _altKey = e.altKey
                        , _controlKey = e.ctrlKey
                    ;
                    //console.log( _key + ' ' + _keyCode + ' ' + _shifted + ' ' + _altKey + ' ' + _controlKey );

                    if( this.id === jQuery( '#filteredInput' ).prop( 'id' ) ) {
                        if(
                            // BACK,         TAB
                            ( _key === 8 || _key === 9 )    // normal keyboard nav
                        ){}

                        else if(
                            // END,           HOME,          LEFT,          UP,            RIGHT,         DOWN
                            ( _key === 35 || _key === 36 || _key === 37 || _key === 38 || _key === 39 || _key === 40 )  // normal keyboard nav
                        ){}

                        else if(
                            // DELETE
                            ( _key === 46 ) // normal keyboard nav
                        ){}

                        else if(
                            ( _key >= 65 && _key <= 90 )    // a- z

                            //( _key >= 48 && _key <=  57 && _shifted !== true ) ||   // 0 - 9 (unshifted)
                            //( _key >= 65 && _key <=  90 ) ||                        // a- z
                            //( _key >= 96 && _key <= 105 )                           // number pad 0- 9
                        ){}

                        else {
                            e.preventDefault();
                        }
                    }

                });
            });
        </script>
Mac
  • 1,432
  • 21
  • 27
0

/* You won't get a keyCode on keypress for non-printing keys, why not capture them on keydown instead? */

function passkeycode(e){
    e= e || window.event;
    var xtrakeys={
        k8: 'Backspace', k9: 'Tab', k13: 'Enter', k16: 'Shift', k20: 'Caps Lock',
        k35: 'End', k36: 'Home', k37: 'Ar Left', k38: 'Ar Up', k39: 'Ar Right',
        k40: 'Ar Down', k45: 'Insert', k46: 'Delete'
    },
    kc= e.keyCode;
    if((kc> 64 && kc<91) || xtrakeys['k'+kc]) return true;
    else return false;
}

inputelement.onkeydown=passkeycode;

kc> 64 && kc<91 // a-zA-Z

xtrakeys['k'+integer]) defines special keycodes allowed

kennebec
  • 102,654
  • 32
  • 106
  • 127
-1

I think keyCode returns the ASCII key value, Ascii-104 is h.

http://www.asciitable.com/

Charcode is as noted in another answer an alternative used in some browsers.

Here is a article with a crssbrowser example: http://santrajan.blogspot.com/2007/03/cross-browser-keyboard-handler.html

David Mårtensson
  • 7,550
  • 4
  • 31
  • 47
  • Looks very promising. Will try it later on. – Remotec Nov 26 '10 at 13:36
  • Interesting, A down vote on a 6 year old answer without explanation? I suspect it is due to the fact that this answer is only valid for IE <= 8.0 and as such is obsolete for the most part. – David Mårtensson Feb 08 '16 at 08:04
-1

I think you're taking the wrong approach entirely. How about something like:

<input id="test">

<script type="text/javascript">
var aToZ = function(el){
    if(this.value.match(/[^a-zA-Z]/)){
        this.value = this.value.replace(/[^a-zA-Z]+/, '')
    }
}
document.getElementById("test").onkeyup = aToZ
</script>

Also, don't forget to repeat the check server-side too.