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)