Determine if JavaScript e.keyCode is a printable (non-control) character

JavascriptKeycode

Javascript Problem Overview


I'd just like to know the range(s) of JavaScript keyCodes that correspond to typeable characters; or alternatively, the range of non-typeable (control) characters like backspace, escape, command, shift, etc. so I can ignore them.

The reason I ask is calling String.fromCharCode() is resulting in odd characters for control keys. For example I get "[" for left command, "%" for left arrow. Weirdness like that.

Javascript Solutions


Solution 1 - Javascript

Keydown will give you the keyCode of the key pressed, without any modifications.

$("#keypresser").keydown(function(e){
    var keycode = e.keyCode;

    var valid = 
        (keycode > 47 && keycode < 58)   || // number keys
        keycode == 32 || keycode == 13   || // spacebar & return key(s) (if you want to allow carriage returns)
        (keycode > 64 && keycode < 91)   || // letter keys
        (keycode > 95 && keycode < 112)  || // numpad keys
        (keycode > 185 && keycode < 193) || // ;=,-./` (in order)
        (keycode > 218 && keycode < 223);   // [\]' (in order)
    
    return valid;
});

Only the number keys, letter keys, and spacebar will have keycodes correlating to String.fromCharCode as it uses Unicode values.

Keypress will be the charCode representation of the text entered. Note that this event won't fire if no text is "printed" as a result of the keypress.

$("#keypresser").keypress(function(e){
    var charcode = e.charCode;
    var char = String.fromCharCode(charcode);
    console.log(char);
});

http://jsfiddle.net/LZs2D/1/ Will demonstrate how these work.

KeyUp behaves similarly to KeyDown.

Solution 2 - Javascript

Just for background, the "keypress" event will give you a charCode property whenever you press a character key.

Editor.addEventListener('keypress', function(event){
	if (event.charCode) {
		//// character key
		console.log( String.fromCharCode(event.charCode) ); /// convert charCode to intended character.
	} else {
		//// control key
	}

However, the "keypress" event doesn't capture every keystroke - several keys fire before the "keypress" event.

In contrast, the "keydown" event will capture every keystroke, but it doesn't have a charCode property. So how can we tell if it's a character key? Checking on every key stroke whether the keyCode is within the lower and upper bounds for multiple ranges isn't optimally efficient. I suspect that there are also issues for characters outside of the ASCII range.

My approach is the check the length of the event "key" property. The "key" property is an alternative to "keyCode" to determine which key was pressed. For control keys, the "key" property is descriptive (e.g. "rightArrow", "F12", "return", etc.). For character keys, the "key" property for a character key is just the character (e.g "a", "A", "~", "\", etc.). Therefore, for every character key, the length of the "key" property will have length of 1; whereas control characters will have length greater than 1.

Editor.addEventListener('keydown', function(event){
	if (event.key.length == 1){ 
		//// character key
	} else {
		//// control key
	}
})

Solution 3 - Javascript

I noticed that all characters with length of 1 ('A','B',number,symbol) is printable so I use only. I use this solution for non-english characters too:

if(e.key.length==1)
    print();

Solution 4 - Javascript

This article has a list of the keyCodes in Javascript:

http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes

Solution 5 - Javascript

You can also use RegEx for this:

$(".input").keyup(function (event) {
    if (event.key.match(/^[\d\w]$/i)) {
      // put function to trigger when a digit or a word character is pressed here
    }

the i flag makes the expression case insensitive.

Solution 6 - Javascript

As of 2021, an easy way to do this is, through InputEvent's.

This only works for <input>, <select>, and <textarea>, which should be the majority of cases:

function handleInput(event) {
  if (event.inputType === 'insertText' || event.inputType === 'insertCompositionText') {
    console.log('Input Detected', event.data)
  }
}

element.oninput = handleInput
// or
element.addEventListener('input', handleInput)

The insertCompositionText property allows us to detect some precomposed characters.

For tags other than <input>, <select> and <textarea>, we can use keydown event with event.key.length with the fixes mentioned by Tim Perry:

function handleKeydown(event) {
  if([...event.key].length === 1 && !event.ctrlKey && !event.metaKey) {
    console.log('Key Detected', event.key)
  }
}
element.onkeydown = handleKeydown
// or
element.addEventListener('keydown', handleKeydown)

Despite this, I believe both struggle when it comes to recognising some precomposed characters and other quirks.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiondevios1View Question on Stackoverflow
Solution 1 - JavascriptShmiddtyView Answer on Stackoverflow
Solution 2 - JavascriptiamioView Answer on Stackoverflow
Solution 3 - JavascriptTeuView Answer on Stackoverflow
Solution 4 - JavascriptDave ZychView Answer on Stackoverflow
Solution 5 - JavascripttltView Answer on Stackoverflow
Solution 6 - JavascriptnoobView Answer on Stackoverflow