Last active
April 28, 2022 16:27
-
-
Save joekrump/096b124d5eac4c99717496c3b34a6c93 to your computer and use it in GitHub Desktop.
Timer button - Plain JavaScript and HTML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Timer</title> | |
<style> | |
:root { | |
--text-color: black; | |
--background-color: white; | |
--backdrop-light: 0%; | |
} | |
@media (prefers-color-scheme: dark) { | |
:root { | |
--text-color: white; | |
--background-color: black; | |
--backdrop-light: 100%; | |
} | |
} | |
body { | |
background-color: var(--background-color); | |
} | |
section { | |
display: grid; | |
grid-template-columns: repeat(10, 1fr); | |
gap: 1rem; | |
align-items: center; | |
justify-items: center; | |
} | |
button { | |
padding: 12px 8px; | |
backdrop-filter: blur(40px); | |
background-color: hsl(0 0% var(--backdrop-light) / 50%); | |
border: 1px solid var(--text-color); | |
border-radius: 8px; | |
cursor: pointer; | |
color: var(--text-color); | |
flex-wrap: nowrap; | |
display: flex; | |
justify-content: space-between; | |
} | |
.timer-button .icon { | |
margin-right: 4px; | |
} | |
.time { | |
font-variant-numeric: tabular-nums; | |
} | |
.timer-button { | |
font-size: 2ch; | |
font-weight: 700; | |
} | |
</style> | |
</head> | |
<body> | |
<button class="reset-timers-button">Reset Timers</button> | |
<section> | |
</section> | |
<script> | |
for (let i = 0; i < 800; i++) { | |
document.body.querySelector("section").innerHTML += ` | |
<button class="timer-button"> | |
<span class="icon play">▶️</span> | |
<span class="time" data-seconds="0" data-minutes="0" data-hours="0">00:00:00</span> | |
</button> | |
`; | |
} | |
const timerButtons = document.querySelectorAll("button.timer-button"); | |
const resetTimersButton = document.querySelector(".reset-timers-button"); | |
let isTimerTicking; | |
let intervalId; | |
resetTimersButton.addEventListener("click", (_e) => resetTime()); | |
for (const timerButton of timerButtons) { | |
timerButton.addEventListener("click", () => { | |
isTimerTicking = timerButtons.item(0).querySelector(".icon").classList.contains("pause"); | |
if (isTimerTicking) { | |
clearInterval(intervalId); | |
window.dispatchEvent(new CustomEvent("pause:time")); | |
} else { | |
for (const timerButton of timerButtons) { | |
updateButtonIcon(timerButton.querySelector(".icon"), "⏸"); | |
} | |
intervalId = dispatchTickEvent(timerButton.querySelector(".time"), 1000); | |
} | |
}); | |
} | |
window.addEventListener("tick:time", ({ detail: time }) => { | |
const buttons = document.querySelectorAll("button.timer-button"); | |
const firstButton = buttons.item(0); | |
for (const button of buttons) { | |
updateButtonTime(button.querySelector(".time"), time); | |
} | |
}); | |
window.addEventListener("pause:time", (_e) => { | |
const buttons = document.querySelectorAll("button.timer-button"); | |
for (const button of buttons) { | |
updateButtonIcon(button.querySelector(".icon"), "▶️"); | |
} | |
}); | |
function updateButtonIcon(iconElement, content) { | |
updateButtonIconClass(iconElement); | |
updateButtonIconContent(iconElement, content); | |
} | |
function dispatchTickEvent(timeElement, intervalMilliSeconds) { | |
return setInterval(() => { | |
window.dispatchEvent(new CustomEvent("tick:time", { | |
detail: getCurrentButtonTime(timeElement) | |
})); | |
}, intervalMilliSeconds); | |
} | |
function getCurrentButtonTime(buttonTimeElement) { | |
return { | |
seconds: parseInt(buttonTimeElement.dataset.seconds, 10), | |
minutes: parseInt(buttonTimeElement.dataset.minutes, 10), | |
hours: parseInt(buttonTimeElement.dataset.hours, 10), | |
}; | |
} | |
function updateButtonTime(buttonTimeElement, newTime) { | |
setTime(buttonTimeElement, incrementTime(newTime.seconds, newTime.minutes, newTime.hours)) | |
} | |
function updateButtonIconClass(iconElement) { | |
iconElement.classList.toggle("pause"); | |
iconElement.classList.toggle("play"); | |
} | |
function updateButtonIconContent(iconElement, content) { | |
iconElement.innerHTML = content; | |
} | |
function setTime(timeElement, { seconds, minutes, hours }) { | |
timeElement.setAttribute("data-seconds", seconds); | |
timeElement.setAttribute("data-minutes", minutes); | |
timeElement.setAttribute("data-hours", hours); | |
timeElement.innerHTML = getFormattedTime({ hours, minutes, seconds }); | |
} | |
function resetTime() { | |
const buttonTimeElements = document.querySelectorAll("button.timer-button .time"); | |
for (const timeElement of buttonTimeElements) { | |
setTime(timeElement, { seconds: 0, minutes: 0, hours: 0 }); | |
} | |
} | |
function incrementTime(seconds = 0, minutes = 0, hours = 0) { | |
if (seconds === 59) { | |
seconds = 0; | |
minutes++; | |
} else { | |
seconds++; | |
} | |
if (minutes === 59) { | |
minutes = 0; | |
hours++; | |
} | |
return { | |
seconds, | |
minutes, | |
hours | |
}; | |
} | |
function getFormattedTime({ hours, minutes, seconds }) { | |
let formattedSeconds = seconds; | |
let formattedMinutes = minutes; | |
let formattedHours = hours; | |
if (seconds < 10) { | |
formattedSeconds = `0${seconds}`; | |
} | |
if (minutes < 10) { | |
formattedMinutes = `0${minutes}`; | |
} | |
if (hours < 10) { | |
formattedHours = `0${hours}`; | |
} | |
return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment