Javascript shipping countdown timer code help

Joined
Feb 25, 2022
Messages
18
Reaction score
1
I am having a issue with some javascript code on a category page, one here is a example https://shop.it-doneright.co.uk/laptops-tablets/Laptops, I am trying to add a javascript shipping countdown timer that says order within x amount of time and it will be delivered on this date so I found some code online at https://medium.com/@tristannothling...r-e-commerce-store-without-using-4eb117165da2 and noticed at first it only worked on the first div element and not the others so I looked it up on Google and found it was due to the script using byID and others said it was better to use class so I changed the code to use class and queryselector but now it's not working, below is the current code I have

Code:
<div class="delivery-text">Super fast delivery available</div>

<script>
                function isHoliday(date) {
  const holidays = [
    new Date(2024, 0, 1), // New Year's Day
    new Date(2024, 3, 7), // Good Friday
    new Date(2024, 3, 10), // Easter Monday
    new Date(2024, 4, 1), // Early May Bank Holiday
    new Date(2024, 4, 8), // King Charles Coronation
    new Date(2024, 4, 29), // Spring Bank Holiday
    new Date(2024, 7, 28), // Summer Bank Holiday
    new Date(2024, 11, 25), // Christmas Day
    new Date(2024, 11, 26), // Boxing Day
  ];

  for (let i = 0; i < holidays.length; i++) {
    if (date.getFullYear() === holidays[i].getFullYear() &&
        date.getMonth() === holidays[i].getMonth() &&
        date.getDate() === holidays[i].getDate()) {
        return true;
    }
  }
  return false;
}
                   
                    function isBusinessDay(date) {
  const dayOfWeek = date.getUTCDay();
  return dayOfWeek > 0 && dayOfWeek < 6;
}
                   
                    function nextBusinessDay(date) {

  let nextDay = new Date(date);
  nextDay.setUTCDate(date.getUTCDate() + 1);

  while (!isBusinessDay(nextDay) || isHoliday(nextDay)) {
    nextDay.setUTCDate(nextDay.getUTCDate() + 1);
  }

  return nextDay;
}
                   
                    function countdownToDispatch() {

  const now = new Date();
  let dispatchDate;

  //If it's before 11AM, a business day, and not a holiday, our dispatch date is today!

  if (now.getUTCHours() < 14 && isBusinessDay(now) && !isHoliday(now)) {
    dispatchDate = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 14, 0, 0, 0);
  } else {
    dispatchDate = nextBusinessDay(now);
    dispatchDate.setUTCHours(14, 0, 0, 0);
  }

  const timeUntilDispatch = dispatchDate.getTime() - now.getTime();
  const days = Math.floor(timeUntilDispatch / (1000 * 60 * 60 * 24));
  const hours = Math.floor((timeUntilDispatch % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  const minutes = Math.floor((timeUntilDispatch % (1000 * 60 * 60)) / (1000 * 60));
  const seconds = Math.floor((timeUntilDispatch % (1000 * 60)) / 1000);

  let timeString = '';

  if (days > 0) {
    timeString += days + ' days ';
  }
  if (hours > 0) {
    timeString += hours + ' hours ';
  }
  if (minutes > 0) {
    timeString += minutes + ' minutes ';
  }
  if (seconds > 0) {
    timeString += seconds + ' seconds ';
  }

  return timeString.trim();
}
 
                    function setOrderArrivalDate() {
  const now = new Date();

  let dispatchDate;
  if (now.getUTCHours() < 14 && isBusinessDay(now) && !isHoliday(now)) {
    dispatchDate = now;
  } else {
    dispatchDate = nextBusinessDay(now);
  }

  const arrivalDate = nextBusinessDay(dispatchDate);
  let result = countdownToDispatch();

  const formattedDate = arrivalDate.toLocaleDateString("en-GB", {
    weekday: 'long',
    day: 'numeric',
    month: 'long'
  });

  const finalArrivalDateString = formattedDate.split(' ')[0] + ' ' + ordinalSuffix(arrivalDate.getUTCDate()) + ' ' + formattedDate.split(' ')[2];
  //const deliveryText = document.getElementById('delivery-text');
const deliveryText = document.getElementsByClassName("delivery-text");
//const deliveryText = document.querySelectorAll('.delivery-text');
  deliveryText.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString;

}
                   
                    function ordinalSuffix(i) {
  const j = i % 10, k = i % 100;
  if (j == 1 && k != 11) {
      return i + "st";
  }
  if (j == 2 && k != 12) {
      return i + "nd";
  }
  if (j == 3 && k != 13) {
      return i + "rd";
  }
  return i + "th";
}
                   
                    setInterval(setOrderArrivalDate, 1000);
                   
                </script>
 
Last edited:
Joined
Jul 4, 2023
Messages
539
Reaction score
70
Use
JavaScript:
const deliveryText = document.getElementsByClassName("delivery-text")[0];
instead
JavaScript:
const deliveryText = document.getElementsByClassName("delivery-text")

The first line includes [0], which accesses the first element in the array-like object returned by getElementsByClassName. Without [0], deliveryText would reference the entire collection of elements rather than a specific one. This can lead to errors if you're trying to manipulate a single element directly, as methods or properties intended for one element won't work on a collection.
 
Joined
Feb 25, 2022
Messages
18
Reaction score
1
Use
JavaScript:
const deliveryText = document.getElementsByClassName("delivery-text")[0];
instead
JavaScript:
const deliveryText = document.getElementsByClassName("delivery-text")

The first line includes [0], which accesses the first element in the array-like object returned by getElementsByClassName. Without [0], deliveryText would reference the entire collection of elements rather than a specific one. This can lead to errors if you're trying to manipulate a single element directly, as methods or properties intended for one element won't work on a collection.
Think that's where the issue is, I am trying to get it to work on every product not just the first product/div element
 
Joined
Jul 4, 2023
Messages
539
Reaction score
70
Okay, I see where the problem is now (multiple elements).

If you want to use an ID for each div element, it must be unique. This is because IDs are meant to uniquely identify a single element in the DOM. Using the same ID for multiple elements can cause conflicts and unexpected behavior, as methods like getElementById will only return the first matching element.

Solution: by ID
HTML:
<div id="delivery-text-1">Super fast delivery available</div>
<div id="delivery-text-2">Super fast delivery available</div>
<div id="delivery-text-3">Super fast delivery available</div>

<script>
    const deliveryTexts = document.querySelectorAll('[id^="delivery-text-"]');
    for (const deliveryText of deliveryTexts)
      deliveryText.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString;
</script>

Solution: by class
HTML:
<div class="delivery-text">Super fast delivery available</div>
<div class="delivery-text">Super fast delivery available</div>
<div class="delivery-text">Super fast delivery available</div>

<script>
    const deliveryTexts = document.getElementsByClassName('delivery-text');
    for (const deliveryText of deliveryTexts)
      deliveryText.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString;
 
    // or
 
    const deliveryTexts = document.querySelectorAll('.delivery-text');
    for (const deliveryText of deliveryTexts)
      deliveryText.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString;  deliveryText.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString;
</script>


BTW,
HTML:
<div class="delivery-text">Super fast delivery available</div>
<div class="delivery-text">Super fast delivery available</div>
<div class="delivery-text">Super fast delivery available</div>

<script>
  [...document.getElementsByClassName('delivery-text')]
  .map((item) => item.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString);
</script>
 
Last edited:
Joined
Feb 25, 2022
Messages
18
Reaction score
1
Okay, I see where the problem is now (multiple elements).

If you want to use an ID for each div element, it must be unique. This is because IDs are meant to uniquely identify a single element in the DOM. Using the same ID for multiple elements can cause conflicts and unexpected behavior, as methods like getElementById will only return the first matching element.

Solution: by ID
HTML:
<div id="delivery-text-1">Super fast delivery available</div>
<div id="delivery-text-2">Super fast delivery available</div>
<div id="delivery-text-3">Super fast delivery available</div>

<script>
    const deliveryTexts = document.querySelectorAll('[id^="delivery-text-"]');
    for (const deliveryText of deliveryTexts2)
      deliveryText.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString;
</script>

Solution: by class
HTML:
<div class="delivery-text">Super fast delivery available</div>
<div class="delivery-text">Super fast delivery available</div>
<div class="delivery-text">Super fast delivery available</div>

<script>
    const deliveryTexts = document.getElementsByClassName('delivery-text');
    for (const deliveryText of deliveryTexts)
      deliveryText.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString;
 
    // or
 
    const deliveryTexts = document.querySelectorAll('.delivery-text');
    for (const deliveryText of deliveryTexts)
      deliveryText.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString;  deliveryText.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString;
</script>


BTW,
HTML:
<div class="delivery-text">Super fast delivery available</div>
<div class="delivery-text">Super fast delivery available</div>
<div class="delivery-text">Super fast delivery available</div>

<script>
  [...document.getElementsByClassName('delivery-text')]
  .map((item) => item.textContent = 'Order within the next ' + result + ' to receive your order on ' + finalArrivalDateString);
</script>
Thank you so much, the solution by class worked perfect. Really appreciate the help and replies and code
 
Joined
Feb 25, 2022
Messages
18
Reaction score
1
Sorry last question, how do I remove the comma after the day, currently it's Tuesday, 24th December. I would like it to be Tuesday 24th December
 
Joined
Jul 4, 2023
Messages
539
Reaction score
70
I can't see this comma in my browser.

1734867600608.png


The comma after the day appears depending on the date format settings of the operating system where the browser is running.

Check this out.
JavaScript:
    const formattedDate = arrivalDate.toLocaleDateString("en-GB", {
      weekday: 'long',
      day: 'numeric',
      month: 'long'
    });
   
    const dateParts = formattedDate.split(' ');
    const finalArrivalDateString = `${dateParts[0]} ${ordinalSuffix(arrivalDate.getUTCDate())} ${dateParts[2]}`;
    
    const deliveryTexts = document.getElementsByClassName('delivery-text');
    for (const deliveryText of deliveryTexts)
        deliveryText.textContent = `Order within the next ${result} to receive your order on ${finalArrivalDateString}`;
 
Joined
Feb 25, 2022
Messages
18
Reaction score
1
I can't see this comma in my browser.

View attachment 3048

The comma after the day appears depending on the date format settings of the operating system where the browser is running.

Check this out.
JavaScript:
    const formattedDate = arrivalDate.toLocaleDateString("en-GB", {
      weekday: 'long',
      day: 'numeric',
      month: 'long'
    });
  
    const dateParts = formattedDate.split(' ');
    const finalArrivalDateString = `${dateParts[0]} ${ordinalSuffix(arrivalDate.getUTCDate())} ${dateParts[2]}`;
   
    const deliveryTexts = document.getElementsByClassName('delivery-text');
    for (const deliveryText of deliveryTexts)
        deliveryText.textContent = `Order within the next ${result} to receive your order on ${finalArrivalDateString}`;
Ahh looks to be a firefox browser issue as looked in Chrome and it don't have the comma after the day, is there a way to remove it from the firefox browser?
 
Joined
Jul 4, 2023
Messages
539
Reaction score
70
JavaScript:
const dateParts = formattedDate.split(' ');
const finalArrivalDateString = `${dateParts[0]} ${ordinalSuffix(arrivalDate.getUTCDate())} ${dateParts[2]}`;
 
const deliveryTexts = document.getElementsByClassName('delivery-text');
for (const deliveryText of deliveryTexts)
    deliveryText.textContent = `Order within the next ${result} to receive your order on ${finalArrivalDateString}`;
Using this code we force the date to be formatted according to your idea, regardless of system settings or default browser behavior.
 
Joined
Feb 25, 2022
Messages
18
Reaction score
1
Using this code we force the date to be formatted according to your idea, regardless of system settings or default browser behavior.
Thank you, I tried that but it's displaying Order within the next ${result} to receive your order on ${finalArrivalDateString} on the category page https://shop.it-doneright.co.uk/laptops-tablets/Laptops

I copied the code again exactly and it's displayed the correct text etc but it's still got the comma after the day
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,075
Messages
2,570,562
Members
47,197
Latest member
NDTShavonn

Latest Threads

Top