But not with symbols like plus, minus, times, and divide.
Listening to symbols
The error occurred because querySelector is not able to find a button with the special key. event.key does not provide the same value as what we wrote in data-key.
This means we need to change event.key to match the data-key attribute.
calculator.addEventListener('keydown', event => {
let key = event.key
// Operator keys
if (key === '+') key = 'plus'
if (key === '-') key = 'minus'
if (key === '*') key = 'times'
if (key === '/') key = 'divide'
const button = calculator.querySelector(`[data-key="${key}"]`)
button.click()
})
If you’re on a keyboard without a number pad, you have to press shift + 8 to get *. And you’ll produce an error in the process (because no button matches data-key="shift").
We don’t want to do anything if a button is not found, so we use an early return statement to end the function.
calculator.addEventListener('keydown', event => {
let key = event.key
if (key === '+') key = 'plus'
if (key === '-') key = 'minus'
if (key === '*') key = 'times'
if (key === '/') key = 'divide'
const button = calculator.querySelector(`[data-key="${key}"]`)
if (!button) return
button.click()
})
You can press +, -, *, and / keys now.
Special keys
We still need to allow users to press these keys with their keyboard:
The decimal key
The clear key
The equal key
It makes sense to use these keys:
.: For decimal key
Backspace: For clear key
Escape: For clear key
Enter: For equal key
=: For equal key
calculator.addEventListener('keydown', event => {
let key = event.key
// Operator keys
if (key === '+') key = 'plus'
if (key === '-') key = 'minus'
if (key === '*') key = 'times'
if (key === '/') key = 'divide'
// Special keys
if (key === '.') key = 'decimal'
if (key === 'Backspace') key = 'clear'
if (key === 'Escape') key = 'clear'
if (key === 'Enter') key = 'equal'
if (key === '=') key = 'equal'
const button = calculator.querySelector(`[data-key="${key}"]`)
if (!button) return
button.click()
})
Note: Enter triggers a button click. We need to disable this default behaviour. If you don’t, enter will make two calculations, and your results will be incorrect.
calculator.addEventListener('keydown', event => {
let key = event.key
// Operator keys
if (key === '+') key = 'plus'
if (key === '-') key = 'minus'
if (key === '*') key = 'times'
if (key === '/') key = 'divide'
// Special keys
if (key === '.') key = 'decimal'
if (key === 'Backspace') key = 'clear'
if (key === 'Escape') key = 'clear'
if (key === 'Enter') key = 'equal'
if (key === '=') key = 'equal'
const button = calculator.querySelector(`[data-key="${key}"]`)
if (!button) return
event.preventDefault()
button.click()
})
You can now perform any calculation you want. It’ll work.
But it’s confusing to see focus remaining on the plus key all the time. It makes the user believe they pressed the plus key, even though that’s not the case!
Managing focus
We want to let highlight the key the user pressed. This should have already happened. It doesn’t because of the way browsers apply focus when users click buttons.
We can correct the focus with this code. Make sure you put this at the top of your JavaScript file.
document.addEventListener('click', event => {
if (event.target.matches('button')) {
event.target.focus()
}
})
Activating the calculator
If you’re using the calculator, would you think about using number keys when the plus button gets highlighted?
Probably not.
We can show users they’ve activated the calculator by highlighting the entire calculation. To do this, we need to set the calculator’s tabindex to 0.
<div class="calculator" tabindex="0"> ... </div>
We also need to create some styles:
/* Get these styles from the starter file */
.calculator:focus,
.calculator:focus-within {
/* ... */
}
Even if the calculator gets activated, users may still not know they can use the calculator with their keyboard. We should provide them with some clues.
You already learned how to do this with the carousel, so I’m not going to do this. I’ll leave you to figure it out :)
Allow users to tab through the calculator
One final thing. It takes MANY tabs to go through the calculator. We want to allow users to tab through it if the calculator is not their main focus.
We can do this by setting tabindex for all buttons in the calculator to -1.