Archie
Archie

Reputation: 86

Fix the 'pause' bug in stopwatch

I'm trying to make a very simple stopwatch, but I cannot make 'pause' works properly. It should pause the stopwatch and after clicking 'START' again - proceed the timer. But it just stopps and resets the timer

var body = document.body;

var start = document.querySelector('.start');
var stop = document.querySelector('.stop');
var reset = document.querySelector('.reset');
var lap = document.querySelector('.lap');

var lapContainer = document.querySelector('.lapContainer');

var mil = document.querySelector('.milis');
var sec = document.querySelector('.secs');
var min = document.querySelector('.mins');
var hours = document.querySelector('.hours');
var flag = false;


// Create blocks for time markers
function createTimeSection(timeType) { // timeType = min/sec/ms/ :
  var lapTime = document.createElement('div');
  lapTime.classList.add('lapSection');
  lapBlock.appendChild(lapTime);
  lapTime.innerHTML = (timeType);
}

function createTimeBlock(type) {
  lapBlock = document.createElement('div');
  lapBlock.classList.add('lapBlock');
  lapContainer.appendChild(lapBlock);
  var lapText = document.createElement('div');

  lapText.classList.add('lapText');
  lapBlock.appendChild(lapText);
  lapText.innerHTML = (type);

  createTimeSection(hours);
  createTimeSection(':');
  createTimeSection(minutes);
  createTimeSection(':');
  createTimeSection(seconds);
  createTimeSection(':');
  createTimeSection(milliseconds);
}

// hide/display START/STOP buttons
function displayStopButton() {
  start.style.display = 'none';
  stop.style.display = 'block';
}

function displayStartButton() {
  start.style.display = 'block';
  stop.style.display = 'none';
}


// Get Date start point
function startStopwatch() {
  flag = true;
  initialDate = new Date;
}


// calculate timer
function getTime() {

  var currentDate = new Date;
  timer = new Date (currentDate - initialDate);
  
  milliseconds = timer.getMilliseconds();
  seconds = timer.getSeconds();
  minutes = timer.getMinutes();
  hours = timer.getUTCHours();

  if(milliseconds < 100){
    milliseconds = '0' + milliseconds;
  }
  if(seconds < 10){
    seconds = '0' + seconds;
  }
  if (minutes < 10){
    minutes = '0' + minutes;
  }
  if (hours < 10){
    hours = '0' + hours;
  }
}

// display timer in document
function counter() {
  getTime();
  mil.innerHTML = milliseconds;
  sec.innerHTML = seconds;
  min.innerHTML = minutes;
  hours.innerHTML = hours;
}

// interval for display
function displayTimer() {
  timerId = setInterval(counter, 10);
}


function stopTimer() {
  clearInterval(timerId);
  getTime();
  createTimeBlock('STOP');
  flag = false;
}

function newLap() {
  if (flag == true){
    getTime();
    createTimeBlock('LAP');
  } else {
    lapBlock = document.createElement('div');
    lapBlock.classList.add('lapBlock');
    lapContainer.appendChild(lapBlock);
    var lapText = document.createElement('div');

    lapText.classList.add('lapText');
    lapBlock.appendChild(lapText);
    lapText.innerHTML = ('PRESS START FIRST');
  }
}


function resetTimer() {
  flag = false;
  clearInterval(timerId);
  start.style.display = 'block';
  stop.style.display = 'none';
  mil.innerHTML = '00';
  min.innerHTML = '00';
  sec.innerHTML = '00';
  document.querySelector('.lapContainer').innerHTML = '';
}

start.addEventListener('click', startStopwatch);
start.addEventListener('click', displayStopButton);
start.addEventListener('click', displayTimer);

lap.addEventListener('click', newLap)

stop.addEventListener('click', stopTimer)
stop.addEventListener('click', displayStartButton);

reset.addEventListener('click', resetTimer);
.top-block{
	position: fixed;
	left: 150px;
}

.sw{
	float: left;
	width: 100px;
	height: 30px;
	border: 1px solid black;
	margin: 10px;
	text-align: center;
}

.buttons-block{
	clear: both;
}

.button{
	margin: 10px;
	float: left;
	display: block;
	width: 100px;
	height: 30px;
	color: black;
	font-weight: bold;
	font-size: 20px;
	text-decoration: none;
	text-align: center;
	line-height: 30px;
	border: 1px solid black;
}


.start{
	background: green;
	clear: both;	
}

.stop{
	display: none;
	background: yellow;
}

