Home > OS >  Stopwatch in js returns NaN
Stopwatch in js returns NaN

Time:11-07

So I've been doing some setTimeout and SetInterval in JS just to gain more knowledge. I'm currently trying to create the most simple Stopwatch you've ever seen but it returns NaN when I'm using it. Any ideas how to make it work? I just gave up after 90mins. Youtube and W3School did not help. I have tried changing code a little bit, but nothing helped.

var timeOutStopwatch; // global var to stop multiple functions at once

function stopwatch(screenStopwatch, number) {
  screenStopwatch.innerHTML = --number;

  if (number < 0)
    return;
  timeOutStopwatch = setTimeout(function() {
    stopwatch(screenStopwatch, number);
  }, 1000);
};

function stopwatchInterval(screenStopwatch, number) {
  var timeIntervalRef = setInterval(function() {
    if (--number < 0) {
      clearInterval(timeIntervalRef);
      return;
    }

    screenStopwatch.innerHTML = number;
  }, 1000);

  return timeIntervalRef;
};

window.onload = function() {
  var btnStartStopwatch = document.getElementById("turnOn_stopwatch");
  var btnStopStopwatch = document.getElementById("turnOff_stopwatch");

  var screenStopwatch = document.getElementById("stopwatch_screen");

  var timeIntervalRef;

  btnStartStopwatch.onclick = function() {
    var startValue = document.getElementById("start_Value");
    screenStopwatch.innerHTML = startValue.value;
    timeIntervalRef = stopwatchInterval(screenStopwatch, startValue);

  };
  btnStopStopwatch.onclick = function() {
    clearTimeout(timeIntervalRef);
  };
};
* {
  padding: 0;
  margin: 0;
}

body {
  background: linear-gradient( 45deg, #2193b0, #6dd5ed);
  height: 100vh;
}

#container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 800px;
  height: 100px;
  text-align: center;
}

input {
  border-radius: 8px;
}

#start_Value {
  background-color: #252525;
  color: wheat;
  width: 200px;
  height: 20px;
}

#turnOn_stopwatch,
#turnOff_stopwatch {
  background: linear-gradient( 45deg, #cc2b5e, #753a88);
  opacity: 0.7;
  width: 100px;
  color: wheat;
}

#stopwatch_screen {
  position: absolute;
  top: 55%;
  left: 50%;
  font-size: 20px;
  transform: translateX(-50%);
}
<div id="container">
  <input type="text" id="start_Value">
  <input type="button" value="On" id="turnOn_stopwatch">
  <input type="button" value="Off" id="turnOff_stopwatch">
</div>

<div id="stopwatch_screen"></div>

CodePudding user response:

The culprit was the wrong usage of .value, you were passing the html element to stopwatchInterval instead of the actual value:

var startValue = document.getElementById("start_Value");
screenStopwatch.innerHTML = startValue.value;
timeIntervalRef = stopwatchInterval(screenStopwatch, startValue);

Just move .value up to the declaration:

var startValue = document.getElementById("start_Value").value;
screenStopwatch.innerHTML = startValue;
timeIntervalRef = stopwatchInterval(screenStopwatch, startValue);

var timeOutStopwatch; // global var to stop multiple functions at once

function stopwatch(screenStopwatch, number) {
  screenStopwatch.innerHTML = --number;

  if (number < 0)
    return;
  timeOutStopwatch = setTimeout(function() {
    stopwatch(screenStopwatch, number);
  }, 1000);
};

function stopwatchInterval(screenStopwatch, number) {
  var timeIntervalRef = setInterval(function() {
    if (--number < 0) {
      clearInterval(timeIntervalRef);
      return;
    }

    screenStopwatch.innerHTML = number;
  }, 1000);

  return timeIntervalRef;
};

window.onload = function() {
  var btnStartStopwatch = document.getElementById("turnOn_stopwatch");
  var btnStopStopwatch = document.getElementById("turnOff_stopwatch");

  var screenStopwatch = document.getElementById("stopwatch_screen");

  var timeIntervalRef;

  btnStartStopwatch.onclick = function() {
    var startValue = document.getElementById("start_Value").value;
    screenStopwatch.innerHTML = startValue;
    timeIntervalRef = stopwatchInterval(screenStopwatch, startValue);

  };
  btnStopStopwatch.onclick = function() {
    clearTimeout(timeIntervalRef);
  };
};
* {
  padding: 0;
  margin: 0;
}

body {
  background: linear-gradient( 45deg, #2193b0, #6dd5ed);
  height: 100vh;
}

#container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 800px;
  height: 100px;
  text-align: center;
}

input {
  border-radius: 8px;
}

#start_Value {
  background-color: #252525;
  color: wheat;
  width: 200px;
  height: 20px;
}

#turnOn_stopwatch,
#turnOff_stopwatch {
  background: linear-gradient( 45deg, #cc2b5e, #753a88);
  opacity: 0.7;
  width: 100px;
  color: wheat;
}

#stopwatch_screen {
  position: absolute;
  top: 55%;
  left: 50%;
  font-size: 20px;
  transform: translateX(-50%);
}
<div id="container">
  <input type="text" id="start_Value">
  <input type="button" value="On" id="turnOn_stopwatch">
  <input type="button" value="Off" id="turnOff_stopwatch">
</div>

<div id="stopwatch_screen"></div>

CodePudding user response:

Just following on from Bquardi's answer you can simplify your code a little.

  1. Cache the elements up front
  2. Declare the interval outside of the functions so it can be cleared at any point
  3. You probably want your condition to read if (--number <= 0) so that it stops at zero rather than -1.
  4. There's no need to pass in both the HTML and the value to the stopwatch function - just pass in the value because the function already makes the required HTML.
  5. You should check that value exists before calling the function.

const start = document.getElementById('on');
const stop = document.getElementById('off');
const screen = document.getElementById('screen');

let interval;

function stopwatch(number) {
  interval = setInterval(function() {
    if (--number <= 0) clearInterval(interval);
    screen.innerHTML = number;
  }, 1000);
}

start.onclick = function() {
  const value = document.getElementById('value');
  if (value) stopwatch(value);
};

stop.onclick = function() {
  clearTimeout(interval);
};
* {
  padding: 0;
  margin: 0;
}

body {
  background: linear-gradient( 45deg, #2193b0, #6dd5ed);
  height: 100vh;
}

#container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 800px;
  height: 100px;
  text-align: center;
}

input {
  border-radius: 8px;
}

#value {
  background-color: #252525;
  color: wheat;
  width: 200px;
  height: 20px;
}

#on,
#off {
  background: linear-gradient( 45deg, #cc2b5e, #753a88);
  opacity: 0.7;
  width: 100px;
  color: wheat;
}

#screen {
  position: absolute;
  top: 55%;
  left: 50%;
  font-size: 20px;
  transform: translateX(-50%);
}
<div id="container">
  <input type="text" id="value">
  <input type="button" value="On" id="on">
  <input type="button" value="Off" id="off">
</div>

<div id="screen"></div>

  • Related