Focus a Field Using JavaScript KeyboardEvents
Tags: javascript, keyboardevent
Published: 2022-11-18 19:13:31

If you don't already know, you can press the forward slash key `/` on Gmail, YouTube, and Google search result pages to focus your cursor back to the search field. I'll show you how you can implement this on your website with JavaScript, and a few things to look out for.

First, you'll need reference to the search field you want to focus, in my case:
```
const searchField = document.querySelector('#search-input');
```
We'll come back to this later.

Second, you'll need to add an `EventListener`. I would suggest adding the `EventListener` to the `window`  `EventTarget` so the keyboard shortcut works anywhere on your webpage:
```
window.addEventListener()
```

Next, you will need to choose a `listener` to listen for your keyboard shortcut. You have a few main choices:
1. `keydown`
2. `keypress`
3. `keyup`

You should avoid using `keypress` because it has been deprecated, [per MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/keypress_event).

As their names suggest, `keydown` fires when the key is pressed and `keyup` fires when the key is released. Note that `keydown` will continue to fire for as long as the key is held down (`keypress` does, too). If you want to avoid the possibility of a bunch of unwanted characters in your focused input area, you may want to use `keyup` instead. Interestingly, Google will let you input as many forward slashes as you want if you hold down the key.

Another behavior to consider is the order the that the `listeners` fire. Because `keydown` fires on, well, key *down*, it fires before `keyup`. That difference may be obvious, but it can cause a noticeable delay if your users hold the shortcut key down for longer than a quick press. That said, the difference will probably be imperceptible to most. In my example, though, I'll use `keyup`:
```
window.addEventListener('keyup', (event) => {
    // code
})
```

`KeyboardEvent` objects have a number of important [properties](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#instance_properties). You can use `.code` or `.key` to specify which key to act on. MDN makes an important note about `.code`: this property ignores keyboard layout; it returns the code for the physical key location. So, if you have users that may be using Dvorak or other non-QWERTY keyboard layouts, you may need to consider how that affects their experience.

To determine which `.code` value corresponds to which character, check out [this MDN doc](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values). A list of `.key` values is provided [at this doc](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).

Combining `.code` and all of the above with an `if` statement gets us a basic implementation:
```
const searchField = document.querySelector('#search-input');
window.addEventListener('keyup', (event) => {
  if(event.code === 'Slash'){
    searchField.focus();
  }
})
```

The `.focus()` method focuses on the query selector we made in the first step.

There are a couple of other things we can add, though—some of which will be a matter of preference or depend on your implementation.

First, if your website has another text input besides your search field, you may want to disable the `/` shortcut (or whatever you set your shortcut key to) when entering text in the other input field. To do that, we first need to know what element the user is currently focused on, which can accomplished with the `.activeElement` property on the document.

We also need to know the name of the tag of the active element, which we can find with the aptly named `.tagName` property. Note that `.tagName` will return the element's tag name in all caps (e.g., an `<input>` tag will be returned as `INPUT`). Combined with `.activeElement`, the code looks like this:
```
document.activeElement.tagName
```

Combined with our existing `if` statement, your code should look like this:
```
const searchField = document.querySelector('#search-input');
window.addEventListener('keyup', (e) => {
  if((e.code === 'Slash') && (document.activeElement.tagName !== 'INPUT')){
    searchField.focus();
  }
})
```

If you're checking if your user is already in a text input field, you'll probably also want to check if the user is in a `textarea` field. You can accomplish this in the same way as above:
```
document.activeElement.tagName !== 'TEXTAREA'
```

In total, the final product looks like this:
```
const searchField = document.querySelector('#search-input');
window.addEventListener('keyup', (e) => {
  if((e.code === 'Slash') && (document.activeElement.tagName !== 'INPUT') && (document.activeElement.tagName !== 'TEXTAREA')){
    searchField.focus();
  }
})
```

Bonus: You may also want to check if your user is in an element that has the `contenteditable` HTML attribute enabled. The process to check is a little different, but also more straightforward with the `.isContentEditable` property. The property returns `true` if the contents are editable and `false` if not. `contenteditable` is of course less common than text inputs and text areas, but it's worth noting.