Keyboard: keydown and keyup

This chapter is dedicated to the study of keyboard, along with its keydown and keyup events, and their usage in JavaScript.

As a rule, a keyboard event is generated by pressing a key: no matter it’s a symbol key or a special key, such as Shift, Ctrl, and more.

Before getting to the keyboard, please consider that there are other ways of inputting on modern devices. For instance, speech recognition or copy/paste using the mouse.

In case you intend to track any input into the <input> field, then keyboard events are not enough. Another event called input is used for tracking changes of an input field by any means.

In general, keyboard events are used when there is an intention of handling keyboard actions (including virtual keyboard). For example, for reacting to arrow keys Up and Down or hotkeys ( key combinations are also counted).

Teststand

If you want to understand the keyboard events better, you can use the following test stand:

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <style>
      #keyInput {
       font-size: 100%;
       box-sizing: border-box;
       width: 90%;
       border: 1px solid green;
      }
      #area {
       width: 90%;
       box-sizing: border-box;
       height: 250px;
       border: 1px solid green;
       display: block;
      }
      form label {
       display: inline;
       white-space: nowrap;
      }
    </style>
  </head>
  <body>
    <form id="form" onsubmit="return false">
      <p>Focus on the input field and press a key.</p>
      <input type="text" placeholder="Press keys here" id="keyInput">
      <textarea id="area"></textarea>
      <input type="button" value="Clear textarea" onclick="area.value = ''" />
      <div>
        Prevent default for:
        <label>
        <input type="checkbox" name="keydownStop" value="1"> keydown</label>&nbsp;&nbsp;&nbsp;
        <label>
        <input type="checkbox" name="keyupStop" value="1"> keyup</label>
        <p>
          Ignore:
          <label>
          <input type="checkbox" name="keydownIgnore" value="1"> keydown</label>&nbsp;&nbsp;&nbsp;
          <label>
          <input type="checkbox" name="keyupIgnore" value="1"> keyup</label>
        </p>
      </div>
    </form>
    <script>
      keyInput.onkeydown = keyInput.onkeyup = keyInput.onkeypress = handle;
      
      let lastTime = Date.now();      
      function handle(e) {
        if (form.elements[e.type + 'Ignore'].checked) return;
      
        let text = e.type +
          ' key=' + e.key +
          ' code=' + e.code +
          (e.shiftKey ? ' shiftKey' : '') +
          (e.ctrlKey ? ' ctrlKey' : '') +
          (e.altKey ? ' altKey' : '') +
          (e.metaKey ? ' metaKey' : '') +
          (e.repeat ? ' (repeat)' : '') +
          "\n";
      
        if (area.value && Date.now() - lastTime > 250) {
          area.value += new Array(81).join('-') + '\n';
        }
        lastTime = Date.now();      
        area.value += text;      
        if (form.elements[e.type + 'Stop'].checked) {
          e.preventDefault();
        }
      }    
    </script>
  </body>
</html>

Keydown and Keyup

The keydown and keyup events occur whenever the user presses a key. The keydown happens at the moment the user presses the key down. It repeats as long as the user keeps it down. The keyup event happens when the user releases the key after the default action has been performed.

Event.code and Event.key

The key property of the event object allows getting the character, while the code property - the “physical key code”.

For instance, the same “S” can be pressed both with the Shift button or without. It will give different characters: lowercase z and uppercase Z.

The event.key is the character itself: hence, it will be different.

In case the user works with different languages, then switching to another language will bring a completely different character instead of “S”. It will be the value of the event.key, while event.code is constantly the same.

An important thing to remember: KeyS and keyS are not the same. The first letter of Key should be uppercase. So, event.code=="keyZ" will cause an error. Let’s consider a case where a key doesn’t give a character. For example, Shift or F1. For these types of keys, event.key is almost the same as event.code. The event.code indicates exactly which key is pressed. For instance, almost all the keyboards have two Shift keys: on the right and the left side. The event.code specifies, which of them is pressed, and event.key tells you what key it is ( in this case, “Shift”).

Imagine handling a hotkey Ctrl+Z (for Mac it will be Cmd+Z). For most text editors, it provides an “Undo” action. It is possible to set a listener on keydown and check the pressed key. But, a dilemma appears here: should you check the event.key or event.code?

On the one hand, event.key is considered a character, it may change depending on the language. In case the user has different languages in OS and switches between them, the same key will give different characters. You, it is better to check event.code, like here:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script>
      document.addEventListener('keydown', function(event) {
        if (event.code == 'KeyZ' && (event.ctrlKey || event.metaKey)) {
          alert('Undo!')
        }
      })      
    </script>
  </body>
</html>

On the other hand, a problem exists with event.code. The same key can have different characters for different keyboard layouts.

Auto-repeat

When any key is being pressed for a long enough time, it gets “auto-repeating”. The keydown event happens again and again, and when it is released, the keyup is got. So, it is typical to have many keydowns and only one keyup.

For events that happen by auto-repeat, the event.repeat property is set to true.

Default Actions

There can be different default actions. It’s because many possible things can be initiated by the keyboard, as described below:

  • A character comes out on the screen.
  • A character is deleted with the Delete key.
  • The scrolling of the page with the PageDown key.
  • Opening of the “Save Page” dialog by Ctrl+S.

If you prevent the default action on keydown, it may cancel most of them, except for the OS-based specific keys. For instance, Alt+F4 closes the current browser window on Windows. And, in JavaScript, no way exists to stop it by preventing the default action.

Let’s check out an example where the <input> expects a phone number, not accepting keys except digits, such as +, - or ():

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script>
      function checkedPhoneKey(key) {
        return (key >= '0' && key <= '9') || key == '+' || key == '(' || key == ')' || key == '-';
      }
    </script>
    <input onkeydown="return checkedPhoneKey(event.key)" placeholder="Phone number" type="tel">
  </body>
</html>

Also, take into account that special keys, like Backspace, Left, Right, Ctrl+V will not work in such an output. That is the side-effect of the checkedPhoneKey strict filter.

Let’s consider another example, where arrows and deletion works pretty well:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script>
      function checkedPhoneKey(key) {
        return (key >= '0' && key <= '9') || key == '+' || key == '(' || key == ')' || key == '-' ||
          key == 'ArrowLeft' || key == 'ArrowRight' || key == 'Delete' || key == 'Backspace';
      }
    </script>
    <input onkeydown="return checkedPhoneKey(event.key)" placeholder="Phone number" type="tel">
  </body>
</html>

However, you can still add anything by applying a mouse and right-click + Paste. Therefore, the filter is not 100% reliable. There is an alternative means: tracking the input event, which triggers after any modification. There, you have the option of checking the new value and highlighting/modifying it whenever it’s not valid.

Legacy

Previously, there was a keypress event, along with keyCode, charCode, which properties of the event object.

Anyway, they caused so many incompatibilities that developers started deprecating all of them and making new, modern events ( described above). Of course, the old code still works but there is no use in them.

Summary

Pressing any key always creates a keyboard event, be it special keys or symbol keys. The exception is the Fn key, which at times is presented on a laptop keyboard. No keyboard event exists for it, as it’s often performed at a lower level than OS.

The keyboard events are keydown and keyup. The first one triggers on pressing the key down, the second one- on releasing the key.

The primary keyboard event properties are the following:

  • code: it is the key code ( for example, "KeyA"), specific to the key location on the keyboard.
  • key: the character ("A", "a") for non-character keys. Normally, its value is equivalent to the value of the code.



Do you find this helpful?

Related articles