SetInterval not refreshing HTML in Chrome - javascript

I'm trying to implement a script that essentially counts down from 30 seconds to 0, and at 0, redirects to the homepage. However, I noticed that my script only works on Firefox but not Chrome and Safari. On these browsers, the counter remains "stuck" at 30 seconds—never refreshing the HTML, but the redirect works fine. Not sure if I'm doing something wrong or if setInterval is not the right method for this kind of thing.
<script>
var seconds = 31;
var counter = setInterval("timer()", 1000);
function timer() {
seconds = seconds - 1;
if (seconds < 0) {
setTimeout("location.href='http://www.homepage.com';", 100);
return;
}
updateTimer();
}
function updateTimer() {
document.getElementById('timer').innerHTML = "Redirecting in " + " " + seconds + " " + "seconds";
}
</script>
Thanks in advance!
EDIT: So weirdly enough, my code (and all of yours) is working on JSFiddle, but it's just failing to "repaint" the HTMLinner when it's actually rendering the page. The seconds are changing fine (I outputted them to the console), the changes just aren't rendering.
Final Edit: This problem basically resulted from invalid CSS. I believe—the counter was running above the photo and I set the span to relative positioning with a higher z-index and top and bottom elements. I don't believe this is acceptable for something that is not a block.

Here's a working sample:
(function() { // wrapper for locals
var timer = document.getElementById("timer"),
seconds = 5,
counter = setInterval(function() {
if (--seconds < 1) {
clearInterval(counter);
timer.innerHTML = "Redirecting now...";
setTimeout(function() {
location.href = 'http://www.homepage.com';
}, 500);
} else {
timer.innerHTML = timer.innerHTML.replace(/\d+/, seconds);
}
}, 1000);
})();
<div id="timer">Redirecting in 5 seconds</div>
​
​

Here is a cleaner implementation with fewer defined functions (with demo):
<span id='timer'></span>
<script>
var seconds = 31;
setInterval(function() {
seconds = seconds - 1;
if (seconds < 0) {
setTimeout(function() {document.getElementById('timer').innerHTML = "redirecting..."}, 100);
return;
}
updateTimer();
}, 1000);
function updateTimer() {
document.getElementById('timer').innerHTML = "Redirecting in " + + seconds + " seconds";
}
<script>
Of course every JavaScript programmer should any opportunity to point out that "eval is evil" which includes passing a string to setInterval and setTimeout :)

Change your function to a variable, that worked for me:
<script>
var seconds = 31;
var counter = setInterval(timer, 1000);
var timer = function() {
seconds = seconds - 1;
if (seconds < 0) {
setTimeout("location.href='http://www.homepage.com';", 100);
return;
}
updateTimer();
}
function updateTimer() {
document.getElementById('timer').innerHTML = "Redirecting in " + " " + seconds + " " + "seconds";
}
</script>

Related

Showing multiple timer function in Angular.js

I am trying to display two timer on a webpage with different start times.
First timer only shows for 5 seconds and then after 10 seconds I need to show timer2.
I am very new to Angular and have put together following code.
It seems to be working fine except when the settimeout is called the third time it doesn't work correctly and it starts going very fast.
Controller
// initialise variables
$scope.tickInterval = 1000; //ms
var min ='';
var sec ='';
$scope.ti = 0;
$scope.startTimer1 = function() {
$scope.ti++;
min = (Math.floor($scope.ti/60)<10)?("0" + Math.floor($scope.ti/60)):(Math.floor($scope.ti/60));
sec = $scope.ti%60<10?("0" + $scope.ti%60):($scope.ti%60);
$scope.timer1 = min + ":" + sec;
mytimeout1 = $timeout($scope.startTimer1, $scope.tickInterval); // reset the timer
}
//start timer 1
$scope.startTimer1();
$scope.$watch('timer1',function(){
if($scope.timer1 !=undefined){
if($scope.timer1 =='00:05'){
$timeout.cancel(mytimeout1);
setInterval(function(){
$scope.startTimer2()
$scope.ti = 0;
},1000)
}
}
})
//start timer 2 after 2 mins and 20 seconds
$scope.startTimer2 = function() {
$scope.ti++;
min = (Math.floor($scope.ti/60)<10)?("0" + Math.floor($scope.ti/60)):(Math.floor($scope.ti/60));
sec = $scope.ti%60<10?("0" + $scope.ti%60):($scope.ti%60);
$scope.timer2 = min + ":" + sec;
mytimeout2 = $timeout($scope.startTimer2, $scope.tickInterval);
}
$scope.$watch('timer2',function(){
if($scope.timer2 !=undefined){
if($scope.timer2 =='00:05'){
$timeout.cancel(mytimeout2);
setInterval(function(){
$scope.startTimer1();
$scope.ti = 0;
},1000)
}
}
})
In my view I simply have
<p>{{timer1}}</p>
<p>{{timer2}}</p>
You're basically starting multiple startTimer function so it's adding up. If i understood your problem well you don't even need to have all those watchers and timeouts.
You just can use $interval this way :
$scope.Timer = $interval(function () {
++$scope.tickCount
if ($scope.tickCount <= 5) {
$scope.timer1++
} else {
$scope.timer2++
if ($scope.tickCount >= 10)
$scope.tickCount = 0;
}
}, 1000);
Working fiddle

