A dynamic delivery time counter for WooCommerce as a shortcode

Viewed 260

I've created a shortcode for Wordpress using a javascript counter.

Back End - Counter works fine:

Counter works fine

Front End - Counter doesn't work (no console errors...):

Counter doesn't work (no console errors...)

My code for the shortcode:

// Delivery Counter Time
 function bb__delivery_counter_function() {
    ?>
 <script type='text/javascript'>
        if (document.getElementById('countdownTimer')) {
            pad = function(n, len) { // leading 0's
                var s = n.toString();
                return (new Array( (len - s.length + 1) ).join('0')) + s;
            };
            
            var timerRunning = setInterval(

                function countDown() {
                    var target = 12; // 12:00hrs is the cut-off point
                    var now = new Date();
                    
                    //Put this in a variable for convenience
                    var weekday = now.getDay();
                    
                    if(weekday == 0){//Sunday? Add 24hrs
                        target += 24;
                    }//keep this before the sunday
                    
                    if(weekday == 6){//It's Saturday? Add 48hrs
                        target += 48;
                    }
                    
                    //If between Monday and Friday, 
                    //check if we're past the target hours, 
                    //and if we are, abort.
                    if((weekday>=1) && (weekday<=5)){
                        if (now.getHours() > target) { //stop the clock
                            target += 24;
                        }                
                    }
                    
                    var hrs = (target - 1) - now.getHours();
                    if (hrs < 0) hrs = 0;
                    var mins = 59 - now.getMinutes();
                    if (mins < 0) mins = 0;
                    var secs = 59 - now.getSeconds();
                    if (secs < 0) secs = 0;
                    
                    var str = pad(hrs, 2) + ':' + pad(mins, 2) + '.<small>' + pad(secs, 2) + '</small>';
                    document.getElementById('countdownTimer').innerHTML = str;
                    
                }, 1000
            );
        }
  </script>
  <?php

  return '<div id="countdownTimer"></div>';
}

add_shortcode('bb__delivery_counter', 'bb__delivery_counter_function');

When I add the shortcode in Elementor theme everything works fine in the "back end" so the counter counts in the Elementor Admin view.

But if I try to access the page through the front end, the Javascript doesn't work. Any ideas why this is happening?

1 Answers

There are some mistakes in your code. You need to buffer the Javascript to return it as it should be for a shortcode and now JS wait until DOM is loaded using jQuery (as jQuery library is already loaded in WordPress/WooCommerce). Also I have simplified a bit your code:

// Delivery Counter Time
add_shortcode('bb__delivery_counter', 'shortcode_delivery_counter_func');
function shortcode_delivery_counter_func() {
    ob_start(); // Start buffering
    ?>
    <script type='text/javascript'>
    jQuery(function($) {
        function pad(n, len) { // leading 0's
            var s = n.toString();
            return (new Array( (len - s.length + 1) ).join('0')) + s;
        };

        setInterval( function() {
            var target = 12, // 12:00hrs is the cut-off point
                now = new Date(),
                weekday = now.getDay();

            if (weekday == 6) { // On Saturday: Adds 48hrs
                target += 48;
            } 
            // On sundays | And from monday to Friday after the cut-off : Adds 24hrs
            else if ( weekday == 0 || now.getHours() > target ) {
                target += 24;
            }

            var hrs  = (target - 1) - now.getHours(),
                mins = 59 - now.getMinutes(),
                secs = 59 - now.getSeconds();

            if (hrs < 0) hrs = 0;
            if (mins < 0) mins = 0;
            if (secs < 0) secs = 0;

            $('#countdownTimer').html( pad(hrs, 2) + ':' + pad(mins, 2) + '.<small>' + pad(secs, 2) + '</small>' );
        }, 1000 );
    });
    </script>
    <?php

    return '<div id="countdownTimer"></div>' . ob_get_clean(); // return buffered JS with html
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Related