Course: JavaScript

Progress (0%)

JavaScript Keyboard Events

Chapter 64 13 mins

Learning outcomes:

  1. The keydown event
  2. The keypress event
  3. The keyup event
  4. The KeyboardEvent object

Key going down

The first event that we shall discuss is in this chapter is keydown.

The keydown event fires when a key is pressed down on the keyboard.

Hence the name 'keydown'.

Note that the keydown event fires for any key on the keyboard - not just a bunch of them unlike the keypress event, as we shall see below.

It's common to handle key events on HTML <input> elements because they are the places where users can enter data. Likewise below we illustrate keydown with the help of an input element.

<input type="text">
var input = document.getElementsByTagName("input")[0];

input.onkeydown = function(e) {
    console.log(e.key); // log the name of the key pressed
}

Live Example

What's happening over here is pretty simple. The keydown event is being handled on the <input> element using the onkeydown handler.

As soon as a key is pressed down into the input element, its name is displayed to the user, using the key property of the event object. The key property holds the name of the key pressed.

We'll learn more about the event object of key events later in this chapter.

A common use of the keydown event is to see what is the data of the input element after the current key's value is added to it. This can be done very easily using the value property of the input element.

If you noticed, there is one problem in this code...

Let's say you press the key 's' on your keyboard while the input element is empty. The value logged to us turns out to be "", not "s", which is what we would expect.

This is due to the internal implementation of browsers of the keydown event, discussed as follows:

Internal implementation of keydown

Normally, when we press a key while the cursor is inside an input element, its corresponding operation is performed on the element. For example, when we type an alphabet key, its character shows up in the input element. Similarly, when we type Backspace or Del, a character is removed from the element, and so on and so forth.

This is the native handler executed by the browser's engine in the background whenever a key is pressed down on the keyboard. The handler computes which key is pressed and then performs an action depending on the key.

Now, the keydown event is also dispatched by the browser engine. And this happens before the native handler described above gets executed.

This simply means that when the keydown event fires, the native handler of the browser has not yet been executed, and likewise the corresponding action of the pressed key is not performed in the given input element.

Once the keydown handler exits only then does this default keydown behavior takes place.

Coming back to our point, when the keydown event fires on an input element, retrieving the value of the input at this stage is useless, since it might be one character short or long.

So how to solve this issue?

Well there a couple of ways:

  1. Construct a keydown handler that recognises the key pressed, performs its respective operation on the current input value and ends with the final processed value. As you would agree, this is both complicated and inefficient for such a simple task.
  2. Use setTimeout() to call a function once both the keydown event and the browser's native handler complete. Inside this function, inspect the input's value.
  3. If you don't necessarily want to act when the user presses the key down, go with keyup instead. When keyup fires, the default keydown action of the browser has been executed, and so one can inspect the input's value without worrying it will be one character short or long.

The second option is the most feasible if keydown is really desired. The following snippet demonstrates it:

var input = document.getElementsByTagName("input")[0];

input.onkeydown = function(e) { var _this = this;
// log input's value once keydown completes setTimeout(function() { console.log(_this.value); }, 0); }

In the live example below, instead of logging the value, we output it inside an HTML element.

Live Example

The preventDefault() method

Recall the preventDefault() method of the event object that we saw in the previous chapters. It can prove to be extremely useful when it comes to the keydown event.

As we've stated before, the browser engine fires the keydown event before performing its own native action. Calling the preventDefault() method within keydown's handler can prevent this default action from being executed.

As a result we can get some keys to act differently, for example, make the Backspace delete two characters rather than one, or make the left and right arrow keys change the value of the input rather than move the cursor to the left or right, and so on.

Below shown is an example:

var input = document.getElementsByTagName("input")[0];

input.onkeydown = function(e) {
    if (e.keyCode === 8) {
        alert("Backspace pressed");
        e.preventDefault();
    }
}

Here we check whether the key dispatching the keydown event is the Backspace key using its key code and if it is, then make an alert and prevent the default action of the Backspace key that is to remove the last character from the input's value.

It doesn't matter whether we call preventDefault() after the alert() statement or before it. What matters is that we do call it at some point.

In the live example below you can compare two inputs - one operating normally on the Backspace key whereas the other one preventing its default action using the handler shown above.

Live Example

Moving on, one extremely important thing to note is that calling preventDefault() directly in the handler of keydown could prevent the default action of every single key and thus make the input element not able to accept any input.

So always be double careful when using preventDefault(). Make sure you're not blocking something due to which the user may be deprived of a useful feature.

Key press

The keypress event is similar to keydown in that it also fires when a given key is pressed down and continues firing until the key is released.

However, one major difference between the two is that keypress only fires for a given set of keys.

The keypress event operates exactly like keydown except for that if doesn't fire for command keys.

By command keys, we mean keys such as Tab, Shift, Enter, F1 and so on and so forth.

The keydown event fires only for alphanumeric keys. In contrast, keydown, as we saw above, fires for all keys on the keyboard.

Consider the example below:

var input = document.getElementsByTagName("input")[0];

input.onkeypress = function(e) {
    console.log(e.key);
}

When you press a non-command key like a, 0 or /, its name is logged in the console. However when you press something like Backspace nothing is seen, since keypress doesn't fire for these command giving keys.

Live Example

The preventDefault() method

The keydown event as we know by now is fired by the browser engine before its own default procedure. Keypress follows the same order - it's also fired before the browser's default response to the action of a key going down.

Here's the complete line-up:

First keydown is fired, followed by keypress, and finally the default behavior takes place.

This means that preventDefault(), if called within the handler of keypress, will prevent the alphanumeric keys from registering characters in a given input element.

Command keys would still work as normal.

This can be seen in the example below:

var input = document.getElementsByTagName("input")[0];

input.onkeypress = function(e) {
    e.preventDefault();
    console.log(e.key);
}

Once again in the link below, instead of logging e.key, we display it inside an HTML element.

Live Example

Key going up

The third and the last keyboard event is keyup.

As the name suggests:

The keyup event fires when a given key on the keyboard is released.

The name 'keyup' comes from the fact that at this stage the key has gone upwards.

Anyways, below we illustrate the keyup event using our same old input element:

var input = document.getElementsByTagName("input")[0];

input.onkeyup = function(e) {
    console.log(e.key);
}

Live Example

A very easy way to distinguish between the keydown and keyup events is to hold a key pressed down and then release it after a while. The moment the key is released is exactly when keyup fires.

The keyup event takes place once the browser is done by executing its default handler for the key going down. This means that calling preventDefault() inside keyup won't have any significant effect.

This also means that if we inspect an input element's value from within the handler of keyup, it won't be one character short or long ever.

And this is the reason why many developers use keyup to listen for key presses in an input element - inside its handler one can easily retrieve input.value and be rest assured that it will be the latest value.

Key events on window

It's not always the case to handle keyboard events inside an input element. Sometimes the window object is what gets the job done. But exactly when?

Let's say you have an application that can edit text documents online. While working in it you can save the changes using the key sequence Ctrl + s, the very common sequence used throughout applications to save files.

Now it would be useless to create an input element where the user should go and then press these two keys in order to save the file.

This sounds pretty senseless, doesn't it?

Ideally while working with your application the user shall be able to save the file by pressing Ctrl + s no matter which element is he or she interacting with.

In another instance, suppose you have a feature on your website whereby a user can click on an image to see its enlarged version and then press Esc to go back.

Once again, letting this happen only if an input element is in focus is bogus!

In both these cases, the target of the key events shouldn't be an input element. Rather it should be the global window object.

When a key is pressed while a given webpage is in focus, its window object receives the corresponding key event. Interacting with a particular element isn't necessary — the event fires in every way on the window object.

The following example illustrates this idea:

window.onkeyup = function() {
    alert("Key event on WINDOW");
}

In the link below, try pressing any key on your keyboard once the page loads completely — you'll see an alert.

Live Example

Not surprisingly, handling key events on window is very common.

This idea is used extensively in games to move characters, quit gameplay; in online editors to provide shortcuts to given editing tools; and to some extent in day-to-day websites to power features such as closing a panel on the press of the Esc key.

One important thing to note is that since key events fire on window regardless of which element is currently in focus, pressing a key while inside an input element fires two events: one for the input element itself and the other for the window object.

This can be seen as follows:

<input type="text" placeholder="Type something">
window.onkeyup = function() {
    alert("Key event on WINDOW");
}

var input = document.getElementsByTagName("input")[0];
input.onkeyup = function(e) {
    alert("Key event on INPUT");
}
If a key is pressed inside the input element, the key event would first fire for the input element and then for window.

Live Example

The KeyboardEvent Object

We can add way more functionality to our keyboard events by employing the KeyboardEvent object in the event handlers. We can use a number of properties and methods to carry out various useful tasks. Let's take a look at some of them.

key property

To check for which key is pressed on the occurence of the above events, we can use the key property. It contains the name of the key pressed like ArrowDown for the down arrow key. Consider the following:

ele.onkeyup = function(e) {
    console.log(e.key);
    // ArrowDown for down arrow key
    // Shift for shift key
}

Pressing a would give "a", a with Shift would give "A", 1 would give "1", 1 with Shift would give "!" and so on. Try pressing different keys and see what you get logged in the console.

We can use this way of noting the key pressed, to perform different actions for different keys under one single handler like the example below. We have only one function for onkeyup event but different actions for different keys.

ele.onkeyup = function(e) {
    if (e.key === "ArrowDown") {
        // some code to execute on arrow down
    }
    else if (e.key === "ArrowUp") {
        // code to execute on arrow up
    }
}
If you want to match a specific key in your events and don't know its name what you can do is a simple trick which you have actually just seen above! Simply log the key using the key property (as we did in the first example in this section) and see its name! That's it - now you know its name.
Remember one thing when matching key names that they are CASE-SENSITIVE.

ctrlKey, shiftKey, altKey and metaKey

In addition to checking which key is pressed we can also check if the ctrl key, shift key, alt key, or meta key are held on as the other keys are pressed. For example when you save a document using Ctrl + S you have pressed S with the Ctrl key held down.

In JavaScript we can use the ctrlKey, shiftKey, altKey and metaKey properties to check for whether the given keys are held on or not while the other keys are clicked. Each of these is a boolean holding true if the respective key is kept pressed.

ele.onkeyup = function(e) {
    console.log(e.ctrlKey); // will return true if any key is pressed with ctrl
}
When you press the ctrl key itself ONLY, or any other keys of the above, ctrlKey will be true because the ctrl key is actually pressed!
With the help of these properties we can give our JS programs, keyboard shortcuts, for example Shift + N for performing given tasks.

"I created Codeguage to save you from falling into the same learning conundrums that I fell into."

— Bilal Adnan, Founder of Codeguage