21

I need to detect whether the key which has just been pressed is a printable key, like a character, possibly accented, a number, a space, a punctuation symbol and so on, or a non printable key, like ENTER, TAB or DELETE.

Is there a reliable way to do this in Javascript, other than listing all non printable keys and hope not to forget some?

Andrea
  • 20,253
  • 23
  • 114
  • 183

4 Answers4

36

Luckily, this task is much easier in modern browsers. You can now use KeyboardEvent.key to detect a printable key via its length.

test.onkeydown = e => {
  let isPrintableKey = e.key.length === 1;
  alert(`Key '${e.key}' is printable: ${isPrintableKey}`);
}
<input id="test">

Besides that, you can also detect any other keys from the list, like Enter, Delete, Backspace, Tab, etc.

This method is much more reliable simply because unlike event.which, event.key is already standardized.

Lewis
  • 14,132
  • 12
  • 66
  • 87
  • 4
    It should be noted that this will crash ungracefully in older browsers, because `e.key` is undefined. It's safer to check `e.key && e.key.length === 1`. Even anno 2018, global support for `key` is only ~80%: https://caniuse.com/#feat=keyboardevent-key – Thomas Feb 07 '18 at 08:57
  • 4
    Unfortunately it isn't that reliable. In IE11 for example you will get "Divide", "Multiply", "Subtract", "Add", "Decimal" if you press the math operator key or comma on the numpad. – BooFar Jun 24 '18 at 17:59
  • Be careful if you're using this with `e.preventDefault()` because you'll also block keyboard shortcuts (CMD+R, for example). – claviska Aug 29 '20 at 15:12
  • 2
    Is is actually defined that events for printable keys will always have a “key-length” of 1? I could imagine that some keys in some languages will result in more then one character. – JojOatXGME Feb 04 '21 at 16:39
18

I answered a similar question yesterday. Note that you have to use the keypress event for anything character-related; keydown won't do.

I would argue that Enter is printable, by the way, and this function considers it to be. If you disagree, you can amend it to filter out keypresses with the which or keyCode property of the event set to 13.

function isCharacterKeyPress(evt) {
    if (typeof evt.which == "undefined") {
        // This is IE, which only fires keypress events for printable keys
        return true;
    } else if (typeof evt.which == "number" && evt.which > 0) {
        // In other browsers except old versions of WebKit, evt.which is
        // only greater than zero if the keypress is a printable key.
        // We need to filter out backspace and ctrl/alt/meta key combinations
        return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8;
    }
    return false;
}

var input = document.getElementById("your_input_id");
input.onkeypress = function(evt) {
    evt = evt || window.event;

    if (isCharacterKeyPress(evt)) {
        // Do your stuff here
        alert("Character!");
    }
});
Community
  • 1
  • 1
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • MDN suggests that we should not use the `window.event` property because it is non standard and there may be incompatibilities, [link](https://developer.mozilla.org/en-US/docs/Web/API/Window/event) . Any opinions on that ? – Segmentation Nov 28 '16 at 23:27
  • 1
    @Segmentation: I absolutely agree. I'd only ever use it for compatibility with IE <= 8, which was more of a concern in 2010 than it is now. `window.event` will only be used in old IE in this answer anyway because the event object will be passed into the event handler in all modern browsers. – Tim Down Nov 29 '16 at 11:35
  • 2
    The `keypress` event is deprecated: https://developer.mozilla.org/en-US/docs/Web/API/Document/keypress_event – Trevor Sep 18 '19 at 02:49
  • The `which` event is deprecated too: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/which – Ferares Aug 12 '21 at 13:52
2

If you need to identify printable key just for change detection as user change the input, you could use oninput event.

Downhillski
  • 2,555
  • 2
  • 27
  • 39
2
let isPrintableKey = event.key.length === 1 || event.key === 'Unidentified';

If you do not include: || event.key === 'Unidentified' your code will not work on mobile browsers.

Lee Smith
  • 6,339
  • 6
  • 27
  • 34