.reset{
	background: #6b919c;
}

.lap{
	background: rgb(120,120,120);
}

.hours,
.secs,
.mins,
.milis{
	margin: 0;
	line-height: 32px;
}

.lapBlock{
	clear: both;
	height: 30px;
	width: 280px;
}

.lapSection{
	float: left;
	margin: 1px;
}

.lapText{
	float: left;
	margin-right: 5px;
}

.lapContainer{
	float: left;
	margin-top: 15px;
}
	<div class="top-block">
		<div class="sw">
		  <p class="hours">00</p>
		</div>

		<div class="sw">
		  <p class="mins">00</p>
		</div>

		<div class="sw">
		  <p class="secs">00</p>
		</div>

		<div class="sw">
		  <p class="milis">00</p>
		</div>

		<div class="buttons-block">
			<a href="#" class="button start">START</a>
			<a href="#" class="button stop">PAUSE</a>
			<a href="#" class="button lap">LAP</a>
			<a href="#" class="button reset">RESET</a>
		</div>
	</div>
	<div class="lapContainer">
		
	</div>
Or codepen: http://codepen.io/ArkadiyS/pen/XKdLqz

Upvotes: 0

Views: 101

Answers (2)

Barmar
Barmar

Reputation: 780818

You need to distinguish the first click on Start, which should start counting from 0, with subsequent clicks. You can use a variable that's set by the Reset button. In my code this is the first_time variable.

When you pause the stopwatch, you need to save the current time. Then when you restart it, adjust initialDate by the difference in time since it was paused.

// Get Date start point
function startStopwatch() {
  flag = true;
  if (first_time) {
    initialDate = new Date;
    first_time = false;
  } else {
    initialDate.setMilliseconds(initialDate.getMilliseconds() + (new Date - pauseTime));
  }
}  

var body = document.body;

var start = document.querySelector('.start');
var stop = document.querySelector('.stop');
var reset = document.querySelector('.reset');
var lap = document.querySelector('.lap');

var lapContainer = document.querySelector('.lapContainer');

var mil = document.querySelector('.milis');
var sec = document.querySelector('.secs');
var min = document.querySelector('.mins');
var hours = document.querySelector('.hours');
var flag = false;
var first_time = true;

// Create blocks for time markers
function createTimeSection(timeType) { // timeType = min/sec/ms/ :
  var lapTime = document.createElement('div');
  lapTime.classList.add('lapSection');
  lapBlock.appendChild(lapTime);
  lapTime.innerHTML = (timeType);
}

function createTimeBlock(type) {
  lapBlock = document.createElement('div');
  lapBlock.classList.add('lapBlock');
  lapContainer.appendChild(lapBlock);
  var lapText = document.createElement('div');

  lapText.classList.add('lapText');
  lapBlock.appendChild(lapText);
  lapText.innerHTML = (type);

  createTimeSection(hours);
  createTimeSection(':');
  createTimeSection(minutes);
  createTimeSection(':');
  createTimeSection(seconds);
  createTimeSection(':');
  createTimeSection(milliseconds);
}

// hide/display START/STOP buttons
function displayStopButton() {
  start.style.display = 'none';
  stop.style.display = 'block';
}

function displayStartButton() {
  start.style.display = 'block';
  stop.style.display = 'none';
}


// Get Date start point
function startStopwatch() {
  flag = true;
  if (first_time) {
    initialDate = new Date;
    first_time = false;
  } else {
    initialDate.setMilliseconds(initialDate.getMilliseconds() + (new Date - pauseTime));
  }
}  


// calculate timer
function getTime() {

  var currentDate = new Date;
  timer = new Date (currentDate - initialDate);
  
  milliseconds = timer.getMilliseconds();
  seconds = timer.getSeconds();
  minutes = timer.getMinutes();
  hours = timer.getUTCHours();

  if(milliseconds < 100){
    milliseconds = '0' + milliseconds;
  }
  if(seconds < 10){
    seconds = '0' + seconds;
  }
  if (minutes < 10){
    minutes = '0' + minutes;
  }
  if (hours < 10){
    hours = '0' + hours;
  }
}

// display timer in document
function counter() {
  getTime();
  mil.innerHTML = milliseconds;
  sec.innerHTML = seconds;
  min.innerHTML = minutes;
  hours.innerHTML = hours;
}

// interval for display
function displayTimer() {
  timerId = setInterval(counter, 10);
}


