<h1>Countdown Timer</h1>
<section id="timer-input">
<form action="javascript:void(0);" id="timer-form" onsubmit="setTimer()">
<input type="text" id="hours" placeholder="HH" aria-label="hours"/>
<input type="text" id="minutes" placeholder="MM" aria-label="minutes"/>
<input type="text" id="seconds" placeholder="SS" aria-label="seconds"/>
<button type="submit">Start</button>
</form>
</section>
<section id="timer-display" hidden>
<div class="d-flex">
<div class="d-inline timer" id="countdown">
</div>
<div class="d-inline">
<button onclick="pause(event)">Pause</button>
<button onclick="reset()">Reset</Reset>
</div>
</div>
</section>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 80vh;
width: 100%;
}
section {
margin: 1rem;
paddin: 0.5rem;
}
input {
text-align: center;
padding: 0.6rem;
margin: 0.5rem;
width: 3rem;
}
button {
background: transparent;
padding: 0.8rem;
margin: 0.5rem;
min-width: 4rem;
}
button:hover {
background: #eee;
cursor: pointer;
}
.d-inline {
display: inline-block;
}
.countdown {
font-size: 2rem;
padding: 0.5rem;
}
.timer {
margin: 2rem;
}
.d-flex {
display: flex;
align-items: center;
}
/*
* https://frontendeval.com/questions/countdown-timer
*
* Create a countdown timer that notifies the user
*/
let duration;
let countdown;
let paused = false;
function getPerms() {
if (Notification.permission !== "denied") {
// We need to ask the user for permission
Notification.requestPermission().then((permission) => {
// If the user accepts, let's create a notification
if (permission === "granted") {
const notification = new Notification("Your timer notification will be shown here");
}
});
}
}
getPerms();
function setTimer(event) {
const hours = document.getElementById("hours").value;
const mins = document.getElementById("minutes").value;
const secs = document.getElementById("seconds").value;
let hh = parseInt(hours ? hours : 0);
let mm = parseInt(mins ? mins : 0);
let ss = parseInt(secs ? secs : 0);
//convert to milliseconds
duration = (ss + (mm * 60) + (hh * 60 * 60)) * 1000;
// console.log(duration, hh, mm, ss);
if(!duration) return;
startTimer();
displayTimer(true);
}
function displayTimer(bool) {
if(bool) renderCountdown();
const timerForm = document.getElementById("timer-input");
timerForm.hidden = bool;
const timerDisplay = document.getElementById("timer-display");
timerDisplay.hidden = !bool;
}
function renderCountdown() {
const div = document.getElementById("countdown");
div.innerHTML = "";
//calculate hours, mins, and secs
let ss = Math.floor(duration / 1000);
let mm = Math.floor(ss / 60);
let hh = Math.floor(mm / 60);
ss = ss%60;
mm = mm%60;
// console.log(duration, ss, mm, hh);
div.appendChild(getSpan(hh, 2));
div.appendChild(getSpan(":", 1));
div.appendChild(getSpan(mm, 2));
div.appendChild(getSpan(":", 1));
div.appendChild(getSpan(ss, 2));
}
function getSpan(val, pad) {
const span = document.createElement("span");
span.classList.add("countdown");
span.innerHTML = val.toString().padStart(pad, '0');
return span;
}
function reset() {
displayTimer(false);
document.getElementById("timer-form").reset();
document.getElementById("countdown").innerHTML = "";
}
function pause(event) {
paused = !paused;
event.target.innerHTML = paused ? "Resume" : "Pause";
}
function notify(message) {
if (!("Notification" in window)) {
// Check if the browser supports notifications
alert(message);
} else if (Notification.permission === "granted") {
// Check whether notification permissions have already been granted;
// if so, create a notification
const notification = new Notification(message);
// …
} else if (Notification.permission !== "denied") {
// We need to ask the user for permission
Notification.requestPermission().then((permission) => {
// If the user accepts, let's create a notification
if (permission === "granted") {
const notification = new Notification(message);
}
});
}
alert(message);
}
function startTimer() {
countdown = setInterval(() => {
if(duration === 0) {
clearInterval(countdown);
reset();
notify("timer has finished");
}
if(!paused) {
duration -= 1000;
renderCountdown();
}
}, 1000)
}
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.