JSFiddle - React, Tailwind, and code Playground
HTML
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
<div class="container">
<h1>
<i class="fa fa-clock-o"></i>
<span class="js-date"></span>
<small class="js-ms"></small>
</h1>
<div>
<button class="btn btn-primary js-start">
<i class="fa fa-play"></i>
start
</button>
<button class="btn btn-danger js-stop">
<i class="fa fa-pause"></i>
stop
</button>
</div>
<form class="form-horizontal" role="form">
<div class="form-group">
<div class="col-xs-6">
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-history"></i>
</div>
<select class="form-control" name="dir" id="dir">
<option value="fwd">foward</option>
<option value="bwd">backward</option>
</select>
</div>
</div>
<div class="col-xs-6">
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-flask"></i>
</div>
<select class="form-control" name="mod" id="mod">
<option value="std">normal</option>
<option value="fst">fast</option>
<option value="slw">slow</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<div class="col-xs-10">
<input class="form-control text-center js-usrtime" type="time" value="01:00"/>
</div>
<div class="col-xs-2">
<button class="js-settime btn btn-default btn-block">Set</button>
</div>
</div>
</form>
</div>
JavaScript
var dirStrategies = {
fwd: function(a, b) {
return a + b;
},
bwd: function(a, b) {
return a - b;
}
};
var modStrategies = {
std: function(val) {
return val;
},
fst: function(val) {
return val * 4;
},
slw: function(val) {
return val * 0.25;
}
};
var ms = 0,
ticker = null,
date = new Date('0'),
dir = dirStrategies.fwd,
mod = modStrategies.std,
now = Date.now();
running = false;
function tick() {
ms = Date.now() - now;
now = Date.now();
if (running) {
date.setTime(dir(date.getTime(), mod(ms)));
render();
}
}
function render() {
document
.querySelector('.js-ms')
.innerText = date.getMilliseconds().toString();
document
.querySelector('.js-date')
.innerText = date.toTimeString().substr(0, 8);
}
function start(event) {
running = true;
}
function stop(event) {
running = false;
}
function changeDir(event) {
dir = dirStrategies[event.currentTarget.value];
}
function changeMod(event) {
mod = modStrategies[event.currentTarget.value];
}
function setTime(event) {
event.preventDefault();
time = document.querySelector('.js-usrtime').value;
date = new Date('0001-01-01 ' + time);
render();
}
document
.querySelector('#dir')
.addEventListener('change', changeDir);
document
.querySelector('#mod')
.addEventListener('change', changeMod);
document
.querySelector('.js-start')
.addEventListener('click', start);
document
.querySelector('.js-stop')
.addEventListener('click', stop);
document
.querySelector('.js-settime')
.addEventListener('click', setTime);
setInterval(tick, 10);
render();