I'm trying to make a countdown timer for each row of a table based on a hidden field containing the ammount of seconds to finish. Here is what I have done so far:
function countdownProcedure() {
var interval = 1000;
var i = 0;
var seconds;
$(".rfqTbl tr").each(function() {
if(i > 0) {
seconds = $(this).find("#sqbTimestamp").text();
var days = Math.floor(seconds / (60*60*24));
seconds -= days * 60 * 60 * 24;
var hours = Math.floor(seconds / (60*60));
seconds -= hours * 60 * 60;
var minutes = Math.floor(seconds / 60);
seconds -= minutes * 60;
if(days < 1) { days=""; }
$(this).find("#countDown").html(days + "<pre> Days</pre> " + hours + "<pre>:</pre>" + minutes + "<pre>:</pre>" + seconds);
if(days > 1) {
$(this).find("#countDown").css({
'color':'#2A7F15',
'font-weight':'bold'
});
};
if(days < 1) {
$(this).find('#countDown').css('color','red');
$(this).find('#countDown pre:nth-of-type(1)').css('display','none');
}
if(seconds < 10) {
$(this).find("#countDown").append(" ");
};
if(minutes < 60){ interval = 1000; };
}
i++;
});
setInterval(countdownProcedure,interval);
};
However, my problem is that I'm trying to get this function to run (realistically every second or 30) so that the time shown would update and hence 'countdown'. The problem I am having is in firefox and safari the browsers are just hanging after the first countdown and chrome is doing nothing (I guess it has a safe guard to prevent it from hanging).
Any help would be much appreciated!
You are running a multitude of setInterval() calls, so the event queue gets crowded with your function.
I think, what you mean is more like setTimeout() at the end of your function.
function countdownProcedure(){
// all your logic
setTimeout(countdownProcedure,interval);
};
The difference is, that setInterval() will run your code every x seconds, until you tell it to stop.
setTimeout() on the other hand, just runs your code once after x seconds.
Change all ids for clases Ex: #sqbTimestamp for .sqbTimestamp
in an HTML document, should exists only 1 element with some id, if you set multiple elements with same id, unexpected results (as browser hanging) can occurrs.
Also, you are setting days="" and then do the following compare if (days > 1)
I think your algorithm is wrong. You are recursively setting intervals which are calling themselves every time and setting new intervals and so on...
You must change your algorithm a bit to get it clean.
Related
I have a program which I wrote with html just like a website but runs offline so I want to add 35 minutes countdown after the user have logged in then when the 35 minutes is exusted the user will be logged out
But I can't get the code right because I am new to javascript but I was able to get it to count for 60seconds and after that it will alert the user with "logout" but I want it to log the user out not to alert the user to logout
This is the html code
<div id="counter">1:00</div>
And this is the javascript code
function countdown() {
var seconds = 60;
function tick() {
var counter = document.getElementById("counter");
seconds--;
counter.innerHTML = "0:" + (seconds < 10 ? "0" : "") + String(seconds);
if( seconds > 0 ) {
setTimeout(tick, 1000);
} else {
alert("Game over");
}
}
tick();
}
countdown();
<script>
// Set the date we're counting down to
var countDownDate = new Date("July 12, 2017 09:00:00").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Output the result in an element with id="counter"
document.getElementById("counter").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("counter").innerHTML = "EXPIRED";
}
}, 1000); // time changes in every 1 second
</script>
<p2>to go</p2>
try this out, change date and time according to your need
Handling sessions in the frontend is not the best way to approach this, but since you asked...
Your method seems correct, I mean you just have to change 60 seconds with 2100 (for 35 minutes) seconds. To logout you'd need a function or a page to log them out.
The problem with this method is that if they refresh the page the counter also refreshes, also they can directly change the javascript if they want, rewrite the function and so many other things...
Luckily for you Javascript now supports something called session storage and local storage, so you can store your timer in one of these variables and even if they refresh the page you don't lose their latest value. Session variables last for as long as the browser is open, local variables last until forever, or if until you unset them.
You can set storage values like this:
var latestTime = localStorage.getItem('secondsPassed');
localStorage.setItem('secondsPassed', lastTime+1);
This will at least get around them refreshing the page and closing-reopening the browser to refresh the timer!
If you want to learn how to handle sessions properly read into PHP since the backend is the best way to handle these kind of things.
function countdown() {
var timeoutMinutes = 35;
var startTime = new Date();
var elapsedSecond = 0;
function tick() {
var counter = document.getElementById("counter");
var currentTime = new Date();
elapsedSecond = (currentTime - startTime) / 1000;
counter.innerHTML = formatPlaces("0") + ":"
+ formatPlaces(elapsedSecond / 60) + ":"
+ formatPlaces(elapsedSecond % 60);
if (elapsedSecond <= timeoutMinutes * 60) {
setTimeout(tick, 1000);
} else {
alert("Game over");
}
}
tick();
}
function formatPlaces(value) {
var intValue = parseInt(value);
return intValue.toString().length == 1 ? "0" + intValue.toString() : intValue.toString();
}
countdown();
<div id="counter">00:00</div>
numberOfSeconds=1*60,
r=document.getElementById('clock');
var t = setInterval(function(){
numberOfSeconds--;
var minutes=Math.floor(numberOfSeconds/60),seconds=(numberOfSeconds%60)+'';
r.textContent='Registration closes in '+minutes+':'+(seconds.length>1?'':'0')+seconds;
if (numberOfSeconds <= 0) {
clearInterval(t);
alert('boom');
}
},1000);
html section
<div id="clock"></div>
how i can add milliseconds to this reverse count down timer/counter script.
i want it like 00:00:00 <== milliseconds in last.
}},1000 / 20);
However above little change in last of script made seconds into milliseconds but i can't figure out how i can adjust it with seconds like MM:SS:MS 00:00:00
Any Help will be appreciated..!
That setInterval will have to be set to 1 (ms), if you need to see the milliseconds. 1000ms = 1s. So I believe MM:SS:MS would look more like 00:00:000.
I do not think it's possible. i did a test and the results show that js cannot be as fast to set 1millisecond to setInterval. setting it to 1ms - 15ms will output the same results.
normaly the code below should work the way you wanted.
var m = 60*1000, r = document.getElementById("clock");
var t = setInterval(function () {
m--;
var min = Math.floor(m / 60000),
sec = Math.floor((m % 60000) / 1000);
mil = (m % 60000) % 1000; r.innerHTML = min + ":" + sec + ":" + mil;}, 1)
Maybe the problem comes from my computer (maybe it is slow).
if you ever want the test script, tell it in comment so i will give it to you in order you'll test it by yourself
So the code below is the code that I was able to work with so far; however, doesn't do exactly what I need it to do.
I want to be able to call a function (aka: sundayDelta() ), however, I would love to be able to define the day of week and time of day I want the function to use in the countdown inside the calling of the function. I'm not sure if this is possible...but I was thinking something like this
sundayDelta(1,1000) which would turn into Day of Week Sunday and time of day: 1000 (10:00am). Not sure if something like this is even possible; however, I'm hoping it is. I plan on having multiple countdowns going on the same page just appearing at different times of day.
When the countdown finishes, I want it to refresh a div (doesn't matter what name the div has)
I would also love to be able to incorporate PHP server time into this that way everyone is seeing the correct countdown no matter where they are.
Any help would be great! Thanks for your input!
function plural(s, i) {
return i + ' ' + (i > 1 ? s + 's' : s);
}
function sundayDelta(offset) {
// offset is in hours, so convert to miliseconds
offset = offset ? offset * 20 * 20 * 1000 : 0;
var now = new Date(new Date().getTime() + offset);
var days = 7 - now.getDay() || 7;
var hours = 10 - now.getHours();
var minutes = now.getMinutes() - 00 ;
var seconds = now.getSeconds()- 00;
if (hours < 0){
days=days-1;
}
var positiveHours= -hours>0 ? 24-(-hours) : hours;
return [plural('day', days),
plural('hour', positiveHours),
plural('minute', minutes),
plural('second', seconds)].join(' ');
}
// Save reference to the DIV
$refresh = $('#refresh');
$refresh.text('This page will refresh in ' + sundayDelta());
// Update DIV contents every second
setInterval(function() {
$refresh.text('This page will refresh in ' + sundayDelta());
}, 1000);
When I make flexible text for intervals, I like to subtract out until nothing is left. That way you only show the non-0 values:
function sundayDelta(target_date) {
var now = new Date();
var offset = Math.floor((Date.parse(target_date) - now.valueOf()) / 1000);
var r = [];
if (offset >= 86400) {
var days = Math.floor(offset / 86400);
offset -= days * 86400;
r.push(plural('day', days));
}
if (offset >= 3600) {
var hours = Math.floor(offset / 3600);
offset -= hours * 3600;
r.push(plural('hour', hours));
}
if (offset >= 60) {
var minutes = Math.floor(offset / 60);
offset -= minutes * 60;
r.push(plural('minute', minutes));
}
if (offset != 0) {
r.push(plural('second', offset));
}
return r.join(' ');
}
In the PHP code, you can set variable this way. And we'll leave time zones out of it for now, but they could be added as well just by specifying them.
echo "target_date = '" . date('Y-m-d H:i:s', strotime('next Sunday 10am')) . "';\n";
I want to implement a count-up timer JS code that starts counting at each load page from 0. The code which I've now is like this:
var secondsTotal = 0;
setInterval(function() {
++secondsTotal;
var minutes = Math.floor(secondsTotal / 60);
var seconds = Math.floor(secondsTotal) % 60;
var milliseconds = Math.floor(secondsTotal) % 1000;
document.getElementById('counter').innerHTML = minutes + ":" + seconds + "." + milliseconds;
}, 1000);
The output format should be: 00:00.0
mm:ss.ms
So, how to output the result like above format (minutes and seconds should be exactly printed in two digits format)?
If you want to do it per-page, you're almost there. Right now, your code does not allow you to track milliseconds, as your setInterval runs every second. What I would recommend instead is something like this:
(function() {
var counter = 0,
cDisplay = document.getElementById("counter");
format = function(t) {
var minutes = Math.floor(t/600),
seconds = Math.floor( (t/10) % 60);
minutes = (minutes < 10) ? "0" + minutes.toString() : minutes.toString();
seconds = (seconds < 10) ? "0" + seconds.toString() : seconds.toString();
cDisplay.innerHTML = minutes + ":" + seconds + "." + Math.floor(t % 10);
};
setInterval(function() {
counter++;
format(counter);
},100);
})();
This does a couple of things to allow your code to run 10 times per second:
The output element, #counter, is cached and not retrieved every iteration
The formatting is kept to arithmetic operations only - modulo and division.
This now also adds leading zeroes.
If you would like to keep this counter running page-per-page, consider using document.cookies to pass the final value from page to page.
Fiddle
This serves as a good first version. However, you may want to:
Pause/re-start your timer
Reset your timer
Have multiple timers
For this reason, I will add a slightly more complex form of the above code, which will allow you to manage multiple timers. This will make use of a few OO concepts. We will use a TimerManager object to "host" our timers, and each Timer object will have a link to the manager.
The reason for this is because every timer will depend on the same setInterval() by doing it this way, rather than to have multiple setInterval() calls. This allows you to cut down on wasted clock cycles.
More on this in about 5 minutes!
Counting seconds that way isn't guaranteed to be accurate. The setInterval method can drift on you based upon the JS engine's ability to complete its other tasks. Not sure what your use case is, such as how long you expect to count up, but it's worth taking note of. See Will setInterval drift? for a detailed explanation.
I'd recommend you check out the momentjs plugin # http://momentjs.com/ and update your code to something like the following
var startTime = moment();
var el = document.getElementById('counter');
setInterval(function() {
var ms = moment().diff(startTime),
min = moment.duration(ms).minutes(),
sec = moment.duration(ms).seconds();
ms = moment.duration(ms).milliseconds();
min = (min < 10) ? "0" + min.toString() : min.toString();
sec = (sec < 10) ? "0" + sec.toString() : sec.toString();
ms = ms.toString().substring(0,2); // change this if you want to expand ms counter display
el.innerHtml = min + ":" + sec + "." + ms;
}, 50);
You're free to update the interval, and your milliseconds display without adjusting your calculations.
I'm using script below to countdown from given time and display how many hours+minutes+seconds left for timeout on the script in real-time.
Counting down woks perfectly fine but the problem I'm facing is, when using next and previous buttons on browsers, the time doesn't get refreshed and I see old time instead. It either shows previous time or later.
I'm aware that next and previous buttons on browsers don't refresh pages but how can I overcome this issue?
JS
function timeout_warning(login_timeout)
{
var counter = 0;
var total_seconds = 0;
var colour = '';
var interval_id = '';
interval_id = setInterval(function ()
{
counter++;
total_seconds = login_timeout - counter;
hours = parseInt(total_seconds / 3600 ) % 24;
minutes = parseInt(total_seconds / 60 ) % 60;
seconds = parseInt(total_seconds % 60, 10);
remaining = (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes) + ":" + (seconds < 10 ? "0" + seconds : seconds);
if (minutes == 0 && seconds == 0)
{
document.getElementById('font_timeout').innerHTML = 'Timeout';
window.clearInterval(interval_id);
}
else
{
document.getElementById('font_timeout').innerHTML = remaining + 'sec';
}
}, 1000);
}
HTML BODY
<body onload="timeout_warning('1800')">
Without a live example I can only give an opinion to the solution. You might want to us JavaScript to load the remaining time from a cookie so that when a browser arrow is clicked the code will pull the time from the cookie and not from the cached data.
A solution has already been posted on this and uses a form to store data in the page to see if the user has pressed the back button. It sets some form data and if the page goes back, it can tell if that data is already set, and if it is, it needs to force a reload (so your timer will start again).