-2

I have this calculator that I'd like for the results to auto update after the the user adds input. I've tried the .keyup thing, but I don't understand it. I'm kinda new to javascript.

Here's my codepen for the project. http://codepen.io/Tristangre97/pen/zNvQON?editors=0010

HTML

<div class="card">
<div class="title">Input</div>
<br>

<div id="metalSpan"><input class="whiteinput" id="numMetal" type="number">
<div class="floater">Metal Quantity</div>

<div id="metalAlert">
</div>
</div>
<br>

<div id="forgeSpan"><input class="whiteinput" id="numForge" type=
"number">&nbsp;

<div class="floater">Forge Quantity</div></div>
<br>
<input checked id="rb1" name="fuel" type="radio" value="spark"> <label for=
"rb1">Sparkpowder</label> <input id="rb2" name="fuel" type="radio" value=
"wood"> <label for="rb2">Wood</label><br>
<br>
<button class="actionButton" id="submit" type="button">Calculate</button></div>

<div id="forgeAlert">
</div>

<div id="radioSpan">
<div class="floater">
</div>

<div class="card">
<div class="title2">Results</div>
<br>

<div id="result"><span id="spreadMetal"></span> metal <span class=
"plural"></span> forge<br>
<span id="spreadSpark"></span> <span id="fuelType"></span> <span class=
"plural"></span> forge <span id="allSpark"></span><br>
Completion Time: <span id="timeSpark"></span> minutes<br></div>
</div>
</div>

JS

var metals = 0;
var ingots = 0;
var forges = 0;
var spread = 0;
var sparks = 0;
var tSpark = 0;
var isWood = false;
$(document).ready(function() {
    $("#result").hide();
    $("#alert").hide();
    $("#submit").click(function() {
        metals = $("#numMetal").val();
        forges = $("#numForge").val();
        if (metals == 0 || metals == '') {
            $("#metalAlert").html("Please enter a value");
        }
        else if (forges == 0 || forges == '') {
            $("#metalAlert").html('');
            $("#forgeAlert").html("Please enter a value");
        }
        else {
            if ($("input[name=fuel]:checked").val() == "wood") {
                isWood = true;
            }
            else {
                isWood = false;
            }
            if (forges > 1) {
                $(".plural").html("per");
            }
            else {
                $(".plural").html("in the");
            }
            $("#forgeAlert").html('');
            if (metals % 2 == 0) {}
            else {
                metals = metals - 1;
                $("#alert").show();
            }
            ingots = metals / 2;
            spread = Math.floor(metals / forges);
            sparks = Math.ceil(((spread / 2) * 20) / 60);
            if (isWood) {
                sparks = sparks * 2;
            }
            tSpark = sparks * forges;
            if (forges > 1) {
                $("#allSpark").html(String("(" + tSpark + " total)"));
            }
            else {
                $("#allSpark").html(String(''));
            }
            $("#timeSpark").html(String((isWood) ? (sparks / 2) : sparks));
            $("#spreadMetal").html(String(spread));
            $("#spreadSpark").html(String(sparks));
            $("#fuelType").html((isWood) ? "wood" : "sparkpowder");
            $("#result").show();
        }
    });
});

4 Answers4

0

Look, you have two options:

Put all your algorithm of submit click into a function and call him into two binds: the submit click and input change (on('change')) or just remove your calculate button and rely the calculation into onchange of the inputs: each change of checks or inputs will trigger the calculation of metals. The second approach it's more interesting for me and removes the necessity to the user clicks to calculate (he already clicked into inputs and checks). Obviously you can add a filter to only allow to calculation function run after a certain minimum number of data filled, it's a good idea to avoid poor results resulted by lack of data.

capcj
  • 1,535
  • 1
  • 16
  • 23
0

To run the function whenever something is inputted in the field, try the

$("input").on('input', function() { .. });

var metals = 0;
var ingots = 0;
var forges = 0;
var spread = 0;
var sparks = 0;
var tSpark = 0;
var isWood = false;
$(document).ready(function() {
  $("#result").hide();
  $("#alert").hide();
  $("input").on('input', function() {
    metals = $("#numMetal").val();
    forges = $("#numForge").val();
    if (metals == 0 || metals == "") {
      $("#metalAlert").html("Please enter a value");
    } else if (forges == 0 || forges == "") {
      $("#metalAlert").html("");
      $("#forgeAlert").html("Please enter a value");
    } else {
      if ($("input[name=fuel]:checked").val() == "wood") {
        isWood = true;
      } else {
        isWood = false;
      }
      if (forges > 1) {
        $(".plural").html("per");
      } else {
        $(".plural").html("in the");
      }
      $("#forgeAlert").html("");
      if (metals % 2 == 0) {
      } else {
        metals = metals - 1;
        $("#alert").show();
      }
      ingots = metals / 2;
      spread = Math.floor(metals / forges);
      sparks = Math.ceil(spread / 2 * 20 / 60);
      if (isWood) {
        sparks = sparks * 2;
      }
      tSpark = sparks * forges;
      if (forges > 1) {
        $("#allSpark").html(String("(" + tSpark + " total)"));
      } else {
        $("#allSpark").html(String(""));
      }
      $("#timeSpark").html(String(isWood ? sparks / 2 : sparks));
      $("#spreadMetal").html(String(spread));
      $("#spreadSpark").html(String(sparks));
      $("#fuelType").html(isWood ? "wood" : "sparkpowder");
      $("#result").show();
    }
  });
});
body {
  background-color:#316b6f;
  font-family:Helvetica,sans-serif;
  font-size:16px;
}
 .whiteinput {
 outline: none;
 border-width: 0px;
 margin: 0;
 padding: .5em .6em;
 border-radius: 2px;
 font-size: 1em;
 color: #316b6f;
}
 .actionButton {
 background-color: #316B6F;
 color: #fff;
 padding: .5em .6em;
 border-radius: 3px;
 border-width: 0px;
 font-size: 1em;
 cursor: pointer;
 text-decoration: none;
     -webkit-transition: all 250ms;
  transition: all 250ms;
}
.actionButton:hover {
 color: #fff;
   
}
.actionButton:active {
 background: #BBFF77;
  color: #316B6F;
   -webkit-transition: all 550ms;
  transition: all 550ms;
}
.card {
  position: relative;
  background: #4E8083;
  color:#FFFFFF;
  border-radius:3px;
  padding:1.5em;
  margin-bottom: 3px;
}

