I'm trying to create multiple countdown timers using jQuery. The problem is that the numbers are not changing. Also, I'm not sure if this is the best way to do it. Any help is appriciated!
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<script>
$(document).ready(function() {
function countDown(id, date) {
var end = new Date(date);
end = (Date.parse(end) / 1000);
var now = new Date();
now = (Date.parse(now) / 1000);
var left = end - now;
var days = Math.floor(left / 86400);
var hours = Math.floor((left - (days * 86400)) / 3600);
var minutes = Math.floor((left - (days * 86400) - (hours * 3600 )) / 60);
var seconds = Math.floor((left - (days * 86400) - (hours * 3600) - (minutes * 60)));
$("#" id).html(days " days, " hours " hours, " minutes " minutes, " seconds " seconds");
}
$(".countdown").each(function() {
var init = setInterval(countDown($(this).attr("id"), $(this).data("date")), 1000);
});
});
</script>
</head>
<body>
<div id="1" data-date="2023-01-06 23:59:59"></div>
<div id="2" data-date="2023-01-07 23:59:59"></div>
<div id="3" data-date="2023-01-08 23:59:59"></div>
</body>
</html>
CodePudding user response:
The problem you have is the way you use setInterval. The code is executing the function and what that function returns is set to the interval.
$(".countdown").each(function(elem) {
var init = setInterval(function() {
countDown($(elem).attr("id"), $(this).data("date"));
}, 1000);
});
Code with some things cleaned up:
$(document).ready(function() {
function countDown(elem, date) {
var end = new Date(date);
end = (Date.parse(end) / 1000);
var now = new Date();
now = (Date.parse(now) / 1000);
var left = end - now;
var days = Math.floor(left / 86400);
var hours = Math.floor((left - (days * 86400)) / 3600);
var minutes = Math.floor((left - (days * 86400) - (hours * 3600)) / 60);
var seconds = Math.floor((left - (days * 86400) - (hours * 3600) - (minutes * 60)));
elem.text(days " days, " hours " hours, " minutes " minutes, " seconds " seconds");
}
$(".countdown").each(function() {
const elem = $(this);
var init = setInterval(function() {
countDown(elem, elem.data("date"));
}, 1000);
});
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<div id="1" data-date="2023-01-06 23:59:59"></div>
<div id="2" data-date="2023-01-07 23:59:59"></div>
<div id="3" data-date="2023-01-08 23:59:59"></div>
CodePudding user response:
You may have the setInterval kicks in once only and dispatch an event that you previously chose to listen for on each of the element wrapping a datetime to countdown.
Here in this demo, on document ready it adds an event listener for the tick
event on all the .countdown
elements. The event handler will grab the data-date
attribute value from the event.target
and will replace its text content with the string returned by getTimeLeft(dategrabbed)
.
Next it will call setInterval once, with the callback in charge of dispatching the above defined event tick
to all the interested elements .countdown
so that they will all update their content.
function getTimeLeft(date) {
const now = new Date();
const before = new Date(date);
const left = (now.getTime() - before.getTime()) / 1000;
const days = Math.floor(left / 86400);
const hours = Math.floor((left - (days * 86400)) / 3600);
const minutes = Math.floor((left - (days * 86400) - (hours * 3600)) / 60);
const seconds = Math.floor((left - (days * 86400) - (hours * 3600) - (minutes * 60)));
return `${days} days, ${hours} hours, ${minutes} minutes, ${seconds} seconds`;
}
$(document).ready(()=>{
//listens for the tick event on all .countdown elements
$('.countdown').on('tick', (event)=>{
const startingDate = $(event.target).data("date");
const timeLeft = getTimeLeft(startingDate);
$(event.target).text(timeLeft);
})
//triggers the tick event to all the .countdown elements every second
setInterval(()=>{ $('.countdown').trigger('tick'); }, 1000);
});
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
</head>
<body>
<div id="1" data-date="2023-01-06 23:59:59"></div>
<div id="2" data-date="2023-01-07 23:59:59"></div>
<div id="3" data-date="2023-01-08 23:59:59"></div>
</body>
</html>