function stopTimer() {
  clearInterval(timerId);
  getTime();
  createTimeBlock('STOP');
  flag = false;
  pauseTime = new Date;
}

function newLap() {
  if (flag == true){
    getTime();
    createTimeBlock('LAP');
  } else {
    lapBlock = document.createElement('div');
    lapBlock.classList.add('lapBlock');
    lapContainer.appendChild(lapBlock);
    var lapText = document.createElement('div');

    lapText.classList.add('lapText');
    lapBlock.appendChild(lapText);
    lapText.innerHTML = ('PRESS START FIRST');
  }
}


function resetTimer() {
  flag = false;
  first_time = true;
  clearInterval(timerId);
  start.style.display = 'block';
  stop.style.display = 'none';
  mil.innerHTML = '00';
  min.innerHTML = '00';
  sec.innerHTML = '00';
  document.querySelector('.lapContainer').innerHTML = '';
}

start.addEventListener('click', startStopwatch);
start.addEventListener('click', displayStopButton);
start.addEventListener('click', displayTimer);

lap.addEventListener('click', newLap)

stop.addEventListener('click', stopTimer)
stop.addEventListener('click', displayStartButton);

reset.addEventListener('click', resetTimer);
.top-block{
	position: fixed;
	left: 150px;
}

.sw{
	float: left;
	width: 100px;
	height: 30px;
	border: 1px solid black;
	margin: 10px;
	text-align: center;
}

.buttons-block{
	clear: both;
}

.button{
	margin: 10px;
	float: left;
	display: block;
	width: 100px;
	height: 30px;
	color: black;
	font-weight: bold;
	font-size: 20px;
	text-decoration: none;
	text-align: center;
	line-height: 30px;
	border: 1px solid black;
}


.start{
	background: green;
	clear: both;	
}

.stop{
	display: none;
	background: yellow;
}

.reset{
	background: #6b919c;
}

.lap{
	background: rgb(120,120,120);
}

.hours,
.secs,
.mins,
.milis{
	margin: 0;
	line-height: 32px;
}

.lapBlock{
	clear: both;
	height: 30px;
	width: 280px;
}

.lapSection{
	float: left;
	margin: 1px;
}

.lapText{
	float: left;
	margin-right: 5px;
}

.lapContainer{
	float: left;
	margin-top: 15px;
}
<div class="top-block">
		<div class="sw">
		  <p class="hours">00</p>
		</div>

		<div class="sw">
		  <p class="mins">00</p>
		</div>

		<div class="sw">
		  <p class="secs">00</p>
		</div>

		<div class="sw">
		  <p class="milis">00</p>
		</div>

		<div class="buttons-block">
			<a href="#" class="button start">START</a>
			<a href="#" class="button stop">PAUSE</a>
			<a href="#" class="button lap">LAP</a>
			<a href="#" class="button reset">RESET</a>
		</div>
	</div>
	<div class="lapContainer">
		
	</div>

Another option would be to have separate Start and Resume buttons. The Start button would initialize initialDate, but the Resume button wouldn't. Clicking the Pause button shows the Resume button, while clicking Reset shows the Start button.

Upvotes: 0

nicael
nicael

Reputation: 18995

You should reset date only upon reset of the timer, but you also do it once the timer is paused.

To do this, I've moved the date initialization to the beginning and also applied it on reset.

Also, your timer was continuing to tick even if stopped, to avoid this I'm just counting stop offset and applying it to the date:

setInterval(function(){
  if(flag==false) offset+=10;
},10)

initialDate = new Date;
var body = document.body;

var start = document.querySelector('.start');
var stop = document.querySelector('.stop');
var reset = document.querySelector('.reset');
var lap = document.querySelector('.lap');

var lapContainer = document.querySelector('.lapContainer');

var mil = document.querySelector('.milis');
var sec = document.querySelector('.secs');
var min = document.querySelector('.mins');
var hours = document.querySelector('.hours');
var flag = false;
var waitTimer, offset=0;


// Create blocks for time markers
function createTimeSection(timeType) { // timeType = min/sec/ms/ :
  var lapTime = document.createElement('div');
  lapTime.classList.add('lapSection');
  lapBlock.appendChild(lapTime);
  lapTime.innerHTML = (timeType);
}

