Day 23: Timer
Lesson 6: Timer: 7
Like I said at the start of the lesson, there is a better way of actually running a timer application that is more accurate.
Instead of using a 1,000 ms interval to run your timer we do the following:
- Get the time duration from the user input (like we currently do)
- Create a
Date
for when that will be, call itendDate
- Display the number of seconds between
Date.now()
andendDate
- Use an interval with a duration of say 100ms (so a tenth of a second) to update that time difference on the screen
- Each time that interval runs to update the time between
Date.now()
andendDate
also check to see ifDate.now()
is afterendDate
and if it is stop the timer.
This is more accurate and has the benefit that you can save endDate
in LocalStorage in order to make a timer that survives page reloads. This way you can see if there is an active timer running when the page loads.
You have all the skills needed to change what you have made here to what I describe above, see how far you get as a challenge - you will learn a lot!
Here is the full complete source code for what we made today (or you can find it at this GitHub repo)
1<html> 2 <head> 3 <style> 4 body { 5 font-family: "Open Sans", "Helvetica Neue", sans-serif; 6 } 7 8 #container { 9 width: 350px; 10 margin: 50px auto; 11 } 12 13 .center { 14 text-align: center; 15 } 16 17 #timer { 18 font-size: 30px; 19 color: black; 20 font-weight: bold; 21 } 22 23 .flex-row { 24 margin-top: 8px; 25 display: flex; 26 flex-direction: row; 27 justify-content: space-between; 28 column-gap: 8px; 29 } 30 31 .flex-row button { 32 border-radius: 8px; 33 padding: 12px; 34 border: none; 35 color: white; 36 cursor: pointer; 37 flex: 1; 38 } 39 40 #time-input { 41 font-size: 30px; 42 padding: 5px; 43 border-radius: 5px; 44 border: 1px solid gray; 45 width: 100%; 46 } 47 48 #start { 49 background-color: #4cbb17; 50 } 51 52 #start:disabled { 53 background-color: #4bbb1771; 54 } 55 56 #stop { 57 background-color: #ff5733; 58 } 59 60 #stop:disabled { 61 background-color: #ff583377; 62 } 63 64 #reset { 65 background-color: orange; 66 } 67 68 #reset:disabled { 69 background-color: rgba(255, 166, 0, 0.5); 70 } 71 </style> 72 </head> 73 <body> 74 <div id="container" class="center"> 75 <div id="timer"></div> 76 77 <div> 78 <input 79 id="time-input" 80 type="number" 81 placeholder="Enter time in seconds" 82 /> 83 </div> 84 85 <div class="flex-row"> 86 <button onclick="startTimer()" id="start">Start</button> 87 <button onclick="stopTimer()" id="stop" disabled>Stop</button> 88 <button onclick="resetTimer()" id="reset" disabled>Reset</button> 89 </div> 90 </div> 91 <script> 92 const timerElement = document.getElementById("timer"); 93 const timeInputElement = document.getElementById("time-input"); 94 const startButton = document.getElementById("start"); 95 const stopButton = document.getElementById("stop"); 96 const resetButton = document.getElementById("reset"); 97 98 let timerInterval; 99 let timerActive = false; 100 let time = 0; 101 102 function updateTimer() { 103 time--; 104 timerElement.innerHTML = time; 105 106 if (time === 0) { 107 clearInterval(timerInterval); 108 } 109 } 110 111 function startTimer() { 112 console.log("starting timer"); 113 114 if (timerActive) { 115 timerInterval = setInterval(updateTimer, 1000); 116 setButtons("running"); 117 return; 118 } 119 120 time = timeInputElement.value; 121 122 if (time <= 0) { 123 alert("Time must be more than 0!"); 124 return; 125 } 126 127 timerElement.innerHTML = time; 128 129 timerInterval = setInterval(updateTimer, 1000); 130 setButtons("running"); 131 timerActive = true; 132 } 133 134 function stopTimer() { 135 console.log("stopping timer"); 136 clearInterval(timerInterval); 137 setButtons("stopped"); 138 } 139 140 function resetTimer() { 141 console.log("resetting timer"); 142 time = 0; 143 timeInputElement.value = ""; 144 timerElement.innerHTML = time; 145 setButtons("clear"); 146 timerActive = false; 147 } 148 149 function setButtons(state) { 150 if (state === "clear") { 151 startButton.disabled = false; 152 stopButton.disabled = true; 153 resetButton.disabled = true; 154 } 155 if (state === "running") { 156 startButton.disabled = true; 157 stopButton.disabled = false; 158 resetButton.disabled = true; 159 } 160 if (state === "stopped") { 161 startButton.disabled = false; 162 stopButton.disabled = true; 163 resetButton.disabled = false; 164 } 165 } 166 </script> 167 </body> 168</html>