Search code examples
javascripthtmlonclickonclicklistener

Calculator - click on a number the same number is displayed more than once


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 enter image description here

 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">&times;</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>


Solution

  • 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">&times;</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>