-2

I am a beginner to JavaScript and am working on creating a simple calculator using functions. I am running into a problem where after entering two numbers and selecting the operation, I am receiving NaN as a result. However, if I run the functions in the console with numbers, it results correctly with a number instead of NaN. I'm returning my values and passing them into the calculation functions; what am I missing? I feel like it is a simple thing I am overlooking but cannot figure it out.

function getVals() {
  var val1 = parseInt(document.getElementById('number1').value);
  var val2 = parseInt(document.getElementById('number2').value);
  return val1, val2;
}

function addNumber(val1, val2) {
  var total = Number(val1) + Number(val2);
  document.getElementById('result').innerHTML = (total);
  return total;
}

function subtractNumber(val1, val2) {
  var total = val1 - val2;
  document.getElementById('result').innerHTML = (total);
  return total;
}

function multiplyNumber(val1, val2) {
  var total = val1 * val2;
  document.getElementById('result').innerHTML = (total);
  return total;
}

function divideNumber(val1, val2) {
  var total = val1 / val2;
  document.getElementById('result').innerHTML = (total);
  return total;
} 

function exponentiation(val1, val2) {
  var total = val1 ** val2;
  document.getElementById('result').innerHTML = (total);
  return total;
} 
<!doctype html>
<html>
  <head>
    <h1>Calculator</h1>
    <body>
      <input id="number1" placeholder="Enter text" onblur="getVals()">
      <input id="number2" placeholder="Enter text" onblur="getVals()"><br>
      <br>
      <input type="submit" onclick="addNumber()" value="+">
      <input type="submit" onclick="subtractNumber()" value="-">
      <input type="submit" onclick="multiplyNumber()" value="x">
      <input type="submit" onclick="divideNumber()" value="÷">
      <input type="submit" onclick="exponentiation()" value="^"><br>
      <br>
      <b>Calculation:</b><br>
      <p id="result"></p>
      <script src="calculator.js"></script>
    </body>
</html>
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
thugrose
  • 1
  • 4

1 Answers1

-1

While you are getting the values of the input elements prior to doing the calculations. You are storing them in local variables that are not accessible outside of the getVals function and your various calculation functions are expecting the two values to be passed into them as arguments, but when you call them, you aren't passing anything.

One solution is to declare the input variables at a higher scope and just use them directly without any function arguments.

// By declaring the variables at a higher scope than any function that
// will use them, they beconme available to all of them.
let val1 = null;
let val2 = null;

function getVals() {
  val1 = parseInt(document.getElementById('number1').value,10);
  val2 = parseInt(document.getElementById('number2').value,10);
}

function addNumber() {
  var total = Number(val1) + Number(val2);
  document.getElementById('result').innerHTML = (total);
  return total;
}

function subtractNumber() {
  var total = val1 - val2;
  document.getElementById('result').innerHTML = (total);
  return total;
}

function multiplyNumber() {
  var total = val1 * val2;
  document.getElementById('result').innerHTML = (total);
  return total;
}

function divideNumber() {
  var total = val1 / val2;
  document.getElementById('result').innerHTML = (total);
  return total;
} 

function exponentiation() {
  var total = val1 ** val2;
  document.getElementById('result').innerHTML = (total);
  return total;
}
<!doctype html>
<html>
  <head>
    <h1>Calculator</h1>
    <body>
      <input id="number1" placeholder="Enter text" onblur="getVals()">
      <input id="number2" placeholder="Enter text" onblur="getVals()"><br>
      <br>
      <input type="submit" onclick="addNumber()" value="+">
      <input type="submit" onclick="subtractNumber()" value="-">
      <input type="submit" onclick="multiplyNumber()" value="x">
      <input type="submit" onclick="divideNumber()" value="÷">
      <input type="submit" onclick="exponentiation()" value="^"><br>
      <br>
      <b>Calculation:</b><br>
      <p id="result"></p>
      <script src="calculator.js"></script>
    </body>
</html>

Now, beyond that you can only return one value from a function so return val1, val2 is only going to return val2.

Also, since all your calculation functions do the same thing, but with different math, you can combine all of them into a single function and eliminate much of the duplication.

Next, you shouldn't be scanning the DOM for the same elements over and over within a function and instead get the references just one when the page loads and then just use those references over and over.

Finally, you should not be using inline event attributes, such as onclick as these are 25+ year old ways of doing event registration before there were any standards. Instead, you should be separating your HTML and JavaScript and hooking up your event handlers with .addEventListener().

Putting all those things in place, we get:

// By declaring these varaibles outside of the various functions that will
// use them, they are available (scoped) to all of them.
let val1 = null;
let val2 = null;

// Get the DOM element references you'll need just once
// rather than every time a function is executed.
const num1 = document.getElementById('number1');
const num2 = document.getElementById('number2');

// Set up event handlers in JavaScript, not HTML
// Here, we are using "event delegation" and just setting
// up one event handler at the document level for any click
// event within it. Those events will "bubble up" to the
// document and be handled here.
document.addEventListener("click", function(evt){
  // We can check the element that triggered the event
  // and see if it's one we really want to handle.
  if(evt.target.classList.contains("operation")){
    calculate(evt.target.value);
  }
});

function calculate(operation) {
  // When using parseInt, always supply the second (optional) radix argument
  // which specifies what numerical base system you are working with, otherwise
  // some values (i.e. 0x) could be processed as hex or base 8.
  val1 = parseInt(num1.value,10);
  val2 = parseInt(num2.value,10);
  
  // switch checks the argument passed to it (operation in this case)
  // and tests it against each case and if it matches, performs the code
  // in that case branch
  switch (operation){
    case "+":
      // Don't use .innerHTNL when the content you are working with isn't HTML
      result.textContent = val1 + val2;   
      break;
    case "-":
      result.textContent = val1 - val2;   
      break;
    case "*":
      result.textContent = val1 * val2;   
      break;
    case "/":
      result.textContent = val1 / val2;   
      break;   
    case "^":
      result.textContent = val1 ** val2;   
      break;      
  }
  
  // There's no need to return anything from this function since
  // you are putting the result into an element on the page.
}
<!doctype html>
<html>
  <head>
    <h1>Calculator</h1>
    <body>
      <!-- If you use type="number", it will avoid non-numeric data from being inputted -->
      <input type="number" id="number1" placeholder="Enter number">
      <input type="number" id="number2" placeholder="Enter number"><br>
      <br>
      <!-- type="submit" is for submitting form data. You aren't doing that
           here and so should just be using type="button" -->
      <input type="button" class="operation" value="+">
      <input type="button" class="operation" value="-">
      <input type="button" class="operation" value="*">
      <input type="button" class="operation" value="/">
      <input type="button" class="operation" value="^"><br>
      <br>
      <b>Calculation:</b><br>
      <p id="result"></p>
      <script src="calculator.js"></script>
    </body>
</html>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71