Search code examples
javascriptbuttoncalculatoroperation

Perform operations on button values in JavaScript


I'm trying to make a calculator in JS and I'm searching for ways to add, subtract, multiply and divide button values. I've created a function to display the buttons but now I realize that that might not be necessary and I might need just one function which displays and does the operation.

HTML code:

        <div class="numbers">
            <button value="1" onclick="displayButtons(this)">1</button>
            <button value="2" onclick="displayButtons(this)">2</button>
            <button value="3" onclick="displayButtons(this)">3</button>
            <button value="4" onclick="displayButtons(this)">4</button> 
            <button value="=" id="calculate" onclick="performOperations(this)">=</button>
            **etc.**
        <div class="operations">
            <button value="+" onclick="displayButtons(this)" style="width: 2rem; top: 5rem;">+</button>
            <button value="-" onclick="displayButtons(this)" style="left: -6rem; top: 5rem;">-</button>
            **etc.**

JS code:


function displayButtons(button) {
    outputDiv.innerHTML += button.value
}

function performOperations(button) {

    var val = parseFloat(button.getAttribute("value"));
    var total = parseFloat(document.getElementById('output').getAttribute("value"));

    document.getElementById('output').innerHTML = total + val;
}

That is my attempt to do addition the button values and I have the performOperations called on the "=" sign which currently displays NaN onclick. (I'm working on the addition first).
Any push in the right direction is appreciated. Thank you!


Solution

  • You're right that you can use one function to do all the work but it means that you have to mark up your HTML with classes and data-attributes.

    In this example I've used CSS grid to display the various calculator buttons. The "equals" and "clear" buttons have a data attribute to help the function decide what operation to do.

    // Cache our elements and add an event listener
    // to the button container. `handleClick` returns a
    // new function that is called when the listener is fired
    const output = document.querySelector('.output');
    const buttons = document.querySelector('.buttons');
    buttons.addEventListener('click', handleClick(), false);
    
    function handleClick() {
    
      // Initialise the sum
      const sum = [];
    
      // Return the function that will be called
      // when a click event occurs
      return function(e) {
    
        // Because we're using event delegation (details
        // below) we need to check that the element that
        // was clicked was a button
        if (e.target.matches('.button')) {
    
          // Destructure the type from the dataset, and
          // the text content
          const { dataset: { type }, textContent } = e.target;
    
          // `switch` on the type
          switch (type) {
    
            // If it's equals evaluate the elements in
            // the array, and output it
            case 'equals': {
              output.textContent = eval(sum.join(''));
              break;
            }
            
            // Clear empties the array, and clears
            // the output
            case 'clear': {
              sum.length = 0;
              output.textContent = '';
              break;
            }
            
            // Otherwise add the textContent to
            // the array, and update the output
            default: {
              sum.push(textContent);
              output.textContent = sum.join(' ');
              break;
            }
          }
        }
    
      }
    
    }
    .container{width:175px;}
    .buttons {display: grid; grid-template-columns: repeat(4, 40px);grid-gap:0.3em;}
    .button {display:flex;justify-content:center;align-items:center;background-color: #efefef; border: 1px solid #565656;padding: 0.5em;}
    .button:not(.void):hover {background-color: #dfdfdf; cursor:pointer;}
    .output {height: 20px; padding: 0.5em 0.2em;font-size: 1.2em;border:1px solid #565656;margin-bottom: 0.2em;}
    <div class="container">
      <div class="output"></div>
      <div class="buttons">
        <div class="button">7</div>
        <div class="button">8</div>
        <div class="button">9</div>
        <div class="button">*</div>
        <div class="button">4</div>
        <div class="button">5</div>
        <div class="button">6</div>
        <div class="button">/</div>
        <div class="button">1</div>
        <div class="button">2</div>
        <div class="button">3</div>
        <div class="button">-</div>
        <div class="button">0</div>
        <div data-type="clear" class="button">C</div>
        <div data-type="equals" class="button">=</div>
        <div class="button">+</div>
      </div>
    </div>

    Additional documentation