A good[ish] website
Web development blog, loads of UI and JavaScript topics
Here’s how to listen to more complex keyboard input with JavaScript.
Usually, it’s better to listen keyup, because with keydown it’s easy to unleash a deluge of events possibly bogging up your site.
const handleKeyboard = event => {
if (event.key === '/') console.log('The ’/’ key was pressed')
}
document.addEventListener('keyup', handleKeyboard)This is roughly what the event contains when an alt key was pressed:
{
altKey: false,
ctrlKey: false,
metaKey: false,
shiftKey: false,
charCode: 0,
code: "AltLeft",
isComposing: false,
key: "Alt",
keyCode: 18,
location: 1,
repeat: false,
type: "keyup",
which: 18,
// Unrelated properties redacted for brevity.
}Here’s a quick rundown what each of them do:
KeyboardEvent.altKeyKeyboardEvent.ctrlKeyKeyboardEvent.metaKeyKeyboardEvent.shiftKeyKeyboardEvent.charCode 👎KeyboardEvent.codeAltLeft or AltRightKeyboardEvent.isComposingcompositionstart and compositionend. Composition session is when a character is required to be entered using multiple keystrokes, like Chinese characters or accented characters like "à": alt+` followed by an a.KeyboardEvent.keyKeyboardEvent.keyCode 👎KeyboardEvent.locationKeyboardEvent.repeatkeydown event.KeyboardEvent.shiftKeyKeyboardEvent.typeI’m using Cmd+/ (or Ctrl+/) as an example here (which opens the search on this site btw). When doing key-combos it’s good to listen to the keydown event:
const handleKeyboard = ({ repeat, metaKey, key }) => {
if (repeat) return
if ((metaKey || ctrlKey) && key === '/') console.log('’Cmd+/’ was pressed')
}
document.addEventListener('keydown', handleKeyboard)See the bail on the repeat, without that, there would be a torrential flood of events firing when the key is kept in a pressed state, which might bog up your app.
This little demo toggles a search bar on the header with Cmd+/ or Ctrl+/:
const [searchOpen, setSearchOpen] = React.useState(false)
const handleKeyboard = ({ repeat, metaKey, ctrlKey, key }) => {
if (repeat) return
// Handle both, `ctrl` and `meta`.
if ((metaKey || ctrlKey) && key === '/') setSearchOpen(prev => !prev)
}
React.useEffect(() => {
document.addEventListener('keydown', handleKeyboard)
// Important to remove the listeners.
return () => document.removeEventListener('keydown', handleKeyboard)
})Notes on the above code:
metaKey and ctrlKey so it works on Windows and Mac.componentWillUnmount method.See a Demo ZEOdZGz
If you want to, say, open the search when s and e are pressed, you need to be a bit more clever. You can keep a log of the keys pressed on keydown and then clear the log on keyup:
const keyLog = {}
const handleKeyboard = ({ type, key, repeat, metaKey }) => {
if (repeat) return
if (type === 'keydown') {
keyLog[key] = true
// When "s" and "e" are pressed.
if (keyLog.s && key === 'e') setSearchOpen(prev => !prev)
}
// Remove the key from the log on keyup.
if (type === 'keyup') delete keyLog[key]
}
React.useEffect(() => {
const events = ['keydown', 'keyup']
events.forEach(name => document.addEventListener(name, handleKeyboard))
return () =>
events.forEach(name => document.removeEventListener(name, handleKeyboard))
})Here’s a demo for that one:
See a Demo zYBVQBp
Comments would go here, but the commenting system isn’t ready yet, sorry.