.title {
  background: #76B167;
  padding: 3px;
  border-radius: 3px 0px 0px 0px;
  position: absolute;
  left: 0;
  top: 0;
  margin-bottom: 5px;
}

.title2 {
  background: #2F3A54;
  padding: 3px;
  border-radius: 3px 0px 0px 0px;
  position: absolute;
  left: 0;
  top: 0;
  margin-bottom: 5px;
}

.floater {
  padding: 3px;
}
.radiobtn {
  background: red;
  border-radius: 2px;
}
input[type=radio] + label:before {
    content: "";  
    display: inline-block;  
    width: 20px;  
    height: 20px;  
    vertical-align:middle;
    margin-right: 8px;  
    background-color: #aaa;  
   
  margin-bottom: 6px;
    border-radius: 2px;  
   -webkit-transition: all 450ms;
  transition: all 450ms;
}
input[type=radio], input[type=checkbox] {
    display:none;
}
input[type=radio]:checked + label:before {
    content: "\2022"; /* Bullet */
    color:white;
    background-color: #fff; 
    font-size:1.8em;
    text-align:center;
    line-height:14px;
    margin-right: 8px;  
}
input[type=checkbox]:checked + label:before {
    content:"\2714"; 
    color:white;
    background-color: #fff; 
    text-align:center;
    line-height:15px;
 
}
*:focus {
    outline: none;
}
 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script
  src="https://code.jquery.com/jquery-3.2.1.min.js"
  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
  crossorigin="anonymous"></script>
<div class="card">
  <div class="title">Input</div><br>
  <div id="metalSpan">
    <input class="whiteinput" id="numMetal" type="number">
<div class="floater">
     Metal Quantity
    </div>
    <div id="metalAlert">
    </div>
   </div>
   <br>
   <div id="forgeSpan">
    <input class="whiteinput" id="numForge" type="number">&nbsp;
 <div class="floater">
     Forge Quantity
    </div>
    </div>
    <br>
  <input type="radio" id="rb1" name="fuel" value="spark" checked>
<label for="rb1">Sparkpowder</label>
  
<input type="radio" id="rb2" name="fuel" value="wood">
<label for="rb2">Wood</label><br><br>
  
  
   <button class="actionButton" id="submit"
   type="button">Calculate</button>
   </div>
  
  

   <div id="forgeAlert">
   </div>
   <div id="radioSpan">
    <div class="floater">
    </div>
        <div class="card">
          <div class="title2">Results</div><br>
    <div id="result">
     <span id="spreadMetal"></span> metal <span class="plural"></span> forge<br>
     <span id="spreadSpark"></span> <span id="fuelType"></span> <span class="plural"></span> forge <span id=
     "allSpark"></span><br>
     Completion Time: <span id="timeSpark"></span> minutes<br>
    </div>
   </div>
  </div>

Codepen

It is triggering your errors because that is part of your function.

More info regarding the input method.

Community
  • 1
  • 1
Chris Happy
  • 7,088
  • 2
  • 22
  • 49
0

In order to auto update calculation, we have to listen to users input on input elements. The easiest approach with minimum changes to existing code is to add input events and emit click on the button:

$("#numMetal, #numForge").on('input', function(){
  $("#submit").click()
})

Better approach is to move calculation logic to separate function and call it on desirable events:

$("#numMetal, #numForge").on('input', function(){
  calculate()
})
 $("#submit").click(function(){
  calculate()
 })

This will keep the code structured and easier to follow.

aBiscuit
  • 4,414
  • 1
  • 17
  • 28
0

Try this:

$( "#numMetal, #numForge" ).keyup(function(event) {
    console.log('a key has been pressed');
    // add code to handle inputs here
});

What happens here is that an event listener - the key up event - is bound to the two inputs you have on your page. When that happens the code inside will be run.

As suggested in other comments it would be a good idea to call a separate method with all the input processing code you have in the submit call, this way you will avoid code duplication.

You will also want to bind events to the checkboxs. This can be achieved with this:

$( "input[name=fuel]" ).on('change',function() {
    console.log('checkbox change');
    // call processing method here
}); 
Tom_B
  • 307
  • 2
  • 8