Goal:
Im looping through several .event elements using jQuery's each function. I am calculating a timer countdown using information coming from hidden span elements inside each .event class. I am using setInterval() to recalculate the remaining time every second.
Problem:
All my calculations work perfectly – but only for the last interval. Each interval seems to overwrite the calculation from the one before. Meaning: only the last .event is even getting an output. All previous .event are not even getting any output. Using logs before and after the interval, I was able to narrow my error down to the setInterval function. How can I prevent each interval from overwriting the one before? Or is my error somewhere I did not even think of yet?
Code:
$('.event').each(function() {
$event = $(this);
// SET FUTURE DATE
$futureDate = $event.find($('.event-time'));
$countdownDate = new Date($futureDate.text()).getTime();
setInterval(function() {
// SET TODAYS DATE
$now = new Date().getTime();
// DIFFERENCE NOW AND FUTURE DATE
$diff = $countdownDate - $now;
// TIME CALCULATIONS FOR d, h, m, s
$days = Math.floor($diff / (1000 * 60 * 60 * 24));
$hours = Math.floor(($diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
$minutes = Math.floor(($diff % (1000 * 60 * 60)) / (1000 * 60));
$seconds = Math.floor(($diff % (1000 * 60)) / 1000);
// OUTPUT
$event.find('.clock .val-d').html($days);
$event.find('.clock .val-h').html($hours);
$event.find('.clock .val-m').html($minutes);
$event.find('.clock .val-s').html($seconds);
}, 1000)
});
The setInterval() function is commonly used to set a delay for functions that are executed again and again, such as animations. You can cancel the interval using clearInterval() . If you wish to have your function called once after the specified delay, use setTimeout() .
JavaScript setInterval() method. The setInterval() method in JavaScript is used to repeat a specified function at every given time-interval. It evaluates an expression or calls a function at given intervals. This method continues the calling of function until the window is closed or the clearInterval() method is called ...
The problem is because when the function within your interval runs the loop has finished, so $event
will only ever refer to the last .event
element in the jQuery object.
The simple fix for this, assuming you can use ES6, is to use the let
keyword to define the $event
:
$('.event').each(function() {
let $event = $(this);
// the rest of your code...
});
If you can't use ES6 then you'll need to use a closure to retain the scope of $(this)
:
$('.event').each(function() {
(function($event) {
$futureDate = $event.find($('.event-time'));
$countdownDate = new Date($futureDate.text()).getTime();
setInterval(function() {
$now = new Date().getTime();
$diff = $countdownDate - $now;
// TIME CALCULATIONS FOR d, h, m, s
$days = Math.floor($diff / (1000 * 60 * 60 * 24));
$hours = Math.floor(($diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
$minutes = Math.floor(($diff % (1000 * 60 * 60)) / (1000 * 60));
$seconds = Math.floor(($diff % (1000 * 60)) / 1000);
$event.find('.clock .val-d').html($days);
$event.find('.clock .val-h').html($hours);
$event.find('.clock .val-m').html($minutes);
$event.find('.clock .val-s').html($seconds);
}, 1000)
})($(this));
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With