Here’s what we wrote for the event listener so far:
calculatorButtonsDiv.addEventListener('click', event => { // ...
// Release operator pressed state const operatorKeys = [...calculatorButtonsDiv.children].filter( button => button.dataset.buttonType === 'operator', ) operatorKeys.forEach(button => button.classList.remove('is-pressed'))
if (buttonType === 'clear') { // ... }
if (buttonType !== 'clear') { // ... }
if (buttonType === 'number') { // ... }
if (buttonType === 'decimal') { // ... }
if (buttonType === 'operator') { // ... }
if (buttonType === 'equal') { // ... }
calculator.dataset.previousButtonType = buttonType})We can make the event listener code easier to read by breaking each “button” part into a dedicated function.
calculatorButtonsDiv.addEventListener('click', event => { // ... if (buttonType !== 'clear') { /* ...*/ }
if (buttonType === 'clear') handleClearkey() if (buttonType === 'number') handleNumberKeys() if (buttonType === 'decimal') handleDecimalKey() if (buttonType === 'operator') handleOperatorKey() if (buttonType === 'equal') handleEqualKey()
calculator.dataset.previousButtonType = buttonType})Ideally, we want to use early returns if there are many if statements. An early return tells us the rest of the code won’t be executed. It makes code easier to understand.
// Ideal, but doesn't work.calculatorButtonsDiv.addEventListener('click', event => { // ... if (buttonType !== 'clear') { /* ...*/ }
if (buttonType === 'clear') return handleClearkey() if (buttonType === 'number') return handleNumberKeys() if (buttonType === 'decimal') return handleDecimalKey() if (buttonType === 'operator') return handleOperatorKey() if (buttonType === 'equal') return handleEqualKey()
calculator.dataset.previousButtonType = buttonType})We cannot use early returns because we need to assign buttonType as previousButtonType at the end of the event listener.
This is where a switch statement is perfect. With switch, we can get the clarity we want, and still execute the final line of code.
calculatorButtonsDiv.addEventListener('click', event => { // ...
if (buttonType !== 'clear') { /* ...*/ }
switch (buttonType) { case 'clear': handleClearKey() break case 'number': handleNumberKeys() break case 'decimal': handleDecimalKey() break case 'operator': handleOperatorKeys() break case 'equal': handleEqualKey() break }
calculator.dataset.previousButtonType = buttonType})We can make the code terser by combining case, the function we want to call, and break in a single line.
calculatorButtonsDiv.addEventListener('click', event => { // ...
if (buttonType !== 'clear') { /* ...*/ }
switch (buttonType) { case 'clear': handleClearKey() break case 'number': handleNumberKeys() break case 'decimal': handleDecimalKey() break case 'operator': handleOperatorKeys() break case 'equal': handleEqualKey() break }
calculator.dataset.previousButtonType = buttonType})Function to handle clear key
We’ll create this function by copying everything from the if (buttonType === 'clear').
function handleClearKey() { display.textContent = '0' button.textContent = 'AC' if (previousButtonType === 'clear') { delete calculator.dataset.firstValue delete calculator.dataset.operator delete calculator.dataset.modifierValue }}We can see we need calculator and button to run this function. We can pass these two variables into the function.
function handleClearKey(calculator, button) { const { previousButtonType } = calculator.dataset
if (buttonType === 'clear') { display.textContent = '0' button.textContent = 'AC' if (previousButtonType === 'clear') { delete calculator.dataset.firstValue delete calculator.dataset.operator delete calculator.dataset.modifierValue } }}
calculatorButtonsDiv.addEventListener('click', event => { // ... switch (buttonType) { case 'clear': handleClearKey(calculator, button) break } // ...})Function to handle number keys
We can create a function called handleNumberKeys. We’ll copy everything from if (buttonType === 'number') into this function.
function handleNumberKeys() { if (displayValue === '0') { display.textContent = key } else { display.textContent = displayValue + key }
if (previousButtonType === 'operator') { display.textContent = key }
if (previousButtonType === 'equal') { resetCalculator() display.textContent = key }}We need key, previousButtonType and displayValue in this function.
We can get key from dutton.dataset and previousButtonType from calculator. We’ll pass these two variables in.
function handleNumberKeys(calculator, button) { const { previousButtonType } = calculator.dataset const { key } = button.dataset // ...}We can get displayValue from getDisplayValue.
function handleNumberKeys(calculator, button) { const displayValue = getDisplayValue() // ...}We’ll use handleNumberKeys like this:
calculatorButtonsDiv.addEventListener('click', event => { // ... switch (buttonType) { // ... case 'number': handleNumberKeys(calculator, button) break } // ...})Function to handle decimal key
Again, we start by copying everything we wrote from if (buttonType === 'decimal') into a new function. We’ll call this function handleDecimalKey
function handleDecimalKey() { if (!displayValue.includes('.')) { display.textContent = displayValue + '.' }
if (previousButtonType === 'equal') { resetCalculator() display.textContent = '0.' }
if (previousButtonType === 'operator') { display.textContent = '0.' }}We can see handleDecimalKey needs displayValue and previousButtonType.
displayValuecan be found fromgetDisplayValuepreviousButtonTypecan be found incalculator.dataset.
So we need to pass calculator into handleDecimalKey.
function handleDecimalKey(calculator) { const displayValue = getDisplayValue() const { previousButtonType } = calculator.dataset
if (!displayValue.includes('.')) { display.textContent = displayValue + '.' }
if (previousButtonType === 'equal') { resetCalculator() display.textContent = '0.' }
if (previousButtonType === 'operator') { display.textContent = '0.' }}Using handleDecimalKey:
calculatorButtonsDiv.addEventListener('click', event => { // ... switch (buttonType) { // ... case 'decimal': handleDecimalKey(calculator) break } // ...})Function to handle operator keys
Again, we will copy everything we wrote in if (buttonType === 'operator') into a new function. We’ll call it handleOperatorKeys.
function handleOperatorKeys() { button.classList.add('is-pressed')
const firstValue = calculator.dataset.firstValue const operator = calculator.dataset.operator const secondValue = displayValue
if ( previousButtonType !== 'operator' && previousButtonType !== 'equal' && firstValue && operator ) { const result = calculate(firstValue, operator, secondValue) display.textContent = result calculator.dataset.firstValue = result } else { calculator.dataset.firstValue = displayValue }
calculator.dataset.operator = button.dataset.key}We can see we calculator, button, and displayValue in this function.
We will pass calculator and button into the function.
function handleOperatorKeys(calculator, button) { const { previousButtonType, firstvalue, operator } = calculator.dataset
// ...}We will get displayValue from getDisplayValue.
function handleOperatorKeys(calculator, button) { const displayValue = getDisplayValue() // ...}Using handleOperatorKeys:
calculatorButtonsDiv.addEventListener('click', event => { // ... switch (buttonType) { // ... case 'operator': handleOperatorKeys(calculator, button) break } // ...})Function to handle Equal key
Finally, we will create a function to handle the equal key. We will also start by copying everything we wrote from if (buttonType === 'equal') into the new function.
function handleEqualKey() { const firstValue = calculator.dataset.firstValue const operator = calculator.dataset.operator const modifierValue = calculator.dataset.modifierValue const secondValue = modifierValue || displayValue
if (firstValue && operator) { const result = calculate(firstValue, operator, secondValue) display.textContent = result calculator.dataset.firstValue = result calculator.dataset.modifierValue = secondValue } else { display.textContent = parseFloat(displayValue) * 1 }}We can see we need calculator and displayValue in this function. You should know the drill by now :)
function handleEqualKey(calculator) { const displayValue = getDisplayValue() const { firstValue, operator, modifierValue } = calculator.dataset
// ...}Using handleEqualKey
calculatorButtonsDiv.addEventListener('click', event => { // ... switch (buttonType) { // ... case 'equal': handleEqualKey(calculator, button) break } // ...})That’s it!
Welcome! Unfortunately, you don’t have access to this lesson. To get access, please purchase the course or enroll in Magical Dev School.
Unlock this lesson