Timmer
Vanilla JS
by wuct
HTML
<h1 id="time"></h1>
<button id="start">
start
</button>
<button id="stop">
stop
</button>
CSS
button {
width: 96px;
height: 32px;
}
JavaScript
const timeDiv = document.querySelector('#time')
const startBtn = document.querySelector('#start')
const stopBtn = document.querySelector('#stop')
const divMod = (x, y) => [Math.floor(x / y), x % y]
const updateTime = (t) => {
const [remSec, ms] = divMod(t, 1000)
const [min, sec] = divMod(remSec, 60)
timeDiv.textContent = `${min}m ${String(sec).padStart(2, "0")}s ${String(ms).padStart(3, "0")}ms`
}
const updateButtons = status => {
startBtn.disabled = status === 'running'
stopBtn.disabled = status === 'stop'
stopBtn.textContent = status === 'running' ? 'pause' : 'reset'
}
let state = {}
const setState = nextState => {
state = Object.assign(state, nextState)
updateTime(state.diff)
updateButtons(state.status)
const json = JSON.stringify(state)
localStorage.setItem('timmer-state', json)
}
const getInitialState = () => {
const json = localStorage.getItem('timmer-state')
if (json) {
return JSON.parse(json)
} else {
return {
status: 'stop', // running, pause
startTime: null,
diff: 0,
}
}
}
const startTimmer = () => {
const { status, startTime } = state
if (status !== 'running') return
const diff = Date.now() - startTime
setState({ diff })
window.requestAnimationFrame(startTimmer)
}
const handleStart = () => {
const { status, startTime } = state
if (status === 'running') return
if (status === 'stop') {
setState({ status: 'running', startTime: Date.now(), diff: 0 })
} else if (status === 'pause'){
setState({ status: 'running' })
}
startTimmer()
}
const handleStop = () => {
const { status, startTime } = state
if (status === 'stop') return
if (status === 'pause') {
setState({ status: 'stop', startTime: null, diff: 0 })
} else if (status === 'running'){
setState({ status: 'pause' })
}
}
setState(getInitialState())
startTimmer()
stopBtn.addEventListener('click', handleStop)
startBtn.addEventListener('click', handleStart)