1

I'm working on this calculator for JavaScript where a ice hockey goalie will be able to enter information to calculate his goals against average, or his GAA. I've got the calculator working (although I wish I could format the output to #.##, but oh well), but I want to be able to handle exceptions arising from say, a user entering a letter instead of a number, which would result in a NaN output via a try/catch statement, except I'm not sure how you would format it to look for NaN values. Any idea how I might go about doing that? Here is my code:

<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
<Title>Goals Against Average Calculator</Title>
<body>
<script src="modernizr.custom.05819.js"></script><!--Links to file containing modernizer library-->

<!-- Navigation -->
<nav>
  <ul class="w3-navbar w3-black">
    <li><a href="file:///C:/Users/Kyle/Desktop/Document1.html">Home</a></li> <!--Link to Home Page-->
    <li><a href="file:///C:/Users/Kyle/Desktop/Document2.html">NHL Teams</a></li><!--Link to Page of NHL Teams-->
    <li><a href="file:///C:/Users/Kyle/Desktop/Document3.html">AHL Teams</a></li><!--Link to Page of AHL Teams-->
    <li><a href="file:///C:/Users/Kyle/Desktop/Document4.html">WHL Teams</a></li><!--Link to Page of WHL Teams-->
    <li><a href="file:///C:/Users/Kyle/Desktop/Document5.html">G.A.A. Calculator</a></li><!--Link to GAA Calculator-->
        <li><a href="file:///C:/Users/Kyle/Desktop/Document6.html">Fan Survey</a></li><!--Link to Fan Survey Page-->
  </ul>
</nav>
<header>
      <h1 style="text-align:center;">Goals Against Average Calculator</h1><!--Title of Page-->
 </header>
    <article>
      <form>
          <fieldset>
            <label for="GoalsAllowed">
              Enter Number of Goals Allowed
            </label>
            <input type="Goals" id="GoalsAllowed" /><!--Input for Goals Allowed-->
            </fieldset>
            <fieldset>
            <label for="MinutesPlayed">
              Enter Minutes Played
            </label>
            <input type="MinPlayed" id="MPlayed" /><!--Input for Minutes Played-->
          </fieldset>
           <fieldset>
            <label for="GameLength">
              Regulation Game Length
            </label>
            <input type="Minutes" id="MinGame" /><!--Input for Length of Regulation Game-->
            </fieldset>
            <fieldset>
            <button type="button" id="button">Calculate</button><!--Calculation Button-->
          </fieldset>
          <fieldset>
            <p id="GAA">&nbsp;</p>
          </fieldset>
        </form>
   </article>
   <script>
        function convert() 
        {

            var Goals = document.getElementById("GoalsAllowed").value;
            var Minutes = document.getElementById("MPlayed").value;
            var GameLength = document.getElementById("MinGame").value;

            var GAA = (Goals * GameLength) / Minutes;
            //window.alert("Swords and Sandals: " + GAA);
            document.getElementById("GAA").innerHTML = "Your Goals Against Average is: " + GAA;

        }
        document.getElementById("button").
        addEventListener("click", convert, false);
   </script>
</body>
</html>

EDIT: The comment about decimal formatting isn't why I'm posting. It was merely for cosmetic reasons on my part on what I would like it to look like, but it works fine as it is.

J.Doe
  • 15
  • 1
  • 6
  • 4
    Use [parseInt()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/parseInt) and [isNaN()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/isNaN). – Etheryte Jan 23 '17 at 21:15
  • simply check `isNaN(GAA)` after this line `var GAA = (Goals * GameLength) / Minutes;` – Anthony C Jan 23 '17 at 21:16
  • Possible duplicate of [Validate decimal numbers in JavaScript - IsNumeric()](http://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric) – Heretic Monkey Jan 23 '17 at 21:18
  • Do not use `parseInt`, there are too many strange edge cases. Use `Number()` instead and either round it to the nearest integer or throw it out if `x % 1` isn't 0. – furkle Jan 23 '17 at 21:19
  • 1
    Also worth considering simply suppressing the ability to enter non-numeric characters upfront, so such a check isn't necessary. – Alexander Nied Jan 23 '17 at 21:20
  • @furkle - why not use parseInt? If you make sure to always add the radix argument there oughtn't be any concerns I can think of... – Alexander Nied Jan 23 '17 at 21:20
  • 1
    @anied Sorry, that's probably less gospel than personal preference on my part, but I dislike the fact that you can `parseInt` `23foo` and it gives you `23` -- it just keeps too much in-band for my taste. – furkle Jan 23 '17 at 21:21
  • @furkle, you are not the only one. i also had ran into the same problem w/ `parseInt` in the past. – Anthony C Jan 23 '17 at 21:23

5 Answers5

1

Others have provided answers about Number.isNaN, so I won't go into details on that; it's the right answer. :-)

As for your secondary question, how to format the number to two decimal places, all numbers have a function toFixed(numberOfPlaces) that returns a formatted string. Now, this function does not perform any rounding; it just chops off the remaining decimals. So for instance:

var num = 1.005;
var formatted = num.toFixed(2);

..will return "1.00". You probably want to round the input so that it gets handled and formatted consistently. To do that, there is a function Math.round() that you can call. It always rounds the number to have no decimals at all. You want two decimals, so that's a non-starter, right? Well, here's a little trick: If you multiply the number by 100 first, then you bump those two digits you want to keep to the left of the decimal. After rounding it, divide it by 100 to put them back in the right place.

Putting it all together:

var input = Number(prompt("Give me a number"));

if (Number.isNaN(input))
    alert("That isn't a valid number!");
else
{
    input = Math.round(input * 100) / 100;

    var formatted = input.toFixed(2);

    alert("Your input was: " + formatted);
}
Jonathan Gilbert
  • 3,526
  • 20
  • 28
  • Nice! Worked perfectly! Nice touch about the decimal formatting too! Wasn't the original question, just purely for cosmetic reasons. I'm kind of OCD like that lol. – J.Doe Jan 23 '17 at 21:29
0

My experience is that the best way to check for NaN is a little verbose, but as far as I've seen it's bulletproof.

var numStr = prompt('Give me a number');
var num = Number.isNaN(Number(numStr));

If numStr was a valid number string, num will be false; if it was not, num will be true.

Why not just use Number.isNaN without converting to a number first? Well, Number.isNaN doesn't check whether a value is a Number or not, it literally just checks if it's NaN, so Number.isNaN('totally not a number') will return false.

furkle
  • 5,019
  • 1
  • 15
  • 24
0

You can also restrict the user to enter only number by using the type="number" to the input type in the HTML directly. HTML 5 introduces the number` type.

<input type="number" id="GoalsAllowed" /><!--Input for Goals Allowed-->

Abhinav Galodha
  • 9,293
  • 2
  • 31
  • 41
0

Here is a JS Fiddle showing you what you can do: https://jsfiddle.net/iamjpg/huk8yp0L/

var convert = function() {
  var Goals = document.getElementById("GoalsAllowed").value;
  var Minutes = document.getElementById("MPlayed").value;
  var GameLength = document.getElementById("MinGame").value;

  var regex = /^[+-]?\d+(\.\d+)?$/

  if (!regex.test(Goals) || !regex.test(Minutes) || !regex.test(GameLength)) {
    alert('Please only enter numeric values.');
    return false;
  }

  var GAA = (Goals * GameLength) / Minutes;
  //window.alert("Swords and Sandals: " + GAA);
  document.getElementById("GAA").innerHTML = "Your Goals Against Average is: " + Math.ceil(GAA * 100) / 100;
}

document.getElementById("button").addEventListener("click", convert, false);

var regex = /^[+-]?\d+(\.\d+)?$/ - Checks if you are entering a number or float.

Math.ceil(GAA * 100) / 100; - Rounds your calculated value to the nearest hundredth.

Hope this is helpful.

iamjpg
  • 7,078
  • 1
  • 16
  • 18
-1

You have to convert each value to number

goal = +goal

and check if it is a number

if(isNaN(goal)){
  // show error
}else{
  // show result
}
Yukulélé
  • 15,644
  • 10
  • 70
  • 94