function createTimeBlock(type) {
  lapBlock = document.createElement('div');
  lapBlock.classList.add('lapBlock');
  lapContainer.appendChild(lapBlock);
  var lapText = document.createElement('div');

  lapText.classList.add('lapText');
  lapBlock.appendChild(lapText);
  lapText.innerHTML = (type);

  createTimeSection(hours);
  createTimeSection(':');
  createTimeSection(minutes);
  createTimeSection(':');
  createTimeSection(seconds);
  createTimeSection(':');
  createTimeSection(milliseconds);
}

// hide/display START/STOP buttons
function displayStopButton() {
  start.style.display = 'none';
  stop.style.display = 'block';
}

function displayStartButton() {
  start.style.display = 'block';
  stop.style.display = 'none';
}


// Get Date start point
function startStopwatch() {
  flag = true;
  
}
setInterval(function(){
  if(flag==false) offset+=10;
},10)
// calculate timer
function getTime() {

  var currentDate = new Date;
  timer = new Date (currentDate - initialDate - offset);
  
  milliseconds = timer.getMilliseconds();
  seconds = timer.getSeconds();
  minutes = timer.getMinutes();
  hours = timer.getUTCHours();

  if(milliseconds < 100){
    milliseconds = '0' + milliseconds;
  }
  if(seconds < 10){
    seconds = '0' + seconds;
  }
  if (minutes < 10){
    minutes = '0' + minutes;
  }
  if (hours < 10){
    hours = '0' + hours;
  }
}

// display timer in document
function counter() {
  getTime();
  mil.innerHTML = milliseconds;
  sec.innerHTML = seconds;
  min.innerHTML = minutes;
  hours.innerHTML = hours;
}

// interval for display
function displayTimer() {
  timerId = setInterval(counter, 10);
}


function stopTimer() {
  clearInterval(timerId);
  getTime();
  createTimeBlock('STOP');
  flag = false;
}

function newLap() {
  if (flag == true){
    getTime();
    createTimeBlock('LAP');
  } else {
    lapBlock = document.createElement('div');
    lapBlock.classList.add('lapBlock');
    lapContainer.appendChild(lapBlock);
    var lapText = document.createElement('div');

    lapText.classList.add('lapText');
    lapBlock.appendChild(lapText);
    lapText.innerHTML = ('PRESS START FIRST');
  }
}


function resetTimer() {
  initialDate = new Date;
  flag = false;
  offset=0;
  clearInterval(timerId);
  start.style.display = 'block';
  stop.style.display = 'none';
  mil.innerHTML = '00';
  min.innerHTML = '00';
  sec.innerHTML = '00';
  document.querySelector('.lapContainer').innerHTML = '';
}

start.addEventListener('click', startStopwatch);
start.addEventListener('click', displayStopButton);
start.addEventListener('click', displayTimer);

lap.addEventListener('click', newLap)

stop.addEventListener('click', stopTimer)
stop.addEventListener('click', displayStartButton);

reset.addEventListener('click', resetTimer);
.top-block{
	position: fixed;
	left: 150px;
}

.sw{
	float: left;
	width: 100px;
	height: 30px;
	border: 1px solid black;
	margin: 10px;
	text-align: center;
}

.buttons-block{
	clear: both;
}

.button{
	margin: 10px;
	float: left;
	display: block;
	width: 100px;
	height: 30px;
	color: black;
	font-weight: bold;
	font-size: 20px;
	text-decoration: none;
	text-align: center;
	line-height: 30px;
	border: 1px solid black;
}


.start{
	background: green;
	clear: both;	
}

.stop{
	display: none;
	background: yellow;
}

.reset{
	background: #6b919c;
}

.lap{
	background: rgb(120,120,120);
}

.hours,
.secs,
.mins,
.milis{
	margin: 0;
	line-height: 32px;
}

.lapBlock{
	clear: both;
	height: 30px;
	width: 280px;
}

.lapSection{
	float: left;
	margin: 1px;
}

.lapText{
	float: left;
	margin-right: 5px;
}

.lapContainer{
	float: left;
	margin-top: 15px;
}
<div class="top-block">
		<div class="sw">
		  <p class="hours">00</p>
		</div>

		<div class="sw">
		  <p class="mins">00</p>
		</div>

		<div class="sw">
		  <p class="secs">00</p>
		</div>

		<div class="sw">
		  <p class="milis">00</p>
		</div>

		<div class="buttons-block">
			<a href="#" class="button start">START</a>
			<a href="#" class="button stop">PAUSE</a>
			<a href="#" class="button lap">LAP</a>
			<a href="#" class="button reset">RESET</a>
		</div>
	</div>
	<div class="lapContainer">
		
	</div>

Upvotes: 1

Related Questions