Here is my JS fiddle:
https://jsfiddle.net/apasric4/xkzwqr1m/1/
My program is supposed to start a countdown timer that calculates the time remaining in days, hours, seconds, etc from today till the the date that the user picks in the input field.
While the program updates the HTML with the correct time remaining, the problem starts when I try to update countdown timer every second. It returns back NaN values for some reason. Why is that??
Here's my JS:
const input = document.querySelector('input')
let timeInterval;
let timeStop;
input.addEventListener('change', (e) => {
e.preventDefault()
timeStop = true;
endTime = Date.parse(e.target.value)
updateHTML(endTime)
})
function updateHTML(endTime) {
let time = calculateTimeDiff(endTime)
if (time.total <= 0) {
timeStop = false;
}
for (let pro in time) {
let el = document.querySelector(`.${pro}`)
if (el) {
el.innerHTML = time[pro];
}
}
updateCounter();
}
function updateCounter () {
if (timeStop) {
timeInterval = setInterval(updateHTML, 1000);
} else {
clearInterval(timeInterval);
}
}
//returning time remaining till date in object form
function calculateTimeDiff(endTime) {
let start = Date.now();
let end = endTime;
let t = (end-start);
let seconds = Math.floor((t / 1000) % 60);
let minutes = Math.floor((t / 1000 / 60) % 60);
let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
let days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
total: t,
days: days,
hours: hours,
minutes: minutes,
seconds: seconds
}
}
When update goes from event - all is fine
But later you use timeInterval=setInterval(updateHTML, 1000)
- and updateHTML
gets executed without parameter . Use real date instead and it will work
Working example:
const input = document.querySelector('input') let timeInterval; let timeStop; let savedTime; input.addEventListener('change', (e) => { e.preventDefault() timeStop = true; endTime = Date.parse(e.target.value) updateHTML(endTime) }) function updateHTML(endTime) { savedTime = endTime || savedTime; let time = calculateTimeDiff(savedTime) if (time.total <= 0) { timeStop = false } for (let pro in time) { let el = document.querySelector(`.${pro}`) if (el) { el.innerHTML = time[pro] } } updateCounter() } function updateCounter() { if (timeStop) { timeInterval = setInterval(updateHTML, 1000) } else { clearInterval(timeInterval) } } //returning time remaining till date in object form function calculateTimeDiff(endTime) { let start = Date.now() let end = endTime let t = (end - start) let seconds = Math.floor((t / 1000) % 60); let minutes = Math.floor((t / 1000 / 60) % 60); let hours = Math.floor((t / (1000 * 60 * 60)) % 24); let days = Math.floor(t / (1000 * 60 * 60 * 24)); return { total: t, days: days, hours: hours, minutes: minutes, seconds: seconds } }
.time { display: inline-block; border-radius: 25%; }
<,DOCTYPE html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width. initial-scale=1"> <link rel="stylesheet" href="styles.css"> </head> <body> <input type="date" name="endDate"> <div class="clock"> <div class="time"><span class="days">0</span> Days</div> <div class="time"><span class="hours">0</span> Hours</div> <div class="time"><span class="minutes">0</span> Minutes</div> <div class="time"><span class="seconds">0</span> Seconds</div> </div> </body> <script src="app.js"></script> </html>
So your code works fine but your problem is with your endTime
. In your setInterval
, you are calling updateHTML
without the parameter endTime
so that causes an error as it doesn't have a reference for the param.
You can either simply update your updateCounter
function to accept this as a parameter and pass it to your setInterval
function:
function updateCounter (endTime) {
if (timeStop) {
timeInterval=setInterval(() => updateHTML(endTime), 1000)
} else {
clearInterval(timeInterval)
}
}
and then call updateCounter
with the endTime
at the bottom of your updateHtml
function.
Or, remove endTime
as a parameter from updateHtml
and make it a global variable:
const input=document.querySelector('input')
let timeInterval;
let timeStop;
let endTime;
input.addEventListener('change', (e)=> {
e.preventDefault()
timeStop=true;
endTime=Date.parse(e.target.value)
updateHTML()
})
function updateHTML () {
let time=calculateTimeDiff(endTime)
if (time.total<=0) {
timeStop=false
}
for (let pro in time) {
let el=document.querySelector(`.${pro}`)
if (el) {
el.innerHTML=time[pro]
}
}
updateCounter()
}
etc...
try this....
const input=document.querySelector('input')
let timeInterval;
let timeStop;
let endTime;
input.addEventListener('change', (e)=> {
e.preventDefault()
timeStop=true;
endTime=Date.parse(e.target.value)
updateHTML()
})
function updateHTML () {
let time=calculateTimeDiff()
if (time.total<=0) {
timeStop=false
}
for (let pro in time) {
let el=document.querySelector(`.${pro}`)
if (el) {
el.innerHTML=time[pro]
}
}
updateCounter()
}
function updateCounter () {
if (timeStop) {
timeInterval=setInterval(updateHTML(), 1000)
} else {
clearInterval(timeInterval)
}
}
//returning time remaining till date in object form
function calculateTimeDiff () {
let start=Date.now()
let end=endTime
let t=(end-start)
let seconds = Math.floor((t / 1000) % 60);
let minutes = Math.floor((t / 1000 / 60) % 60);
let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
let days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
total: t,
days: days,
hours: hours,
minutes: minutes,
seconds: seconds
}
}
Just add preventDefault() in function updateCounter() in your code. Hope it will work. I tried and it worked successfully.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.