countdown timer reset on each page

i have an exam system in php on which i have set a countdown timer with the help of javascript. the questions are displayed one by one on the page and the timer reset to the initial position when the next question comes also the page refreshes itself. I want to set the timer on the decreasing state so is should not start again and again to the initial time. the code is the following i have written for the timer. please anyone help me to sort it out.
<div id="test_time">
<script language="javascript" type="text/javascript">
var min = 10;
var sec = 0;
var timer;
var timeon = 0;
function ActivateTimer() {
if (!timeon) {
timeon = 1;
Timer();
}
}
function Timer() {
var _time = "Time Left : Minutes: " + min + " Seconds: " + sec;
document.getElementById("test_time").innerHTML =_time;
if (_time != "Time Left : Minutes: 0 Seconds: 0") {
if (sec == 0) {
min = min - 1;
sec = 59;
} else {
sec = sec - 1;
}
timer = setTimeout("Timer()", 1000);
}
else {
alert('Test Time Over.. Click Ok to get Results.');
window.location = "result.php";
}
}
</script>
</div>
First you must understand the concept of Jquery while working with the countdown timer and Quiz like PHP project.
You have to follow the following process in the System:
You have to load the question in AJAX.
You must have the div which loads the timer at the page load after the login is being done.
The timer div must not be loaded since the jquery will be keep loading if the page reloads again.
Only once the page has to be loaded that is after the login is done and after that the page should not be loaded and it has to changed inly with the help of AJAX.
Since if the question is loaded over the AJAX only the question div alone will be loaded and that to with AJAX and all the other part of the page will remain the same and you can maintain the timer in a correct manner.
Hope so you might be clear with the Explanations.
Happy Coding :)
Well , the above answer is the proper approach to the problem but still if you want it to work as it is, then you can prefer local Storage Variables.
Let this be home.php
<div id="test_time">
<script type="text/javascript">
var timer;
localStorage.min=10;
localStorage.sec=10;
var timeon = 0;
function ActivateTimer() {
if (!timeon) {
timeon = 1;
Timer();
}
}
function Timer() {
var _time = "Time Left : minutes: " + localStorage.min + " seconds: " + localStorage.sec;
document.getElementById("test_time").innerHTML =_time;
if (_time != "Time Left : minutes: 0 seconds: 0") {
if (localStorage.sec == 0) {
localStorage.min = localStorage.min - 1;
localStorage.sec = 59;
} else {
localStorage.sec = localStorage.sec - 1;
}
timer = setTimeout("Timer()", 1000);
}
else {
alert('Test Time Over.. Click Ok to get Results.');
window.location = "result.php";
}
}
ActivateTimer();
</script>
</div>
<div>
Next Question
</div>
Let this be next_question_1.php
<div id="test_time">
<script type="text/javascript">
function Timer() {
var _time = "Time Left : minutes: " + localStorage.min + " seconds: " + localStorage.sec;
document.getElementById("test_time").innerHTML =_time;
if (_time != "Time Left : minutes: 0 seconds: 0") {
if (localStorage.sec == 0) {
localStorage.min = localStorage.min - 1;
localStorage.sec = 59;
} else {
localStorage.sec = localStorage.sec - 1;
}
timer = setTimeout("Timer()", 1000);
}
else {
alert('Test Time Over.. Click Ok to get Results.');
window.location = "result.php";
}
}
Timer();
</script>
</div>
<div>
<a href="next_question_2.php">Next Question
</div>
Since they are local Storage variables they carry on to next pages until you clear the cookies, you may add as many pages you want. This solves your problem but, I don't recommend such approach. AJAX is the proper way to do it. :)

Timer keeps getting faster on every reset

