javascriptjquerycalculator

Simple project Jquery Simple Calculator


I am currently learning and practicing my frontend web skill to create a simple web apps using Jquery. I decided to make a simple calculator. I could do it easily using some functions with input numbers as parameters. But I am struggling to make it has interface.

Here is the relevant HTML.

<h1>Simple Calculator</h1>
<div class="inputbar">
    <input
      id="calcInput"
      type="text"
      class="displaycalc"
      onkeypress="return /[0-9]/i.test(event.key)"
      placeholder="0"
    />
</div>
<div class="container">
    <div class="digit seven btn">7</div>
    <div class="digit eight btn">8</div>
    <div class="digit nine btn">9</div>  
    <div class="op clear" onclick="clearDisplay()">CE</div>

    <div class="digit four btn">4</div>
    <div class="digit five btn">5</div>
    <div class="digit 6 btn">6</div>
    <div class="op multiply btn" data-operator="times">x</div>  

    <div class="digit one btn">1</div>
    <div class="digit two btn">2</div>
    <div class="digit three btn">3</div>
    <div class="op division btn" data-operator="divide">/</div>

    <div class="op changeminus btn">-/+</div>
    <div class="digit zero btn">0</div>
    
    <div class="op comma btn">.</div>
    <div class="op plus btn" data-operator="plus">+</div>
    <div class="op minus btn" data-operator="minus">-</div>
    <div id="equal" class="op equal btn">=</div>
</div>

I think It seems ok for the interfaces, but the real problem is in the external .js file of mine.

let input1 = [];

//this ONLY shows the live numbers pressed

$(".digit").click((evt) => {
    let currentValue = $("#calcInput").val();
    // Append the clicked button's value to the current input value
    $("#calcInput").val(currentValue + evt.target.innerHTML);
});

$(".op").click((evt) => {
    input1.push(parseFloat($("#calcInput").val()));//when an OP clicked, input1 value updated
    let operator = $(evt.target).data("operator");
    inputSecond();
    

});

$("#equal").click( (evt) => {
    switch(operator){
        case "plus":
            calculation(input1,2,plus);
            break;
        case "minus":
            calculation(input1,2,minus)
            break;
            default:
                break;
    }
});


function inputSecond(){

    $(".digit").click(() => {
    clearDisplay();
    $(".digit").click((evt) => {
        let currentValue = $("#calcInput").val();
        // Append the clicked button's value to the current input value
        $("#calcInput").val(currentValue + evt.target.innerHTML);
    });
})

}





function plus(num1,num2){
   console.log (num1+num2);
}

function minus(num1,num2){
    console.log(num1-num2);
}

function times(num1,num2){
    console.log(num1*num2);
}

function divide(num1,num2){
    console.log(num1/num2);
}

function calculation(num1,num2,operatorFunction){
    operatorFunction(num1,num2);
}

function clearDisplay(){
    $("#calcInput").val("");
}

Wish an expert could help me here, since GPT couldn't really get it where I want to go.

I want the input "display" to behave as a traditional calculator, where when I finish typing the digits that meant to be the first input, when I press an operator, wether plus, minus or multiply, the second input makes input display automatically overwritten the previous state.


Solution

  • Looks like a number of mistakes.

    1. operator is scoped only to the .op click handler, but the #equal click handler also needs access so the variable should be moved outside of the functions.

    2. inputSecond function as a whole doesn't make any sense to me. I don't see any purpose other than to clear the display so I would just move the clearDisplay call to the .op click handler and delete the rest of this function.

    3. The .op click handler doesn't take into account when "=" button is pressed, which is also an op but doesn't have a data-operator attribute, resulting in an error.

    4. The switch statement calling calculation calling different op functions could be simplified (probably to the point of removing calculation function entirely). The input values are in the array input1 which is accessible to all functions, so it doesn't need to be passed around as a parameter anywhere. I admit this isn't actually an error but it's far from the simplest the code could be.

    5. You hard-coded a "2" into every call to calculation and then treat input1 array like a number. Maybe you didn't get this far but there is also no attempt to display the result, and other clean up actions like clearing the input1 array still needs to be done.

    6. This calculator doesn't look built to handle anything other than the simplest calculations, so can be broken very easily. I'm assuming the goal is to get these simple calculations working and you'll worry about more complicated use cases later, but I did need to point it out.

    I fixed everything I could below. I did not end up changing any HTML

    let input1 = [];
    let operator
    
    //this ONLY shows the live numbers pressed
    
    $(".digit").click((evt) => {
      let currentValue = $("#calcInput").val();
      // Append the clicked button's value to the current input value
      $("#calcInput").val(currentValue + evt.target.innerHTML);
    });
    
    $(".op").click((evt) => {
      input1.push(parseFloat($("#calcInput").val())); //when an OP clicked, input1 value updated
      operator = $(evt.target).data("operator") ?? operator;
      clearDisplay();
    });
    
    $("#equal").click((evt) => {
      switch (operator) {
        case "plus":
          calculation(plus);
          break;
        case "minus":
          calculation(minus);
          break;
        default:
          break;
      }
    });
    
    function plus(num1, num2) {
      return num1 + num2;
    }
    
    function minus(num1, num2) {
      return num1 - num2;
    }
    
    function times(num1, num2) {
      return num1 * num2;
    }
    
    function divide(num1, num2) {
      return num1 / num2;
    }
    
    function calculation(operatorFunction) {
      const result = operatorFunction(...input1);
      $("#calcInput").val(result);
      input1 = [];
    }
    
    function clearDisplay() {
      $("#calcInput").val("");
    }
    

    jsfiddle demo