javascriptfunctioncalculatoraddeventlistener

How to add math function without eval to basic calculator


Per the Odin Project's instructions, I need to make my basic calculator operate via math functions rather than using eval(). https://www.theodinproject.com/lessons/foundations-calculator

I've only added the addition part to my mathWorks function. However, I'm not sure how to tie my mathWorks function to my else if block when "=" is selected. Any help would be greatly appreciated.

const container = document.querySelector(".container");
const calcBody = document.querySelector("#calcBody");
const input = document.querySelector("#input");
let a = "";
let b = "";
let operator = "";
let result = "";


      
const numbers = {
    reset: "CE",
    goBack: "C",
    divide: "/",
    multiply: "*",
    seven: 7,
    eight: 8,
    nine: 9,
    add: "+",
    four: 4,
    five: 5,
    six: 6,
    minus: "-",
    one: 1,
    two: 2,
    three: 3,
    decimal: ".",
    zero: 0,
    equal: "=",
};

for (let key in numbers) {
    let button = document.createElement("button");
    button.setAttribute("id", key);
    button.textContent = numbers[key];
    container.appendChild(button);

    button.addEventListener("click", (e) => {
        let val = e.target.textContent;
       
        if(e.target.textContent === "+" || 
           e.target.textContent === "/" ||
           e.target.textContent === "*")
           {
           operator = val;
           input.textContent = a + " " + operator + " ";
           }

        else if(e.target.textContent === "CE") {
             input.textContent = "";
             a = "";
        }
        else if(input.textContent.includes("*") ||
                 input.textContent.includes("+")  ||
                 input.textContent.includes("/")) {
            b += val;
            input.textContent = a + " " + operator + " " + b;
        }

        else if(e.target.textContent === "="){
            mathWorks();
            }
        
        
            else 
        {
            a += val
            input.textContent = a;
        }

    });

    function mathWorks(){
        if(operator === "+"){
            result = parseFloat(a) + parseFloat(b);
            input.textContent = result;
            
        }

    }

}

I'm kind of at a loss at the moment. I've tried adding parseFloat and including a and b in mathWorks parameters.


Solution

  • In general, the training tasks for creating a calculator are reduced to more branching and creating functions for all mathematical operators.

    If you can use function constructors, then the calculator might look like this:

    const container = document.querySelector(".container");
    const calcBody = document.querySelector("#calcBody");
    const input = document.querySelector("#input");
    let a = "";
    let b = "";
    let operator = "";
    let result = "";
    
    const numbers = {
      reset: "CE",
      goBack: "C",
      divide: "/",
      multiply: "*",
      seven: 7,
      eight: 8,
      nine: 9,
      add: "+",
      four: 4,
      five: 5,
      six: 6,
      minus: "-",
      one: 1,
      two: 2,
      three: 3,
      decimal: ".",
      zero: 0,
      equal: "=",
    };
    
    const actions = [];
    let numAcc = '';
    for (let key in numbers) {
      let button = document.createElement("button");
      button.setAttribute("id", key);
      button.textContent = numbers[key];
      container.appendChild(button);
    
      function clear() {
        input.textContent = "";
        actions.length = 0;
        numAcc = '';
      }
    
      button.addEventListener("click", (e) => {
        if (e.target.textContent === "CE") {
          clear();
          calcBody.textContent = '';
          return;
        }
        if (e.target.textContent === "C") {
          if (numAcc.length > 0) {
            numAcc = numAcc.slice(0, -1);
          } else {
            actions.pop();
            if (actions.length) {
              numAcc = actions[actions.length - 1];
              actions.pop();
            }
          }
          input.textContent = actions.join(' ') + ' ' + numAcc;
          return;
        }
        if (e.target.textContent === '=') {
          if (numAcc.length < 1 || actions.length < 2) {
            clear();
            calcBody.textContent = '';
          } else {
            const fn = new Function(`return ${actions.join(' ')} ${numAcc} + 0`);
            calcBody.textContent = fn();
            clear();
          }
        } else {
          if (e.target.textContent === '.' || !isNaN(e.target.textContent)) {
            numAcc += e.target.textContent;
          } else {
            if (numAcc.length) {
              actions.push(numAcc);
              actions.push(e.target.textContent);
              numAcc = '';
            } else {
              actions.pop()
              actions.push(e.target.textContent)
            }
          }
          input.textContent = actions.join(' ') + ' ' + numAcc;
        }
      });
    }
    <div class="container"></div>
    <div id="input"></div>
    <div id="calcBody"></div>