92

How to capture key press, e.g., Ctrl+Z, without placing an input element on the page in JavaScript? Seems that in IE, keypress and keyup events can only be bound to input elements (input boxes, textareas, etc)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
powerboy
  • 10,523
  • 20
  • 63
  • 93
  • 5
    @Tim: Because it would be unconventional to perform actions when those keycombos are pressed when a GUI element is not in focus, thus violating the Principle Of Least Surprise. – Lightness Races in Orbit Jul 24 '11 at 18:15
  • 5
    @Tomalak: There are other elements for which one might reasonably want to handle key events, such as ``, although I would agree that any such element should be forced to have the focus before emitting key events. Using a `tabindex` attribute will enable an element to receive focus if it is otherwise unable to. – Tim Down Jul 24 '11 at 21:32
  • 2
    I would recommend the Keypress javascript library: https://dmauro.github.io/Keypress/ – xinthose Mar 31 '17 at 15:55
  • 1
    Another reason to capture keyboard input is if your only displaying barcode on the screen and using a barcode scanner as your keyboard input. Which I am doing. – Robert Jul 31 '18 at 19:35
  • 1
    Most applications have keyboard shortcuts without an input focus. Common sense. Take CTRL-Z to mean UNDO for example. – Epirocks Nov 19 '18 at 15:06

6 Answers6

76

For non-printable keys such as arrow keys and shortcut keys such as Ctrl-z, Ctrl-x, Ctrl-c that may trigger some action in the browser (for instance, inside editable documents or elements), you may not get a keypress event in all browsers. For this reason you have to use keydown instead, if you're interested in suppressing the browser's default action. If not, keyup will do just as well.

Attaching a keydown event to document works in all the major browsers:

document.onkeydown = function(evt) {
    evt = evt || window.event;
    if (evt.ctrlKey && evt.keyCode == 90) {
        alert("Ctrl-Z");
    }
};

For a complete reference, I strongly recommend Jan Wolter's article on JavaScript key handling.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
42

jQuery also has an excellent implementation that's incredibly easy to use. Here's how you could implement this functionality across browsers:

$(document).keypress(function(e){
    var checkWebkitandIE=(e.which==26 ? 1 : 0);
    var checkMoz=(e.which==122 && e.ctrlKey ? 1 : 0);

    if (checkWebkitandIE || checkMoz) $("body").append("<p>ctrl+z detected!</p>");
});

Tested in IE7,Firefox 3.6.3 & Chrome 4.1.249.1064

Another way of doing this is to use the keydown event and track the event.keyCode. However, since jQuery normalizes keyCode and charCode using event.which, their spec recommends using event.which in a variety of situations:

$(document).keydown(function(e){
if (e.keyCode==90 && e.ctrlKey)
    $("body").append("<p>ctrl+z detected!</p>");
});
Trafalmadorian
  • 2,498
  • 2
  • 21
  • 13
  • 1
    didn't know e.which can capture keystroke as well as mouse click! And could you tell me how to get the keycode 26? – powerboy May 21 '10 at 01:51
  • 2
    keycode 26 is a specific id for "which" set by a keypress event (indicates CTRL+z). To see more character mappings for the keypress event, take a look at [the jQuery docs](http://api.jquery.com/keypress/) or [unixpapa's key event tester](http://unixpapa.com/js/testkey.html) – Trafalmadorian May 21 '10 at 02:05
  • Thx. I know what is the meaning of keycode. I mean, 17 is for Ctrl, 90 is for Z, then how did you get the number 26? I just googled but could not find the answer. – powerboy May 21 '10 at 03:18
  • Use those links I put in my comment to test out the codes for different keystrokes. – Trafalmadorian May 21 '10 at 03:40
  • You won't get 26 in all browsers. In fact, you only get 26 in WebKit. Not in IE, Firefox or IE. – Tim Down May 21 '10 at 08:42
  • @Tim Down, you can easily check for multiple key and modifier combinations across browsers. I'll edit my answer to reflect this. However, event.which definitely does apply 26 to ctrl+z combinations in IE, at least up to IE7. I'd a appreciate a vote back up if this is helpful for you. – Trafalmadorian May 21 '10 at 16:18
  • I'll undo the downvote, but I don't think this is the right approach: using the `keydown` event and checking its `keyCode` property will give you much more uniform results across browsers. – Tim Down May 21 '10 at 16:50
  • Fair enough, I'll go ahead and include that route as well in my answer. Thanks for the constructive crit :) – Trafalmadorian May 21 '10 at 17:03
  • @FlorianB Most developers just put together a bunch of libraries and call it theirs. I don't –  Dec 27 '20 at 16:48
32

For modern JS, use event.key!

document.addEventListener("keypress", function onPress(event) {
    if (event.key === "z" && event.ctrlKey) {
        // Do something awesome
    }
});

NOTE: The old properties (.keyCode and .which) are Deprecated.

Mozilla Docs

Supported Browsers

Gibolt
  • 42,564
  • 15
  • 187
  • 127
  • 4
    Might be worth to add *why* one should change all old code now, what advantage the "modern JS" method has, *especially* when the "old"/traditional/standard method has broader browser support. – Luc Feb 10 '21 at 15:28
18

Detect key press, including key combinations:

window.addEventListener('keydown', function (e) {
  if (e.ctrlKey && e.keyCode == 90) {
    // Ctrl + z pressed
  }
});

Benefit here is that you are not overwriting any global properties, but instead merely introducing a side effect. Not good, but definitely a whole lot less nefarious than other suggestions on here.

Sal Rahman
  • 4,607
  • 2
  • 30
  • 43
8

Code & detects ctrl+z

document.onkeyup = function(e) {
  if(e.ctrlKey && e.keyCode == 90) {
    // ctrl+z pressed
  }
}
Ben Rowe
  • 28,406
  • 6
  • 55
  • 75
1

Attach a listener to the keydown event instead of keypress, since the latter is now deprecated.

window.addEventListener('keydown', keyDownHandler);

The keydown event triggers continuously while the key is pressed. If you wanna have it fire only once, inside the handler use the event.repeat property as so:

keyDownHandler(event) {
     if (!event.repeat) {
         <code here will only be executed once while the key is pressed>
     }
}

Remember to remove the listener when not needed anymore.

window.removeEventListener('keydown', keyDownHandler);
iusting
  • 7,850
  • 2
  • 22
  • 30