keytrack

In JavaScript, you can’t ask whether a key is currently held down. You only get keydown and keyup events as they happen, so if you want to know the current state, you have to keep track of it yourself. For most websites, this is fine. However, if you want to play games within the browser, or write anything that checks the keyboard in a loop, such as… games :), you might need this.

Why I wrote it

While working on WebTigerPython (a browser-based successor to TigerJython), I needed to port the functions isKeyCodePressed and isKeyPressed, which both query whether a key is currently pressed. So I looked for an existing JavaScript library that fit my needs. I found a few, but they did not fit my use case.

  • hotkeys-js: has isPressed, but is a bigger hotkey library, and I did not want to add a whole library with features I did not need
  • keymaster: has isPressed, but is unmaintained since 2014

So I decided to make a small npm package for that reason. Publishing an npm package was something I wanted to try out anyway, and the timing was right for this small adventure.

What it does

It gives you the ability to actively query for pressed keys and key codes. You turn tracking on, and then you can query for the keys, e.g. in a game loop:

import { logKeys, isKeyPressed } from "keytrack";

logKeys(true);

function loop() {
  if (isKeyPressed("ArrowLeft")) player.x -= 1;
  requestAnimationFrame(loop);
}
loop();

You can try it out in the demo on my project page.

Design decisions

In the event API there are the fields key, code and keyCode. key is the resulting character that appears, e.g. if you hold Shift and A, it’s "A". code is a code that every key has, e.g. "KeyA", and keyCode is a number, and it is deprecated.

Internally, keytrack stores the pressed keys by their code, and you can query them by key with isKeyPressed or by keyCode with isKeyCodePressed. The keyCode is provided by a mapping table. The keyCode technically varies for every keyboard layout; I used the US one.

This keyCode was mainly for myself. WebTigerPython has to stay compatible with TigerJython’s isKeyCodePressed, and the existing programs check for numeric key codes. So even though keyCode has been deprecated for a long time, I needed it.

Limitations

One of the reasons why keyCode is deprecated is that it is ambiguous. Left and right modifier keys, such as the two Shift keys, produce the same key code, and the numbers depend on the keyboard layout. Therefore, it does not really make sense for new code; here key might be the better choice.

Another thing I want to add is that it only works while the browser window is focused. Browsers only send key events to the focused page, so that a website can’t log keys typed into other windows, e.g. passwords. This can also lead to stuck keys. If you hold a key and release it in another window, the page never gets the keyup event, so keytrack thinks the key is still pressed.

What’s next

Since the scope of the library is rather limited, it won’t be extended much. I still want to fix the stuck keys from above, by clearing the pressed keys when the window loses focus. Other than that, if you want to extend the library, feel free to create a pull request.




Enjoy Reading This Article?

Here are some more articles you might like to read next: