I'm doing a calculator project. When I click on a number the same number is displayed more than once (only one click on each number). for example, I click on 4, it displays the number 4 once because it was the first click, then I click on the number 1 then it displays the number 1 twice because it was the second number to be clicked.
The code: https://github.com/pittyh6/calculator
function calc() {
const calculator = document.querySelector(".calculator");
// All buttons is inside .calculator__keys.
const keys = document.querySelector(".calculator__keys");
const display = document.querySelector(".calculator__display");
// use an event delegation pattern to listen, since keys are all children of .calculator__keys.
keys.addEventListener("click", (e) => {
if (e.target.matches("button")) {
// use the data-action attribute to determine the type of key that is clicked.
const key = e.target;
const action = key.dataset.action;
// The number of the key that was clicked
const keyContent = key.textContent;
// The current displayed number
const displayedNum = display.textContent;
if (!action) {
console.log("number key!");
if (displayedNum === "0") {
display.textContent = keyContent;
console.log("key content " + keyContent);
} else {
display.textContent = displayedNum + keyContent;
console.log("key content " + keyContent);
}
} else if (
action === "add" ||
action === "subtract" ||
action === "multiply" ||
action === "divide"
) {
console.log("operator key");
// add the is-depressed class to the operator key
key.classList.add("is-depressed");
} else if (action === "decimal") {
console.log("decimal key");
display.textContent = displayedNum + ".";
} else if (action === "clear") {
console.log("clear key");
} else if (action === "calculate") {
console.log("equal key");
}
}
});
}
<body>
<div class="container">
<div class="calculator">
<div class="calculator__display">0</div>
<div class="calculator__keys" onclick="calc()">
<button class="key--operator" data-action="add">+</button>
<button class="key--operator" data-action="subtract">-</button>
<button class="key--operator" data-action="multiply">×</button>
<button class="key--operator" data-action="divide">÷</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>0</button>
<button data-action="decimal">.</button>
<button data-action="clear">AC</button>
<button class="key--equal" data-action="calculate">=</button>
</div>
</div>
</div>
</body>
Every time you click on one of the buttons, the calc
function gets called, which adds an event listener to all the buttons. Therefore, with every click, you have one more listener on the button, thus calling the function multiple times. Choose whether you want to use onclick
or an event listener.
One option would be to remove the onclick
and move the code out of the function to fix your problem like so:
const calculator = document.querySelector(".calculator");
// All buttons is inside .calculator__keys.
const keys = document.querySelector(".calculator__keys");
const display = document.querySelector(".calculator__display");
// use an event delegation pattern to listen, since keys are all children of .calculator__keys.
keys.addEventListener("click", (e) => {
if (e.target.matches("button")) {
// use the data-action attribute to determine the type of key that is clicked.
const key = e.target;
const action = key.dataset.action;
// The number of the key that was clicked
const keyContent = key.textContent;
// The current displayed number
const displayedNum = display.textContent;
if (!action) {
console.log("number key!");
if (displayedNum === "0") {
display.textContent = keyContent;
console.log("key content " + keyContent);
} else {
display.textContent = displayedNum + keyContent;
console.log("key content " + keyContent);
}
} else if (
action === "add" ||
action === "subtract" ||
action === "multiply" ||
action === "divide"
) {
console.log("operator key");
// add the is-depressed class to the operator key
key.classList.add("is-depressed");
} else if (action === "decimal") {
console.log("decimal key");
display.textContent = displayedNum + ".";
} else if (action === "clear") {
console.log("clear key");
} else if (action === "calculate") {
console.log("equal key");
}
}
});
<body>
<div class="container">
<div class="calculator">
<div class="calculator__display">0</div>
<div class="calculator__keys">
<button class="key--operator" data-action="add">+</button>
<button class="key--operator" data-action="subtract">-</button>
<button class="key--operator" data-action="multiply">×</button>
<button class="key--operator" data-action="divide">÷</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>0</button>
<button data-action="decimal">.</button>
<button data-action="clear">AC</button>
<button class="key--equal" data-action="calculate">=</button>
</div>
</div>
</div>
</body>