Jim O.
Jim O.

Reputation: 1111

How to prevent 0 as null in javascript

I have the following code with following conditions:

My only problem is that the code interprets 0 as null. So, If I put 1 minutes 0 seconds, then nothing shows.

I want it to show "fast" when I enter 1 minute 0 seconds.

Thanks in advance.

<html>
<head>

  <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>

  <!-- TODO: Missing CoffeeScript 2 -->

  <script type="text/javascript">//<![CDATA[

    $(window).load(function(){
      
        $('input').keyup(function(){
            var min = 60 * Number($('#D').val());
            var sec = Number($('#E').val());

            if ((min+sec) <= 60) {document.getElementById("Run").innerHTML = "Fast";}
            if ((min+sec) >= 61) {document.getElementById("Run").innerHTML = "Slow";}
            
            if (min == null | min == "") {document.getElementById("Run").innerHTML = "";}
            if (sec == null | sec == "") {document.getElementById("Run").innerHTML = "";}
            
        });
        
	});
</script>

<style>
	h1 { margin: 0 10px 25px 5px; padding: 5px; font-size: 32px; font-family: Arial }
	input { margin: 0 10px 10px 10px; padding: 5px; font-size: 24px; width: 200px }
    label { margin: 0 10px 10px 10px; font-size: 20px; display: block; font-family: Arial }
	span { margin: 0 0px 0px 10px; font-size: 44px; font-family: Arial }
	stat { margin: 0 0px 0px 10px; font-size: 24px; font-family: Arial }
</style>

</head>
<body>
    
    <input id="D"
    	type="number" 
        class="form-control formBlock" 
        placeholder="Minutes" 
        required="" 
        min="1" 
        max="59"
        onkeyup="if(parseInt(this.value) > 59){ this.value = 59; return false; }"
        >
    <stat id="Run"></stat><br>
    <input id="E" 
    	type="number" 
    	class="form-control formBlock" 
    	placeholder="Seconds" 
        required="" 
        min="1" 
        max="59"
        onkeyup="if(parseInt(this.value) > 59){ this.value = 59; return false; }"
        >
        <br>
    <br>

  <script>
    // results
    if (window.parent && window.parent.parent){
      window.parent.parent.postMessage(["resultsFrame", {
        height: document.body.getBoundingClientRect().height,
        slug: ""
      }], "*")
    }
    window.name = "result"
    
    //
    
  </script>

</body>

</html>

Upvotes: 4

Views: 2900

Answers (3)

Kaiido
Kaiido

Reputation: 136638

When using type="number" inputs, use it completely.

They do offer a valueAsNumber property getter, which will coerce your values directly to Numbers, so all you have to do next, is to use them after a fool-guard check against isNaN():

$(window).load(function() {

  const min_input = $('#D')[0];
  const sec_input = $('#E')[0];
  const run_elem = document.getElementById("Run");

  $('input').keyup(function() {
    var min = 60 * min_input.valueAsNumber;
    var sec = sec_input.valueAsNumber;

    if( isNaN(min + sec) ) {
      run_elem.innerHTML = "";
    }
    else if ((min + sec) <= 60) {
      run_elem.innerHTML = "Fast";
    }
    else if ((min + sec) >= 61) {
      run_elem.innerHTML = "Slow";
    }

  });

});
h1 {
  margin: 0 10px 25px 5px;
  padding: 5px;
  font-size: 32px;
  font-family: Arial
}

input {
  margin: 0 10px 10px 10px;
  padding: 5px;
  font-size: 24px;
  width: 200px
}

label {
  margin: 0 10px 10px 10px;
  font-size: 20px;
  display: block;
  font-family: Arial
}

span {
  margin: 0 0px 0px 10px;
  font-size: 44px;
  font-family: Arial
}

