Adding custom keyboard shortcuts to any website
Tags: javascript, tutorial, productivity, tooling
Published: 2022-09-04 00:37:14

Whenever I'm studying English, I always use the google translate website to lookup unknown words. 


![A screenshot of google translate page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ephqzh496cs8s99gka4r.png)

But there is a problem! You see the two buttons marked red? As a hardcore __VIM__ user, I hate to touch my mouse to click those 😩. But luckily Allah gave me the ability to program things.

There is a cool extension out there called [User JavaScript and CSS](https://chrome.google.com/webstore/detail/user-javascript-and-css/nbhcbdghjpllgmfilhnhkllmkecfmpld) that allows us to inject our own __JavaScript__ and __CSS__ code into any website.

![Screenshot of the User JavaScript and CSS extension homepage in chrome webstore](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cz46cd5gvaf4l3ehks0m.png)

At first, we've to select those button elements to click them programmatically. But they all have random classes and ids assigned to them, which are unreliable as selectors. After some searching, I've found that all the buttons have an attribute called `aria-label`.

For the two pronunciation buttons, the value of `aria-label` is `"Listen to source text"` and for the clear button it's `"Clear source text"`.

We can write the following code snippet to select these buttons:

```js
const clearBtn = document.querySelector('[aria-label="Clear source text"]');

const firstSpeakBtn = document.querySelectorAll(
  '[aria-label="Listen to source text"]'
)[1];
```

Now, we can invoke the `clearBtn.click()` and `firstSpeakBtn.click()` methods to clear and pronounce the input text respectively.

Secondly, we need to setup an event listener for the `keydown` events so that we know when to execute clicks on those buttons.

```js
const shortcuts = {};

window.addEventListener("keydown", (e) => {
  // If Control is not pressed or if the Control is pressed alone
  // then return and do nothing.
  if (!e.ctrlKey || e.key === "Control") return;

  const key = e.key;
  if (key in shortcuts) {
    // override browser keyboard shortcuts
    e.preventDefault();
    e.stopPropagation();

    // take some action here
  }
});
```

I want the <kbd>Ctrl-p</kbd> to pronounce and <kbd>Ctrl-l</kbd> to clear the input text.

#### Update:
Added <kbd>Ctrl-k</kbd> and <kbd>Ctrl-j</kbd> for scrolling up and down respectively.


Here is the full code:

```js
// Ctrl-l = clear the input in the first box
// Ctrl-p = pronounce the text in the first box
// Ctrl-j = scroll down
// Ctrl-k = scroll up
const shortcuts = Object.freeze({
  p: () => getSpeakButton().click(),
  l: () => getClearButton().click(),
  j: () => scrollBy({ top: 100, left: 0, behavior: "smooth" }),
  k: () => scrollBy({ top: -100, left: 0, behavior: "smooth" }),
});

window.addEventListener("keydown", (e) => {
  // If Control is not pressed or if the Control is pressed alone
  // then return and do nothing.
  if (!e.ctrlKey || e.key === "Control") return;

  const key = e.key;
  if (key in shortcuts) {
    // override browser keyboard shortcuts
    e.preventDefault();
    e.stopPropagation();

    shortcuts[key]();
  }
});

function getClearButton() {
  const clearBtn = document.querySelector('[aria-label="Clear source text"]');
  return makeBtnSafeToClick(clearBtn);
}

function getSpeakButton() {
  const firstSpeakBtn = document.querySelectorAll(
    '[aria-label="Listen to source text"]'
  )[1];
  return makeBtnSafeToClick(firstSpeakBtn);
}

/*
 * If the button is `nullish`, make sure that invoking the `.click()` method
 * doesn't throw an error.
 * */
function makeBtnSafeToClick(btn) {
  return btn ? btn : { click: () => {} };
}
```
Now, go to the google translate website and click on the __User JavaScript and CSS__ extension and you should see a modal like this:

![A modal dialog with add new button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qs5u14ogqzbuwnysu81k.png)

then click on the __Add new__ button and it'll take you to a page like this:

![Editor Page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spg8fsb5ul4c7f4ulblh.png)

Finally, copy the full code snippet from above and paste it into the __JS__ tab and click __Save__ then reload the page.

At last, we can stay away from that nasty mouse! Life is gud 😋.

#### Credits

The cover image is taken from [Unsplash](https://unsplash.com/photos/vazjaqOpY9g?utm_source=unsplash&utm_medium=referral&utm_content=creditShareLink)