I have a page with multiple .countdown-element
divs which I want to contain a countdown.
I am iterating through each .countdown-element
and attempting to apply a countdown timer to each of them.
The $(this).html()
parts in the setInterval
do not trigger. I assume this is related to using .each
and it’s going through the other .countdown-element
divs before it can run.
How can I get the countdown to be applied to each of the .countdown-element
divs?
$( '.countdown-element' ).each( function() {
// Set the date we're counting down to
var countDownDate = new Date( $(this).attr('data-countdown-to') ).getTime();
console.log( 'test: ' + countDownDate );
// Update the count down every 1 second
var x = setInterval(function() {
// Get today's date and time
var now = new Date().getTime();
// Find the distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="demo"
$(this).html( days + "d " + hours + "h " + minutes + "m " + seconds + "s " );
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
$(this).html( 'EXPIRED' );
}
}, 1000);
});
Div markup is (note the data attribute here is dynamic from PHP hence why I need to apply it as an attribute and use that from the JS):
<div class="countdown-element" data-countdown-to="2021-02-10 12:00"></div>'
Advertisement
Answer
The this
inside the setInterval
is callback is not the same this
as inside the .each
Take a copy of this
inside the .each
and use that, eg:
$( '.countdown-element' ).each( function() {
var countdownElement = $(this);
var timer = setInterval(function() {
// ...
countdownElement.html(days + "d " + hours + "h " + minutes + "m " + seconds + "s ");
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(timer);
countdownElement.html('EXPIRED');
}
}, 1000);
});
Alternatively, depending on your browser, use =>
to preserve this
into the callback
var i = 1;
$("div").each(function() {
// => arrow function preserves `this` from outer
var timer = setInterval(() => {
$(this).html(timer + "," + i)
// just a method to break out
if (i++>20) clearInterval(timer);
}, 100);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div></div>
<div></div>
<div></div>