stat {
  margin: 0 0px 0px 10px;
  font-size: 24px;
  font-family: Arial
}
<script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
<input id="D" type="number" class="form-control formBlock" placeholder="Minutes" required="" min="0" max="59" onkeyup="if(parseInt(this.value) > 59){ this.value = 59; return false; }">
<stat id="Run"></stat><br>
<input id="E" type="number" class="form-control formBlock" placeholder="Seconds" required="" min="0" max="59" onkeyup="if(parseInt(this.value) > 59){ this.value = 59; return false; }">

Upvotes: 1

plalx
plalx

Reputation: 43718

"My only problem is that the code interprets 0 as null"

That's an incorrect assumption, since Number('0') == null is false.

The reason your code behaves like that is 0 == '' is true in JavaScript. You could use === for strict equality, but then both of your conditions would never be entered since min nor sec can be === null or === ''.

min and sec are assigned the result of a number conversion which can only yield a valid number or NaN. Anything that doesn't coerce to a number would give NaN. Unfortunately blank strings does coerce to 0, but you can use the || operator to coerce '' into NaN, since empty string is the only falsy value you can get from your input values (given type="number").

From that point the values can either be numbers or NaN. Given that NaN + number gives out NaN you can safely assume that if isNaN(min + sec) then one of the inputs were invalid or blank.

Also note that you're using | (bitwise or) instead of ||. The if branching outcome was the same as || in your code because the left-hand-side and right-hand-side were booleans, but it's more semantically correct to use ||.

EDIT: @Kaiido makes a point using input.valueAsNumber, which properly coerces '' to NaN already, removing the need for Number(input.value || NaN). See his answer for a slightly better solution.

<html>
<head>

  <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>

  <!-- TODO: Missing CoffeeScript 2 -->

  <script type="text/javascript">//<![CDATA[

    $(window).load(function(){
      
        $('input').keyup(function(){
            const min = 60 * Number($('#D').val() || NaN);
            const sec = Number($('#E').val() || NaN);
            const total = min + sec;

            const speed = isNaN(total)? '' : (total <= 60? 'Fast' : 'Slow');
            
            document.getElementById("Run").innerHTML = speed;     
        });
        
	});
</script>

<style>
	h1 { margin: 0 10px 25px 5px; padding: 5px; font-size: 32px; font-family: Arial }
	input { margin: 0 10px 10px 10px; padding: 5px; font-size: 24px; width: 200px }
    label { margin: 0 10px 10px 10px; font-size: 20px; display: block; font-family: Arial }
	span { margin: 0 0px 0px 10px; font-size: 44px; font-family: Arial }
	stat { margin: 0 0px 0px 10px; font-size: 24px; font-family: Arial }
</style>

</head>
<body>
    
    <input id="D"
    	type="number" 
        class="form-control formBlock" 
        placeholder="Minutes" 
        required="" 
        min="1" 
        max="59"
        onkeyup="if(parseInt(this.value) > 59){ this.value = 59; return false; }"
        >
    <stat id="Run"></stat><br>
    <input id="E" 
    	type="number" 
    	class="form-control formBlock" 
    	placeholder="Seconds" 
        required="" 
        min="1" 
        max="59"
        onkeyup="if(parseInt(this.value) > 59){ this.value = 59; return false; }"
        >
        <br>
    <br>

  <script>
    // results
    if (window.parent && window.parent.parent){
      window.parent.parent.postMessage(["resultsFrame", {
        height: document.body.getBoundingClientRect().height,
        slug: ""
      }], "*")
    }
    window.name = "result"
    
    //
    
  </script>

</body>

</html>

Upvotes: 3

Ed Lucas
Ed Lucas

Reputation: 7305

Marco's got the fix for your immediate problem, where you need to compare for type as well as value by using === (strict comparison). More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators

You also have an issue with your logic, where you are using the bitwise OR | in your conditionals. I'm sure you mean to use a normal OR comparison, ||:

        if (min === null || min === "") {document.getElementById("Run").innerHTML = "";}
        if (sec === null || sec === "") {document.getElementById("Run").innerHTML = "";}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators

Upvotes: 2

Related Questions