Stopwatch

by Laurens Maneschijn

HTML

<div>
	<button class="reset">reset</button>
	<button class="stop">stop</button>
	<button class="start">start</button>
	<button class="restart">(re)start</button>
	<button class="mark">mark</button>
	<br>
	scale:
	<input id="scale"  type="number" value="0.010" min="0.001" max="1.000" step="0.001">
	<input id="scaler" type="range"  value="0.010" min="0.001" max="1.000" step="0.001">
</div>
<div id="main">
</div>
<pre id="log">
</pre>

CSS

input{
	vertical-align: middle;
}
#scale{width: 5em;}

#main, #log {
	border: 1px solid black;
	margin: 2px;
	padding: 2px;
	height: 40%;
	overflow: auto;
	font-size: 10px;
	font-family: monospace;
	line-height: 1;
}
.lines {
	display: block;
	display: table;
}
.line {
	display: block;
	display: table-row;
}
.cell {
	display: table-cell;
	padding: 2px;
}
.bars {
/*
	display: inline-block;
*/
}
.bar {
	display: inline-block;
	vertical-align: top;
	height: 10px;
	overflow: hidden;
	background: #ddd;
	border: 1px dotted #aaa;
	margin: 1px;
}
.bar:hover {
	background: #ddf;
	border-color: #00f;
}

.time, .name {
/*
	display: inline-block;
	vertical-align: top;
	height: 10px;
	text-align: right;
	padding:2px;
*/
}
.time, .name {
	width: 40px;
}

JavaScript

$(document).on('click', '.reset', function(e){
	reset();
});
$(document).on('click', '.stop', function(e){
	stop();
});
$(document).on('click', '.start', function(e){
	start();
});
$(document).on('click', '.restart', function(e){
	restart();
});
$(document).on('click', '.mark', function(e){
	mark();
});
$(document).on('change drag mousemove', '#scaler', function(e){
	$('#scale').val( $('#scaler').val() );
});
$(document).on('change keyup mouseup mousewheel', '#scale', function(e){
	$('#scaler').val( $('#scale').val() );
});

var data = {};
function reset(){
	data.start = getTimeStampInMs();
	data.steps = [];
	draw();
}
reset();
draw();
function stop(){
	if(data.running){
		addStep();
	}
	data.running = false;
	draw();
	loopStop();
}
function start(){
	data.running = true;
	draw();
	loopStart();
}
function restart(){
	reset();
	start();
}
function mark(){
	if(!data.running){return;}
	addStep();
	console.log('mark', getLastStep());
	draw();
}

function newStep(){
	var step = {};
	step.id = data.steps.length;
	step.timestamp = getTimeStampInMs();
	step.total = step.timestamp - data.start;
	step.last = data.steps.length ? 
		step.timestamp - data.steps[data.steps.length - 1].timestamp
		:
		step.timestamp - data.start;
	// to prevent values like: 1897.0048828125 or 3608.9951171875:
	step.total = Math.round(step.total);
	step.last = Math.round(step.last);
	return step;
}
function addStep(){
	data.steps.push(newStep());
}
function popStep(){
	if(!data.steps.length){
		return;
	}
	var step = data.steps.pop();
	return step;
}
function getLastStep(){
	if(!data.steps.length){
		return null;
	}
	return data.steps[data.steps.length - 1];
}
function getTotalTime(){
	if(!data.steps.length){
		return 0;
	}
	var total = getLastStep().timestamp - data.start;
	return Math.round(total);
}
function getLastTime(){
	if(!data.steps.length){
		return 0;
	}
	return getLastStep().last;
}

function getTimeStampInMs(){
	//...