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).
Related
this.start is the function that starts the countdown. The countdown is only supposed to work if session is true. this.pause makes the session false, and is supposed to stop this.start, but the timer never stops; it just keeps counting down.
The function works in the console though. this.resume also does nothing; the the counter just keeps going down, although it's supposed to work when session is true.
Before I was using setInterval for the countdown, and it worked, but I couldn't figure out how to resume it after that. Is there any reason why my if statement isn't working here to pause and resume the countdown timer?
let timer = function(sessionNumber2) {
let session = true;
console.log(Boolean(session));
let currentInterval;
//update counter every 1 second
if (session == true) {
this.start = function() {
//hide start buttun and show other pause
startButton.style.display = 'none';
pause.style.display = 'unset';
const then = new Date();
const end = then.setMinutes(then.getMinutes() + sessionNumber2);
currentInterval = setInterval(function() {
//get Todays date and time
let now = new Date().getTime();
//find the distance between now and count down date
distance = end - now;
// Time calculations for minutes and seconds
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
if (minutes < 10) {
minutes = '0' + minutes;
if (seconds < 10) {
seconds = '0' + seconds;
}
}
time.innerHTML = minutes + ':' + seconds;
console.log(distance);
//if over do something
if (distance <= 0) {
clearInterval(start);
timeName.innerHTML = 'break';
time.innerHTML = 'done';
}
}, 1000)
}
}
//paused
this.paused = function() {
pause.style.display = 'none';
resume.style.display = 'unset';
session = false;
console.log(Boolean(session));
}
//resume
this.resumed = function() {
resume.style.display = 'none';
pause.style.display = 'unset';
session = true;
console.log(Boolean(session));
}
}
As GreatBigBore noted, the answer to your question is debugging. Without debugging you'll have another problem an hour or two from now and find it very difficult to solve. console.log() is a very basic debugging tool; you want to graduate from that quickly. Chrome and Firefox both have great debuggers that let you actually stop the code at any point, view the values of variables, etc. Anytime you have an issue, start with the debugger. Find out what the value of different vars are, find out where the code actually goes step by step, etc. This is a good primer to debugging in Chrome: https://developers.google.com/web/tools/chrome-devtools/javascript/
Good luck!
Edit - one additional note, something that will help you immensely in writing good code is something called "linting". Linting will tell you things like hey you should use === instead of == here. I'd say the industry standard nowadays is ESLint. If you want to learn to write really good, up to date code, set up ESLint :)
I implemented a timer count on my examination page. It is just like the edmodo website. But when you're taking an exam in edmodo, even if you refresh it, the timer is still counting. On my site, if you refresh the page, the timer refresh too. What I want is just like the edmodo which still counting even you refresh the page. Please see my code for your reference.
Note:
I'm using Laravel5.1/jQuery
$(document).ready(function() {
// Quiz timer (Start of Quiz)
var quiz_timer = $('.quiz-timer').html();
var exact_time = parseInt($('.timer-value').html() - 1);
var hrs_to_spend = parseInt(exact_time / 60);
var mins_to_spend = parseInt(exact_time % 60);
var secs_to_spend = 60;
var timeIsUp = false;
var secs = 0,
mins = 0,
hrs = 0;
var secs_zero, mins_zero, hrs_zero, h_spend_zero, m_spend_zero, s_spend_zero;
var setters = setInterval(function() {
if ($('.quiz-timer').html() != '00:00:01') {
if (secs_to_spend > 0) {
secs_to_spend--;
}
if (secs_to_spend <= 0) {
mins_to_spend--;
secs_to_spend = 59;
}
if (mins_to_spend < 0) {
hrs_to_spend--;
mins_to_spend = 59;
}
} else {
$('.quiz-timer').html('00:00:00')
clearInterval(setters);
$('.answer-quiz > .panel-info').attr('class', 'panel panel-danger');
swal({
title: "Oops!",
text: "Time is up.",
type: "warning"
});
timeIsUp = true;
setTimeout(function() {
$('#submitAttempt').click();
}, 2000);
return false;
}
h_spend_zero = (hrs_to_spend < 10) ? '0' : '';
m_spend_zero = (mins_to_spend < 10) ? '0' : '';
s_spend_zero = (secs_to_spend < 10) ? '0' : '';
$('.quiz-timer').html(h_spend_zero + hrs_to_spend + ':' + m_spend_zero + mins_to_spend + ':' + s_spend_zero + secs_to_spend);
if (!timeIsUp) {
secs++;
if (secs == 60) {
mins++;
secs = 0;
}
if (mins == 60) {
hrs++;
mins = 0;
}
hrs_zero = (hrs < 10) ? '0' : '';
mins_zero = (mins < 10) ? '0' : '';
secs_zero = (secs < 10) ? '0' : '';
$('#timeTaken').val(hrs_zero + hrs + ':' + mins_zero + mins + ':' + secs_zero + secs);
}
}, 1000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Original Value: <span class="timer-value">110</span><br><br>
Timer: <span class="quiz-timer"></span><br>
Time Spent: <input type="text" name="time_taken" id="timeTaken" value="">
Set time expiration deadline as a date-time. Count remaining time, not spent time.
For example if date-time now is "2017-08-22 08:00:01" (the starting time of the exam), and you want the expiration after 1 hour, set the date-time deadline to "2017-08-22 09:00:01" (this should be returned from the server). Then let the javascript counter recalculate the difference between the time now and the deadline with refresh rate (interval) every second.
use local storage
1) save the last time in localstorage
like
window.onbeforeunload= function(){
localStorage.setItem("lastTime", timevalue);
}
2) upon reload if time exists in localstorage like
savedTime = localStorage.getItem("lastTime");
mytimer.continueFrom(savedTime)
pick it up from that point and continue the timer
have a look here about localstorage
Local Storage
You can't achieve that with Javascript, javascript code has a session life time, if you close the tab it terminates all the resources that the tab used, including javascript.
You can try to overcome that via saving the counter + current time in local storage, and whenever you start your JS code, check if there are those values in the local storage, and init the counter value with them.
let counter = prevSavedCounter + (new Date()).getTime() - savedTime;
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'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.
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.