I have the following script that is a countdown timer that display the hours, minutes, seconds (00:00:00:00) remaining until reaching a specified date. On my HTML page, I have 4 objects that have the timer. The script works, however the timer is the same across all 4 objects, despite each having unique values that should change the countdown. Forgive me as I'm actually working in Webflow, however hopefully it poses no issue:
<script>
// all the objects with the timer
var wrappers = document.querySelectorAll(".collection-item");
wrappers.forEach(function(wrapper) {
var countDownDate = new Date("July 15, 2023 00:00:00").getTime();
var x = setInterval(function() {
var now = new Date().getTime();
var distance = countDownDate - now;
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);
// update the HTML elements within the current wrapper
wrapper.querySelector("#day").innerHTML = days;
wrapper.querySelector("#hour").innerHTML = hours;
wrapper.querySelector("#minute").innerHTML = minutes;
wrapper.querySelector("#second").innerHTML = seconds;
if (distance < 0) {
clearInterval(x);
carWrapper.querySelector(".announcement").innerHTML = "Yay!";
}
}, 1000);
});
</script>
Each object is part of a collection list in Webflow, seen with the following HTML:
<div role="listitem" class="collection-item w-dyn-item">
<a id="000001" href="/books/000001" target="_blank" class="wrapper w-inline-block">
<h1 class="something">
<span id="day">00</span>
<span id="hour">00</span>
<span id="minute">00</span>
<span id="second">00</span>
</h1>
</a>
<script>
script from above here
</script>
</div>
Not sure what's wrong/how to get each timer to run independently for each object. Again, the timer is counting down properly, but all 4 objects are using the time of the 4th object, instead of their own.
I'm not familiar with webflow but that appears to be a template fragment that gets rendered once for every item.
You only want your javascript to run once since it is updating every .collection-item
, or have it target only the current item.
I would suggest rendering the date value of the item in a data-attribute and include your script once for the entire collection reading each items value from the html.
// all the objects with the timer
var wrappers = document.querySelectorAll(".collection-item");
wrappers.forEach(function(wrapper) {
//get the item's data-date
var countDownDate = new Date(wrapper.querySelector('a').dataset['date']).getTime();
var x = setInterval(function() {
var now = new Date().getTime();
var distance = countDownDate - now;
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);
// update the HTML elements within the current wrapper
wrapper.querySelector("#day").innerHTML = days;
wrapper.querySelector("#hour").innerHTML = hours;
wrapper.querySelector("#minute").innerHTML = minutes;
wrapper.querySelector("#second").innerHTML = seconds;
if (distance < 0) {
clearInterval(x);
carWrapper.querySelector(".announcement").innerHTML = "Yay!";
}
}, 1000);
});
<div role="listitem" class="collection-item w-dyn-item">
<a id="000001" href="/books/000001" target="_blank" class="wrapper w-inline-block" data-date="July 15, 2023 00:00:00">
<h1 class="something">
<span id="day">00</span>
<span id="hour">00</span>
<span id="minute">00</span>
<span id="second">00</span>
</h1>
</a>
</div>
<div role="listitem" class="collection-item w-dyn-item">
<a id="000001" href="/books/000001" target="_blank" class="wrapper w-inline-block" data-date="July 25, 2023 00:00:00">
<h1 class="something">
<span id="day">00</span>
<span id="hour">00</span>
<span id="minute">00</span>
<span id="second">00</span>
</h1>
</a>
</div>
<div role="listitem" class="collection-item w-dyn-item">
<a id="000001" href="/books/000001" target="_blank" class="wrapper w-inline-block" data-date="July 15, 2024 12:30:30">
<h1 class="something">
<span id="day">00</span>
<span id="hour">00</span>
<span id="minute">00</span>
<span id="second">00</span>
</h1>
</a>
</div>
<script>
// "script from above" here only once, it should be safe even when the collection is empty
</script>