Search code examples
javascriptjquerycountdown

How to get JavaScript and JQuery to display 3 digits in the days


I was trying to work this code off the internet and I needed a little bit of help, the code displays a countdown but currently the code only shows "2" Boxes for the day fields. Is there anyway to modify this code to show "3" boxes for the day field?

jQuery Countdown.js

(function($){

    // Number of seconds in every time division
    var days    = 24*60*60,
        hours   = 60*60,
        minutes = 60;

    // Creating the plugin
    $.fn.countdown = function(prop){

        var options = $.extend({
            callback    : function(){},
            timestamp   : 0
        },prop);

        var left, d, h, m, s, positions;

        // Initialize the plugin
        init(this, options);

        positions = this.find('.position');

        (function tick(){

            // Time left
            left = Math.floor((options.timestamp - (new Date())) / 1000);

            if(left < 0){
                left = 0;
            }

            // Number of days left
            d = Math.floor(left / days);
            updateDuo(0, 1, d);
            left -= d*days;

            // Number of hours left
            h = Math.floor(left / hours);
            updateDuo(2, 3, h);
            left -= h*hours;

            // Number of minutes left
            m = Math.floor(left / minutes);
            updateDuo(4, 5, m);
            left -= m*minutes;

            // Number of seconds left
            s = left;
            updateDuo(6, 7, s);

            // Calling an optional user supplied callback
            options.callback(d, h, m, s);

            // Scheduling another call of this function in 1s
            setTimeout(tick, 1000);
        })();

        // This function updates two digit positions at once
        function updateDuo(minor,major,value){
            switchDigit(positions.eq(minor),Math.floor(value/10)%10);
            switchDigit(positions.eq(major),value%10);
        }

        return this;
    };


    function init(elem, options){
        elem.addClass('countdownHolder');

        // Creating the markup inside the container
        $.each(['Days','Hours','Minutes','Seconds'],function(i){
            $('<span class="count'+this+'">').html(
                '<span class="position">\
                    <span class="digit static">0</span>\
                </span>\
                <span class="position">\
                    <span class="digit static">0</span>\
                </span>'
            ).appendTo(elem);

            if(this!="Seconds"){
                elem.append('<span class="countDiv countDiv'+i+'"></span>');
            }
        });

    }

    // Creates an animated transition between the two numbers
    function switchDigit(position,number){

        var digit = position.find('.digit')

        if(digit.is(':animated')){
            return false;
        }

        if(position.data('digit') == number){
            // We are already showing this number
            return false;
        }

        position.data('digit', number);

        var replacement = $('<span>',{
            'class':'digit',
            css:{
                top:'-2.1em',
                opacity:0
            },
            html:number
        });

        // The .static class is added when the animation
        // completes. This makes it run smoother.

        digit
            .before(replacement)
            .removeClass('static')
            .animate({top:'2.5em',opacity:0},'fast',function(){
                digit.remove();
            })

        replacement
            .delay(100)
            .animate({top:0,opacity:1},'fast',function(){
                replacement.addClass('static');
            });
    }
})(jQuery);

Countdown style .css

    .countdownHolder{
    width:450px;
    margin:0 auto;
    font: 40px/1.5 'Open Sans Condensed',sans-serif;
    text-align:center;
    letter-spacing:-3px;
}

.position{
    display: inline-block;
    height: 1.6em;
    overflow: hidden;
    position: relative;
    width: 1.05em;
}

.digit{
    position:absolute;
    display:block;
    width:1em;
    background-color:#444;
    border-radius:0.2em;
    text-align:center;
    color:#fff;
    letter-spacing:-1px;
}

