StevenPHP
StevenPHP

Reputation: 3607

JQuery countdown timer with milliseconds

I have a very basic lightweight function that counts down from 30 seconds. I have been trying to add milliseconds to it but I can't seem to get it to work correctly.

var count = 30;
var counter = setInterval(timer, 1000); //1000 will  run it every 1 second

function timer() {
    if (count <= 0) {
        clearInterval(counter);
        return;
    }
    count = count - 1;
    document.getElementById("timer").innerHTML = count + " secs"; // watch for spelling
}

Upvotes: 8

Views: 27050

Answers (6)

BannerBomb
BannerBomb

Reputation: 53

I know this post is old but I thought I should share my answer maybe it will help someone. This script counts the current date/time with milliseconds, minutes, seconds, month, day, year, and suffix, it is easy to modify, you can modify it to countdown if you need to

    function showRemaining() {
    var currentDate = new Date(); //'11/23/2016 12:00 AM'
    var month = currentDate.getMonth() + 1
    var day = currentDate.getDate()
    var year = currentDate.getFullYear()
    var currentTime = new Date()
    var hours = currentTime.getHours()
    var minutes = currentTime.getMinutes();
    var seconds = currentTime.getSeconds();
    //var milliseconds = currentTime.getMilliseconds().toString().slice(0, 3); //+ 999; //* 111
    var milliseconds = (currentTime.getMilliseconds()/.11).toFixed(0)
    //var milliseconds = currentTime * 3
    var timer;


    if (minutes < 10)
    minutes = "0" + minutes
    
    var suffix = "AM";
    if (hours >= 12) {
    suffix = "PM";
    hours = hours - 12;
    }
    if (hours === 0) {
    hours = 12;
    }
      
      if (seconds < 10)
        seconds = "0" + seconds
        
        if (seconds >= 60) {
          seconds = seconds - 60;
        }
      if (seconds === 60) {
        seconds = 60;
      }
      
      if (hours < 10)
        hours = "0" + hours
        
        if (hours >= 12) {
          hours = hours - 12;
        }
      if (hours === 12) {
        hours = 12;
      }
      
      if (milliseconds < 1000)
        milliseconds = "0000";// + milliseconds
        
        if (milliseconds >= 1000) {
          milliseconds = milliseconds - 100; //was 1000
        }
      if (milliseconds === 1000) {
        milliseconds = 1000;
      }
      
    var now = new Date();
    var distance = currentDate - now;
    if (distance < 0) {
    return;
    }
    
      /*var days = Math.floor(distance / day);
      var hours = Math.floor((distance % day) / hour);
      var minutes = Math.floor((distance % hours) / minute);
      var seconds = Math.floor((distance % minutes) / second);
      //var milliseconds = Math.floor(distance % _second) / _millisecond;*/
      
      document.getElementById('countdown').innerHTML = month + '/'; // months
      document.getElementById('countdown').innerHTML += day + '/'; // days
      document.getElementById('countdown').innerHTML += year + '<br>'; // year
      document.getElementById('countdown').innerHTML += hours + ' : '; // hrs
      document.getElementById('countdown').innerHTML += minutes + ' : '; // mins
      document.getElementById('countdown').innerHTML += seconds + ' : '; // secs
      document.getElementById('countdown').innerHTML += milliseconds + ' '; // milliseconds
      document.getElementById('countdown').innerHTML += '<b>' + suffix + '</b>'; // suffix

    }
      timer = setInterval(showRemaining, 1);
<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <p id="countdown"></p>
</body>
</html>

Upvotes: 0

acolchagoff
acolchagoff

Reputation: 1978

Based on Previous responses, I've derived a vanilla javascript, object oriented approach.

I've also created a github repo in case anyone wants to improve it.

https://github.com/denodster/JSTimer

function Timer(element){
    var interval;
    var milliseconds = 0;
    var self = this;

    function printValue(){
        var seconds = Math.round(milliseconds/10)/100;
        $(element).empty();
        $(element).text(seconds);
    }

    this.start = function(seconds, countdown){
        if(interval){//if an interval exists clear it first
            clearInterval(interval);
        }
        if(seconds) {//if seconds are passed in reset the milliseconds
            milliseconds = milliseconds + (seconds * 1000);
        }
        interval = setInterval(function(){
            if(countdown) {
                if (milliseconds >= 0) {
                    milliseconds -= 10;
                    printValue();
                } else {
                    self.stop();
                }
            } else {
                milliseconds += 10;
                printValue();
            }
        }, 10);
    };

    this.stop = function(){
        clearInterval(interval);
    };

    this.reset = function(){
        milliseconds = 0;
        printValue();
    };

    this.getValue = function(){
        return milliseconds/1000;
    };
}

Example:

<span id="counter"></span>
<script type="text/javascript">
//count down to zero from 10 seconds
var counter = document.getElementById('counter');
var timer = new Timer(counter);
timer.start(10, true);
</script>

Upvotes: 0

MirroredFate
MirroredFate

Reputation: 12835

Try it this way. Stopwatches only count hundredths of seconds anyway.

