skip to Main Content

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 class="countdown" id="1" data-date="2023-01-06 23:59:59"></div>
        <div class="countdown" id="2" data-date="2023-01-07 23:59:59"></div>
        <div class="countdown" id="3" data-date="2023-01-08 23:59:59"></div>
    </body>
</html>

2

Answers


  1. 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 class="countdown" id="1" data-date="2023-01-06 23:59:59"></div>
    <div class="countdown" id="2" data-date="2023-01-07 23:59:59"></div>
    <div class="countdown" id="3" data-date="2023-01-08 23:59:59"></div>
    Login or Signup to reply.
  2. 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 class="countdown" id="1" data-date="2023-01-06 23:59:59"></div>
      <div class="countdown" id="2" data-date="2023-01-07 23:59:59"></div>
      <div class="countdown" id="3" data-date="2023-01-08 23:59:59"></div>
    </body>
    
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search