variable set to a empty string without assigement and want change value

Viewed 40

I've created a calculator and I want the operate() function to be called once all values are not an empty string. For example 5 + 5 should call operate() as soon as the second number is entered.

Whats confusing me is the input field is displaying 5 + 5 but when I console.log the input.value I get 5 + and secondNumbers = "". I'm not sure why this is happening.

enter image description here

If you look in the console to the right of the image you see I get 4 + which is console.log(inputdisplay.value)

I'im not sure if this is Javascript being weird or if I've done something wrong.

const buttons = document.querySelectorAll('button');
const inputdisplay = document.querySelector('.input-display');

var firstNumbers;
var secondNumbers;
var operator;

buttons.forEach(function(button) {
  button.addEventListener('click', function(e) {
    firstNumbers = inputdisplay.value.split(" ")[0]
    operator = inputdisplay.value.split(" ")[1]
    secondNumbers = inputdisplay.value.split(" ")[2]

    console.log(inputdisplay.value)
    console.log(secondNumbers)

    if (typeof(secondNumbers) === "string" && secondNumbers !== "") {
      console.log("ran")
      inputdisplay.value = operate()
    } else if (button.classList.contains("AC")) {
      inputdisplay.value = ""
      return
    } else if (button.classList.contains("equals")) {
      inputdisplay.value = operate()
    } else if (button.classList.contains("operator")) {
      inputdisplay.value += ` ${button.innerText} `
    } else {
      inputdisplay.value += button.innerText
    }
  })
})

function operate() {
  intFirstNumbers = parseFloat(firstNumbers)
  intSecondNumbers = parseFloat(secondNumbers)
  try {
    switch (operator) {
      case "+":
        return intFirstNumbers + intSecondNumbers
      case "-":
        return intFirstNumbers - intSecondNumbers
      case "*":
        return intFirstNumbers * intSecondNumbers
      case "/":
        return intFirstNumbers / intSecondNumbers
    }
  } catch (e) {
    return "Error: " + e.message
  }
}
<div class="container">
  <input readonly class="input-display" type="text">
  <div class="grid">
    <div class="numberGrid">
      <div class="row-1">
        <button class=" button 1">1</button>
        <button class=" button 2">2</button>
        <button class=" button 3">3</button>
        <button class=" button 4">4</button>
      </div>
      <div class=" row-2">
        <button class=" button 5">5</button>
        <button class=" button 6">6</button>
        <button class=" button 7">7</button>
        <button class=" button 8">8</button>
      </div>
      <div class="row-3">
        <button class=" button 9">9</button>
        <button class=" button 0">0</button>
        <button class=" button decimal ">.</button>
      </div>
    </div>
    <div class="operatorGrid">
      <div class="row-4">
        <button class=" button sum operator"> + </button>
        <button class=" button subtract operator"> - </button>
        <button class=" button multiply operator"> * </button>
        <button class=" button divide operator"> / </button>
        <button class=" button backspace operator"> -></button>
        <button class=" button equals"> = </button>
        <button class=" button AC">AC</button>
      </div>
    </div>
  </div>
</div>

1 Answers

seems to me like you are just getting started, so i will not be going deep on best practices. and just help you get this code working. hopefully you understand what's happening a bit better afterwards ^.^

your click handler needs to be reworked

   
if (button.classList.contains("AC")) {
  inputdisplay.value = ""
  return
   // return ~ rest of the function isn't executed
   // also it doesn't make sense as part of an if-else chain
} 

/***
// if you are operating when second number
// is input, this is useless. and would allow
// running `operate` on output
if (button.classList.contains("equals")) {
  inputdisplay.value = operate()

}
***/

// these are your main input "types" operator vs number
if (button.classList.contains("operator")) {
  inputdisplay.value += ` ${button.innerText} `
} else {
  inputdisplay.value += button.innerText
}

// evaluate **after** modifying `inputdisplay.value`
// note: you didn't use these values earlier anyway

firstNumbers = inputdisplay.value.split(" ")[0]
operator = inputdisplay.value.split(" ")[1]
secondNumbers = inputdisplay.value.split(" ")[2]

console.log(inputdisplay.value)
console.log(secondNumbers)

// checking if the input is "complete" and operating if it is
if (typeof(secondNumbers) === "string" && secondNumbers !== "") {
      console.log("ran")
      inputdisplay.value = operate()
}

because you had the check for "completeness" at the top of your handler, it would have worked on the next button click. any button.

so a user inputting 5 > + > 5 > 7 would have called operate when they clicked 7. and then inputdisplay would have been

  1. replaced with 10 by operate
  2. the input of 7 is dangling/lost

now the serious stuff xD

  1. if you have only one element of a certain function, use id="input-display" in HTML. and in JavaScript querySelector('#input-display') or document.getElementById('input-display').

    • similarly for the AC button. if (button.id === 'AC')
  2. that immediate calculation when "secondnumber" is input is most likely not what the user expects. also note that because of the way JavaScript event loop works the user will never see the second number being input. only the result of operate is seen after the second number is clicked

Related