var count = 3000;

var counter = setInterval(timer, 10); //10 will  run it every 100th of a second

function timer()
{
    if (count <= 0)
    {
        clearInterval(counter);
        return;
     }
     count--;
     document.getElementById("timer").innerHTML=count /100+ " secs"; 
}

Just for better formatting and testing:

HTML

<span id="timer"></span>

<button id="start">start</button>
<button id="stop">stop</button>
<button id="reset">reset</button>

Javascript

var initial = 30000;
var count = initial;
var counter; //10 will  run it every 100th of a second

function timer() {
    if (count <= 0) {
        clearInterval(counter);
        return;
    }
    count--;
    displayCount(count);
}

function displayCount(count) {
    var res = count / 100;
    document.getElementById("timer").innerHTML = res.toPrecision(count.toString().length) + " secs";
}

$('#start').on('click', function () {
    clearInterval(counter);
    counter = setInterval(timer, 10);
});

$('#stop').on('click', function () {
    clearInterval(counter);
});

$('#reset').on('click', function () {
    clearInterval(counter);
    count = initial;
    displayCount(count);
});

displayCount(initial);

EDIT:

The original question was trying to figure out how to make a display like a stopwatch, and I know very few that actually count milliseconds. That being said, here is a possible solution to do that. It relies on updating as fast as possible, and getting the difference between our last update and our current one to remain accurate.

var initial = 300000;
var count = initial;
var counter; //10 will  run it every 100th of a second
var initialMillis;

function timer() {
    if (count <= 0) {
        clearInterval(counter);
        return;
    }
    var current = Date.now();

    count = count - (current - initialMillis);
    initialMillis = current;
    displayCount(count);
}

function displayCount(count) {
    var res = count / 1000;
    document.getElementById("timer").innerHTML = res.toPrecision(count.toString().length) + " secs";
}

$('#start').on('click', function () {
    clearInterval(counter);
    initialMillis = Date.now();
    counter = setInterval(timer, 1);
});

$('#stop').on('click', function () {
    clearInterval(counter);
});

$('#reset').on('click', function () {
    clearInterval(counter);
    count = initial;
    displayCount(count);
});

displayCount(initial);

Upvotes: 10

Oscar Paz
Oscar Paz

Reputation: 18312

You can try this. If you're targeting modern browsers, you may have access to the Performance API, which gives high resolution timestamps instead of normal timestamps.

An improved solution would use requestAnimationFrame(). Updating the DOM every millisecond, even if possible with setTimeout(), is a waste of resources, as the browser will only refresh the screen, typically, 60 times in a second (every 16.6 ms). Updating the clock two times or more in that interval would be useless, and the user will only see the last value.

function now() {
    return window.performance ? window.performance.now() : Date.now();
}

var count = 30000;
var delay = 20; //20 ms. This will be only indicative. There's no guarantee the browswer will call the function after exactly this time

var initTick = 0;
var timerElement = document.getElementById("timer");
function tick() {
   var remaining = (count - (now() - initTick)) / 1000;  
   console.log(remaining);
   remaining = remaining >= 0 ? remaining : 0;
   var secs = remaining.toFixed(2);
   timerElement.innerHTML = secs + " secs";
   if (remaining) setTimeout(tick, delay);
}

initTick = now();
console.log(now());
setTimeout(tick, delay);

JSFIDDLE.

Upvotes: 1

Naveen Chandra Tiwari
Naveen Chandra Tiwari

Reputation: 5123

  This may help you:

    var count = 30;
    var count1 = 60;
        //1000 will  run it every 1 second
        var counter1;
        var counter = setInterval(timer, 1000);

        function timer1() {
            if (count1 <= 0 && count < 1) {
                clearInterval(counter1);
                return;
            } else {
                if (count1 <= 0 && count > 0)
                    count1 = 60;
                else
                    count1 = count1 - 1;
                //var counter=setInterval(timer, 1000);
            }
            document.getElementById("timer").innerHTML = count + "." + count1 + " secs"; // watch for spelling
        }
        function timer() {
            if (count <= 0) {
                clearInterval(counter);
                return;
            }
            else {
                counter1 = setInterval(timer1, 10);
            }
            count = count - 1;

        }

Upvotes: 0

Ian Clark
Ian Clark

Reputation: 9357

The problem is that the browser can't possibly handle manipulating the DOM every millisecond. For this reason, lots of browsers actually set a minimum value for intervals - and the W3C suggest a minimum of 4ms (source). We can use this information to create a throttled approach which runs as quickly as possible.

// We actually only run our method every x millisecs, due to browser constraints
var THROTTLE_AMOUNT = 4;

countdown(30);

function countdown(secs) {
    var milli = secs * (1000);
    var counter = setInterval(function() {
        if(milli <= 0) {
            clearInterval(counter);
            return
        }
        milli -= THROTTLE_AMOUNT;
        document.getElementById("timer").innerHTML = milli + " millisecs"; // watch for spelling
    }, THROTTLE_AMOUNT);
}

Upvotes: 3

Related Questions