.digit.static{
    box-shadow:1px 1px 1px rgba(4, 4, 4, 0.35);

    background-image: linear-gradient(bottom, #3A3A3A 50%, #444444 50%);
    background-image: -o-linear-gradient(bottom, #3A3A3A 50%, #444444 50%);
    background-image: -moz-linear-gradient(bottom, #3A3A3A 50%, #444444 50%);
    background-image: -webkit-linear-gradient(bottom, #3A3A3A 50%, #444444 50%);
    background-image: -ms-linear-gradient(bottom, #3A3A3A 50%, #444444 50%);

    background-image: -webkit-gradient(
        linear,
        left bottom,
        left top,
        color-stop(0.5, #3A3A3A),
        color-stop(0.5, #444444)
    );
}

/**
 * You can use these classes to hide parts
 * of the countdown that you don't need.
 */

.countDays{}
.countDiv0{}
.countHours{}
.countDiv1{}
.countMinutes{}
.countDiv2{}
.countSeconds{}


.countDiv{
    display:inline-block;
    width:16px;
    height:1.6em;
    position:relative;
}

.countDiv:before,
.countDiv:after{
    position:absolute;
    width:5px;
    height:5px;
    background-color:#444;
    border-radius:50%;
    left:50%;
    margin-left:-3px;
    top:0.5em;
    box-shadow:1px 1px 1px rgba(4, 4, 4, 0.5);
    content:'';
}

.countDiv:after{
    top:0.9em;
}

script.js

$(function(){

    var note = $('#note'),
        ts = new Date(2016, 11, 27, 23, 59, 59),
        newYear = true;

    if((new Date()) > ts){
        // The new year is here! Count towards something else.
        // Notice the *1000 at the end - time must be in milliseconds
        ts = (new Date()).getTime() + 10*24*60*60*1000;
        newYear = false;
    }

    $('#countdown').countdown({
        timestamp   : ts,
        callback    : function(days, hours, minutes, seconds){

            var message = "";

            message += days + " day" + ( days==1 ? '':'s' ) + ", ";
            message += hours + " hour" + ( hours==1 ? '':'s' ) + ", ";
            message += minutes + " minute" + ( minutes==1 ? '':'s' ) + " and ";
            message += seconds + " second" + ( seconds==1 ? '':'s' ) + " <br />";

            if(newYear){
                message += "left until the new year!";
            }
            else {
                message += "left to 10 days from now!";
            }

            note.html(message);
        }
    });

});

HTML

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>CountDown</title>

        <!-- Our CSS stylesheet file -->
        <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300" />
        <link rel="stylesheet" href="assets/css/styles.css" />
        <link rel="stylesheet" href="assets/countdown/jquery.countdown.css" />
    </head>

    <body>

        <div id="countdown"></div>

        <p id="note"></p>

        <!-- JavaScript includes -->
        <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
        <script src="assets/countdown/jquery.countdown.js"></script>
        <script src="assets/js/script.js"></script>
    </body>
</html>

Not sure if this is workable or not, any input is appreciated.


Solution

  • Yes! It is doable. Here is a working codepen, but let me explain what I did as well.

    First I went to where the HTML is being generated. It was looping over an array of the different numerations, and adding 2 fields for each numeration. I pulled days out of the loop, and gave it 3 fields:

    $('<span class="countDays">').html(
                '<span class="position">\
                    <span class="digit static">0</span>\
                </span>\
                <span class="position">\
                    <span class="digit static">0</span>\
                </span>\
              <span class="position">\
                    <span class="digit static">0</span>\
                </span>'
            ).appendTo(elem);
      elem.append('<span class="countDiv countDivDays"></span>');
        // Creating the markup inside the container
        $.each(['Hours','Minutes','Seconds'],function(i){
            $('<span class="count'+this+'">').html(
                '<span class="position">\
                    <span class="digit static">0</span>\
                </span>\
                <span class="position">\
                    <span class="digit static">0</span>\
                </span>'
            ).appendTo(elem);
    
            if(this!="Seconds"){
                elem.append('<span class="countDiv countDiv'+i+'"></span>');
            }
    

    Then I went to where it was updating the numbers. It was doing some simple division and using an updateDuo method for each numeration. So I made an updateTrio method to update my 3 fields

    // Number of days left
            d = Math.floor(left / days);
            updateTrio(0, 1, 2, d);
            left -= d*days;
    
    function updateDuo(minor,major,value){
            switchDigit(positions.eq(minor),Math.floor(value/10)%10);
            switchDigit(positions.eq(major),value%10);
        }
    
      function updateTrio(minor, middle, major,value){
            switchDigit(positions.eq(minor),Math.floor(value/100)%10);
            switchDigit(positions.eq(middle),Math.floor(value/10)%10);
            switchDigit(positions.eq(major),value%10);
        }
    

    Unfortunately, this solution will always display 3 numbers. But by my count you have about 400 days to figure that problem out :)