Search code examples
javascripthtmltimerinnerhtml

How do I record multiple time values, one after another


I have an issue with printing 5 different values one after another. My code is supposed to work like this:

The user presses the the start button, the timer begins, then the user presses the stop button, the timer stops and the time that has passed is printed below. The user does that 5 times and each entry below is supposed to have a different time value based on how fast the user was. (e.g. "1. you took 2.3 seconds. 2. you took 1.7 seconds. etc.).

My code seems to print the first time value, but when I couldn't get it to work with the second attempt, I've tried adding if statements to check if the first inner html label is filled, but that didn't work.

Here is my code:

var status = 0; //0:stop 1:running
var time = 0;
var f = 0;
var s = 0;
var t = 0;
var f = 0;
var f2 = 0;

function start() {
  status = 1;
  document.getElementById("startBtn").disabled = true;
  timer();
  if (f = 0) {
    f + 1;
  } else if (f > 0) {
    s + 1;
  }

}

function stop() {
  if (f = 1) {
    document.getElementById("first").innerHTML = time + 1;
    f++;
  }
  if (s = 1) {
    document.getElementById("second").innerHTML = time + 1;
    s++;
  }
  status = 0;
  document.getElementById("startBtn").disabled = false;
}

function reset() {
  status = 0;
  time = 0;
  document.getElementById('timerLabel').innerHTML = '00:00:00';
  document.getElementById("startBtn").disabled = false;
}

function timer() {

  if (status == 1) {
    setTimeout(function() {
      time++;
      var min = Math.floor(time / 100 / 60);
      var sec = Math.floor(time / 100);
      var mSec = time % 100;
      if (min < 10) {
        min = "0" + min;

      }
      if (sec >= 60) {
        sec = sec % 60;
      }
      if (sec < 10) {
        sec = "0" + sec;
      }
      document.getElementById('timerLabel').innerHTML = min + ":" + sec + ":" + mSec;
      timer();
    }, 10);
  }
}
<div class="container">
  <h1 class="title">Stopwatch</h1>
  <h1 id="timerLabel">00:00:00</h1>
  <input type="button" value="START" class="myButton" onClick="start()" id="startBtn">
  <input type="button" value="STOP" class="myButton" onClick="stop()">
  <input type="button" value="RESET" class="myButton" onClick="reset()">
  <h2 id="first">0</h2>
  <h2 id="second">0</h2>
  <h2 id="third">0</h2>
  <h2 id="forth">0</h2>
  <h2 id="fifth">0</h2>

</div>


Solution

  • I see several issues right away.

    • First you have var f = 0 twice.
    • You have f + 1; and s + 1; but those statements don't return anything, you want s++; and f++; or s+=1; and f+=1; if you want the s and f variables to increment.
    • Your if conditions use =, which is for assignment and therefore will always return true, instead of == (equality with conversion) or better yet, === (strict equality).

    Fixing those issues will probably get you up and running.

    But, you've also got too much complication in this solution.

    • First, you should not be using inline HTML event attributes (onclick, etc.) and instead, you should be setting up all your event handling in JavaScript.

    • Next, it seems that you have too many variables for what you are trying to do. There really isn't a need for status as far as I can tell. If you are in the stop function, it's obvious that you are stopped. If you are in the timer function, you must be started. I also don't see the need for the f, s, f2 and t variables or the code that tracks them.

    • You forgot to check mSec for single digits and prepend a 0 in those cases.

    • Only use .innerHTML when the string you are supplying contains HTML that needs to be parsed by the browser. If there is no HTML in the string, the HTML parser will be invoked for no reason and that's a waste of resources. For non-HTML strings, use .textContent.

    • You also don't need to set up empty <h2> placeholders for the results ahead of time. You can create them on the fly so there will be less HTML and less JavaScript to try to test for them and match them.

    • Related to the <h2> comment, you should be using tags because of the semantics they convey, not because of the default formatting the browser applies to them. <h1>is fine for your page title of Stopwatch because that's a heading, but it's incorrect for showing the elapsed time because that's not a section heading. And, to show the various times between clicks, a bullet list is appropriate because you are, well, making a list. Use the right tag for the job, but then use CSS to style anything anyway that you want.

    • And, by separating out the code that creates the 00:00:00 string into its own function, you can call it whenever you need that format created.

    I believe I've accomplished what you want below. See comments for explanations:

    var time = 0;         // Store the elapsed time count
    var timeout = null;   // Will hold a reference to the setTimeout
    var lastTime = null;  // Stores the time count when the stop button was last pressed
    
    // Get all the DOM references you'll be working with, just once
    // and make them available to all the functions so you don't need
    // to keep finding them over and over.
    var btnStart = document.getElementById("startBtn");
    var btnStop = document.getElementById("stopBtn");
    var btnReset = document.getElementById("resetBtn");
    var timerLabel = document.getElementById('timerLabel');
    var results = document.getElementById("results");
    
    // Set up your event handlers in JavaScript, not in HTML
    btnStart.addEventListener("click", start);
    btnStop.addEventListener("click", stop);
    btnReset.addEventListener("click", reset);
    
    function start() {
      btnStart.disabled = true;
      timeout = setTimeout(function(){
        time++;                                           // Increment time count
        timerLabel.textContent = getFormattedTime(time);  // Update counter with formatted time
        start();                                          // Run timer again
      }, 10);
    }
    
    function stop() {
      clearTimeout(timeout);                               // Stop the timer  
      var li = document.createElement("li");               // Create a new <li> element
      li.textContent = getFormattedTime(time - lastTime);  // Set the text for the element
      lastTime = time;                                     // Store the time that the timer stopped  
      results.appendChild(li);                             // Add the <li> to the static <ul>
      btnStart.disabled = false;                           // Disable the start button
    }
    
    function reset(){
      clearTimeout(timeout);                    // Stop the timer  
      time = 0;                                 // Reset the time
      lastTime = 0;                             // Reset the last time
      timerLabel.textContent = '00:00:00';      // Reset the time label
      btnStart.disabled = false;                // Enable the start button
      results.innerHTML = "";                   // Clear out the static <ul>
    }
    
    // This function accepts the time count and retuns it in a 00:00:00 format
    function getFormattedTime(timeVal){
      var min = Math.floor(timeVal/100/60);
      var sec = Math.floor(timeVal/100);
      var mSec = timeVal % 100;
      if(min < 10)  { min = "0" + min; }
      if(sec >= 60) { sec = sec % 60;  }
      if(sec < 10) {
        if(sec === 0) {
          sec = "00";
        } else {
          sec = "0" + sec;
        }
      }
      if(mSec < 10) {
        if(mSec === 0) {
          mSec = "00";
        } else {
          mSec = "0" + mSec;
        }
      }   
      
      return min + ":" + sec + ":" + mSec;
    }
    /* Make elapsed time area stand out */
    #timerLabel {
      font-size:2em;
      font-weight:bold;
      margin-bottom:1em;
      background-color:#ff00ff;
      font-family:Arial, Helvetica, sans-serif;
      display:inline-block;
      padding:15px;
      width:10em;
      text-align:center;
    }
    
    ul { padding:0; }              /* remove default indentation of list */
    li { list-style-type: none; }  /* remove standard bullet discs */
    li::before { content: " - "; } /* place a dash before each list item instead */
    <div class="container">
      <h1 class="title">Stopwatch</h1>
      <div id="timerLabel">00:00:00</div>
      <div>
        <input type="button" value="START" class="button" id="startBtn">
        <input type="button" value="STOP" class="button" id="stopBtn">
        <input type="button" value="RESET" class="button" id="resetBtn">
      </div>
      <ul id="results"></ul>
    </div>