The timer keeps getting faster every time I reset it. I'm thinking I need to use clearTimeout but am unsure about how to implement it. Here's the code:
$(function(){
sessionmin = 25;
$("#sessionMinutes").html(sessionmin);
$("#circle").click(function() {
timeInSeconds = sessionmin * 60;
timeout();
});
})
function timeout(){
setTimeout(function () {
if (timeInSeconds > 0) {
timeInSeconds -= 1;
hours = Math.floor(timeInSeconds/3600);
minutes = Math.floor((timeInSeconds - hours*3600)/60);
seconds = Math.floor(timeInSeconds - hours*3600 - minutes*60);
$("#timer").html(hours + ":" + minutes + ":" + seconds);
}
timeout();
}, 1000);
}
You have to define your setTimeout as a variable to reset it.
See Fiddle
var thisTimer; // Variable declaration.
$(function(){
sessionmin = 25;
$("#sessionMinutes").html(sessionmin);
$("#circle").click(function(){
clearTimeout(thisTimer); // Clear previous timeout
timeInSeconds = sessionmin * 60;
timeout();
});
})
function timeout(){
thisTimer = setTimeout(function () { // define a timeout into a variable
if(timeInSeconds>0){
timeInSeconds-=1;
hours = Math.floor(timeInSeconds/3600);
minutes = Math.floor((timeInSeconds - hours)/60);
seconds = (timeInSeconds - hours*3600 - minutes*60)
$("#timer").html(hours + ":" + minutes + ":" + seconds);
}
timeout();
}, 1000);
}
You should: use setInterval instead of setTimeout, return the interval id that setInterval generates, clear that interval before you restart it. Here is an example: https://jsfiddle.net/8n2b7x0s/
$(function(){
var sessionmin = 25;
var intervalId = null;
$("#sessionMinutes").html(sessionmin);
$("#circle").click(function() {
timeInSeconds = sessionmin * 60;
// clear the current interval so your code isn't running multiple times
clearInterval(intervalId);
// restart the timer
intervalId = run();
});
})
function run(){
return setInterval(function () {
if(timeInSeconds>0){
timeInSeconds-=1;
hours = Math.floor(timeInSeconds/3600);
minutes = Math.floor((timeInSeconds - hours)/60);
seconds = (timeInSeconds - hours*3600 - minutes*60)
$("#timer").html(hours + ":" + minutes + ":" + seconds);
}
}, 1000);
}

Executing setTimeout() in loop takes effect only in the first iteration [duplicate]

I'm trying to make a few things scroll down the screen in javascript, however, upon execution, it just says a little and displays everything at once. So it's not clearing with the $("#Menu").html('') function and the setTimeout(function {},500) is just setting a timeout for the entire page instead of the code segment.
var MenuData = [
{'Name':'pictures','x':'30'},
{'Name':'blog','x':'50'},
{'Name':'contact','x':'42'}
]
;
var PositionArray = new Array();
$(document).ready(function () {
for (var count = 0; count < 1000; count++) {
$("#Menu").html('');
if (PositionArray[count] != null) {
PositionArray[count]++;
} else {
PositionArray[count] = 0;
}
setTimeout(function () {
for (var i in MenuData) {
$("#Menu").append('<div style="position:relative; left:' + MenuData[i].x + 'px; top:' + PositionArray[i] + 'px; ">123</div>');
}
}, 500);
}
});
Here's the fiddle: http://jsfiddle.net/LbjUP/
Edit: There was a little bit of error in the code that doesn't apply to the question. Here's the new one: http://jsfiddle.net/LbjUP/1/, I just moved PositionArray[count] to the setTimeout function as PositionArray[i]
As stated in the comments, you are creating 1000 timeouts for 500 ms at the same time - after 500 ms all of them will be executed. What you want is to increase the timeout for every scheduled function:
setTimeout(function() {
// do something
}, count * 500);
However, creating 1000 timeouts at once is not a that good idea. It would be better to use setInterval or call setTimeout "recursively" until a count of 1000 is reached, so that you only have one active timeout at a time.
var count = 0;
function update() {
// do something
if (++count < 1000)
setTimeout(update, 500);
// else everything is done
}
update();
Also, if you intend to create timeouts in a loop, be sure to be familiar with closures and their behavior when accessing counter variables after the loop ran.
Try
function recurse ( cnt ) {
for (var i in MenuData) {
$("#Menu").append('<div style="position:relative; left:' + MenuData[i].x + 'px; top:' + PositionArray[i] + 'px; ">123</div>');
}
if (cnt < 1000){
setTimeout(function () { recurse(cnt + 1); }, 500);
}
}
$("#Menu").html('');
if (PositionArray[count] != null) {
PositionArray[count]++;
} else {
PositionArray[count] = 0;
}
recurse(0);
You can also use setInterval
let i = 0;
const interval = setInterval(() => {
console.log(i);
i++;
if (i >= 10) {
clearInterval(interval);
}
}, 1000);`

Where do I place my "document.getElementById("").innerHTML = "";" Within my Javascript?

At the moment I am creating an on screen timer in javascript. This is the code for my timer:
var i = 30;
function startTimer() {
var countdownTimer = setInterval(function() {
console.log(i);
i = i - 1;
if (i < 0) {
clearInterval(countdownTimer);
}
}, 1000);
}
I am just wondering where I should place my document.getElementById("time-remaining").innerHTML = "Time Remaining:" + i;
I am also wondering if the above document.getElementById is correct (will it be displayed as a onscreen timer or will it fail or something)?
Thanks in advanced.
Try this:
var i = 30;
function startTimer() {
var countdownTimer = setInterval(function () {
console.log(i);
i = i - 1;
if (i < 0) {
clearInterval(countdownTimer);
return; //This will prevent -1 to be written to html
}
document.getElementById("time-remaining").innerHTML = "Time Remaining:" + i;
}, 1000);
}
startTimer();
Dont forget to call the function.
Demo: http://jsfiddle.net/GCu2D/842/
You can put the
document.getElementById("time-remaining").innerHTML = "Time Remaining:" + i;
After the startTimer function or really anywhere.
And yes thedocument.getElementById is correct, if your html id is the same one as in javascript.

Categories

Resources