New to JS. I am trying to add a button to my page that says, "Start Game". When clicked, a countdown timer function starts executing, changing the text on the button every second from 10 down to 0, at which point the button will say "Time's Up!"
I have used the setInterval method to get the countdown timer working, but it starts running as soon as the page loads (run code snippet below to see in action).
I am trying to prevent it from running until the button is clicked. Here is my html button (with the property "onclick="startTimer()"), and the JS:
var timeleft = 10
var gameTimer = setInterval(startTimer, 1000);
function startTimer () {
if (timeleft <= 0) {
clearInterval(gameTimer);
document.getElementById("countdown").innerHTML = "Time's Up!";
} else {
document.getElementById("countdown").innerHTML = timeleft;
}
timeleft -=1;
};
<button id="countdown" onclick="startTimer()">Start Game</button>
I have tried adding a preventDefault to stop it from running on load, but nothing changed. How can I prevent the function from running until it hears the click event?
The core of the answer here is to move the invocation of setInterval() inside the function that's called when your button is clicked.
However, you really should re-factor this code a bit, both for readability as well as function. For example, I would expect startTimer() to do exactly what it says it does - start the timer, nothing more. However it seems that this function handles the decrement of timeleft.
The reason the suggestions in the comments above may not make sense at the moment is because you don't want to call setInterval() every time you want to decrease timeleft. Break this functionality out into discrete functions and save yourself the headache.
var timeleft = 10
var gameTimer;
function startTimer() {
gameTimer = setInterval(tick, 1000);
};
function tick() {
if (timeleft <= 0) {
clearInterval(gameTimer);
document.getElementById("countdown").innerHTML = "Time's Up!";
} else {
document.getElementById("countdown").innerHTML = timeleft;
}
timeleft -= 1;
}
<button id="countdown" onclick="startTimer()">Start Game</button>
Related
Sorry this is going to take a bit of explaining so you know what I'm trying to do here...
I'm having trouble with a timer function. Basically when the user hits the page, an Ajax request is made, the result of which starts a timer function. They have a certain amount of time in which to make a payment (this is a block chain based payment app, payment is made via an external wallet - no user input is required on the payment page at all, no buttons to click etc). If the timer runs out the payment box resets.
But if the persistent Ajax calls running in the background find the users payment on the block chain I need to kill the timer as it is no longer required, but I need to keep the payment box open while the confirmations are being monitored until the transaction is complete.
The trouble is I can't alter the already running timer function. I've tried every way possible I could think of but nothing stops the original function from running and ultimately resetting the payment box while the transaction is ongoing (waiting for confirmations).
I have been reading about wrapping the timer function in an object and adding a listener but everything I found seemed really confusing to me.
Below is the relevant code.
The function that starts the timer is being started by the Ajax response from another function...
myTimer(expiry);
The expiry variable being passed is vital as it sets an intial on / off state for the timer (whether to display it or not from the first response). So I need to keep that.
This is the timer function...
function myTimer(expiry) {
// If expiry set to 0 don't use the timer
if (expiry === 0) {
$('#timer').hide();
return;
}
var start = new Date();
var timeoutVal = Math.floor(expiry/100);
animateUpdate();
function updateProgress(percentage) {
$('#timerInner').css("width", percentage + "%");
}
function animateUpdate() {
var now = new Date();
var timeDiff = now.getTime() - start.getTime();
var perc = Math.round((timeDiff/expiry)*100);
if (perc <= 100) {
updateProgress(perc);
setTimeout(animateUpdate, timeoutVal);
} else {
// Timer expired, clear box and show buy button again
$("#paymentWrap").empty();
$("#btn-Pay").show();
$("#btn-Pay").prop("disabled", false);
return;
}
}
}
}
This is the part that I need to "kill" on demand via another function coming from another Ajax response...
// Timer expired, clear box and show buy button again
$("#paymentWrap").empty();
$("#btn-Pay").show();
$("#btn-Pay").prop("disabled", false);
return;
Can somebody explain how I can add a variable listener to this function (maybe by creating it as an object?) so that I can change the chunk of code that triggers the bit above to include a new var called cancelled that can be updated elsewhere in the script WHILE this function is running.
if (perc <= 100) {
updateProgress(perc);
setTimeout(animateUpdate, timeoutVal);
if (cancelled === true) {
// Hide the timer div and kill the timer function
$("#timer").hide();
return;
}
} else {
// Timer expired, clear box and show buy button again
.......
I know this was really long winded, apologies upfront, but thanks for reading and looking forward to any help you can offer.
Cheers!
You can define a global variable to reference setTimeout() call and use cleaTimeout()
let timer = null;
let then_ = new Date().getTime() + 10000;
function fn() {
timer = setTimeout(function() {
console.log("doing stuff at " + new Date()
, "time remaining to do stuff:", then_ - new Date().getTime());
if (new Date().getTime() < then_) {
fn()
} else {
done()
}
}, 1000)
}
function done() {
clearTimeout(timer);
timer = null;
console.log("done doing stuff at " + new Date());
}
document.querySelector("button")
.onclick = function() {
if (timer) {
done()
} else {
this.onclick = null;
}
}
fn();
<button>clear timer</button>
The below javascript code auto refresh the page every 10 sec.
My question is how can I reset the timer on mousemove and keypress.
Java-Script
<script type="text/javascript" language="JavaScript">
var secs;
var timerID = null;
var timerRunning = false;
var delay = 1000;
function InitializeTimer(seconds) {
//length of the timer, in seconds
secs = seconds;
StopTheClock();
StartTheTimer();
}
function StopTheClock() {
if (timerRunning)
clearTimeout(timerID);
timerRunning = false;
}
function StartTheTimer() {
if (secs == 0) {
StopTheClock();
window.location.href = window.location.href;
}
else {
document.getElementById("lbltime").innerText = secs + " ";
secs = secs - 1;
timerRunning = true;
timerID = self.setTimeout("StartTheTimer()", delay);
}
}
</script>
Thank you in advance.
If I understood you correctly, something like this (really basic example: the timer is reset on mousemove and keypress):
var elem = document.getElementById("timer"), timeout, startTimer = function timer() {
elem.textContent++;
timeout = setTimeout(timer, 1000)
}
function resetTimer() {
// here you reset the timer...
clearTimeout(timeout);
elem.textContent = -1;
startTimer();
//... and also you could start again some other action
}
document.addEventListener("mousemove", resetTimer);
document.addEventListener("keypress", resetTimer);
startTimer();
<span id="timer">-1</span> - Move cursor or press a key to reset timer.
As I guess, you want to delay page reloading if there was some user activity on the page. In your reload() function you just need to check, if timer's value reached the limit (like 60 seconds). If yes, execute reloading. However, notice, that handling mousemove event can make browser's tab have high CPU usage, if, for example, I just start to move my cursor quickly. You might want to pick some important areas and set handlers on the corresponding elements. For example, keypress event can be listened to only on a comment form or mousemove can be listened to only on a menu or on an article.
PS. Also take into account that
The keypress event is fired when a key is pressed down, and that key normally produces a character value
so, if user presses, for example, ctrl or alt the event will not be fired.
Your code seems a bit too branched out in my opinion, what I would do is simplify it a bit.
window.refreshTimeout = null;
function refreshPage(){
location.reload();
}
function refresh(){
clearTimeout(window.refreshTiemout);
window.refreshTimeout = setTimeout(refreshPage, 2000)
}
window.refreshTimeout = setTimeout(refreshPage, 2000)
window.addEventListener('mousemove', refresh)
<h4>HelloWorld</h4>
As you can see, you attach an event listener to the window for a mouse move (you can attach others too) within which you cancel the previous timeout and start a new one. Initially you of course start a timeout.
Ok coming straight to the point
I have a text box and few other things on a page
if the user is typing in the textbox the page should not refresh otherwise it should refresh after a certain interval
I searched alot and cannot find anything similar
I am new to javascript
Here is a simple example of this. A check runs every 3 seconds. if nothing has been typed in it will refresh, if something has been typed in it will wait 3 seconds before refreshing.
http://jsfiddle.net/9ARrG/
HTML
<input onkeyup="resetTimer = true">
JS
resetTimer = false;
setInterval(function() {
if(!resetTimer) {
location.reload();
}
resetTimer = false;
}, 3000);
Give your input/textarea an id
<input id="textbox" />
// OR
<textarea id="textbox"></textarea>
Then, setup a timer to refresh the page. If there's a change, reset the timer.
var originalTimer = 15000; // here's the original time until page refreshes
var timer = originalTimer; // timer to track whether to refresh page
// now every 1 second, update the timer
setInterval(function() {
timer -= 1000; // timer has gone down 1 sec
// if timer is less than 0, refresh page
if (timer <= 0) window.location.reload();
},1000); // repeat every 1 second (1000 ms)
document.getElementById("textbox").onchange = function() {
// detect textbox changes, reset timer
timer = originalTimer;
}
Use the document.activeElement property to conditionally determine what element has focus.
function refreshPageUnlessFocusedOn (el) {
setInterval(function () {
if(el !== document.activeElement) {
document.location.reload();
}
}, 3000)
}
refreshPageUnlessFocusedOn(document.querySelector('textarea'));
Check out the jsfiddle here for a working sample.
I'm using JSF 1.2 with JBoss 4.2 and Richfaces 3.3.
For my current application I have to build a small panel which always displays a progressbar
and the time in minutes till the session will suspend (user get logged out).
Well, till now all is working fine. I implemented my solution via javascript and that works flawless.
But now I have a big problem with ajax requests. I see currently no solution to get a handler or something which is fired on every ajax request (to reset my progressbar and the minutes till logout).
Here is my code so far:
var timeLeft = document.getElementById('valueObject').value;
var maxTimeoutTime = document.getElementById('valueObject').value;
var intervalID;
function updateProgress() {
var percentageValue = timeLeft / (maxTimeoutTime / 100);
$('form:sessionTimeoutBar').component.setValue(percentageValue);
timeLeft = timeLeft - 1000;
if (timeLeft <= 0){
clearInterval(intervalID);
}
}
function resetProgress() {
alert("CALLED");
timeLeft = document.getElementById('valueObject').value;
$('form:sessionTimeoutBar').component.setValue(100);
clearInterval(intervalID);
intervalID = setInterval(updateProgress, 1000);
}
function startProgress() {
$('form:sessionTimeoutBar').component.enable();
$('form:sessionTimeoutBar').component.setValue(100);
intervalID = setInterval(updateProgress, 1000);
}
timeLeft and maxTimeoutTime are retreived over an hidden input field which gets the information from a managed bean method.
startProgress() is called via onload by the body tag.
I have that Javascript counter:
var x=100;
function timerCountdown()
{
document.getElementById('timer1').value=x;
x--;
t=setTimeout("timerCountdown()",1000);
if (x<-1)
{
document.getElementById('timer1').value='Done!';
clearTimeout(t);
}
}
function stopCounter(){
clearTimeout(t);
x=x+1;
}
Then I use:
<body onFocus='timerCountdown()' onBlur='stopCounter()'>
But the problem is, the countdown doesn't start when the page loads. It waits for me to click on another window and to reFocus on the window again.
So I tried this:
<body onLoad='timerCountdown()' onFocus='timerCountdown()' onBlur='stopCounter()'>
But this time, the countdown goes pretty fast. Probably because timerCOuntdown is called twice every second.
Alternatively, I could just use the onFocus and onBlur in the body tag, but I need a function to trigger the Focus upon body load. Is that possible?
Does anyone have a suggestion to solve this problem?
thanks a lot!
The simple answer is because setTimeout is invoked twice, running timerCountdown() once for two times separately, and continually setting two setTimeout IDs.
This would be what you want:
var x = 100;
var t = 0;
function timerCountdown()
{
if (t == 0) t = setInterval(timerCountdown, 1000);
document.getElementById('timer1').value=x;
x--;
if (x < 0)
{
document.getElementById('timer1').value='Done!';
clearTimeout(t);
ticker = 0;
}
}
function stopCounter()
{
clearTimeout(t);
t = 0;
x++;
}
setInterval is much more suited for countdown timers, and things you need to run continually since setTimeout only runs once and you need to keep on calling it.
Edit: This fixes the initial rapid triggering of the timer on Firefox.
Remove the handler from <body onload= and add this to the end of the script block above:
t = setInterval(timerCountdown, 1000);