Clear timeout that's active - javascript

I have a jQuery ajax where I use setTimeout(). Sometimes, the user triggers the ajax multiple times, before the setTimeout() has kicked off.
So is it possible to clear an active version of the setTimeout() that was triggered previously by adding clearTimeout() like this:
clearTimeout(time);
var time = setTimeout(function() {
$('#hello').fadeOut();
},2600);
Or maybe I need to add some form of global variable?

Depending on what you're doing you may want to act on the first click and ignore subsequent clicks until the first one is finished, or you way want to reset the timer and only act 2.6 seconds after the last click... I gave examples of both, let me know if anything needs clarification..
(function() {
let time, btn = document.getElementById('btn1');
btn.onclick = function() {
if (time) clearTimeout(time);
time = setTimeout(function() {
alert("what the stink?!");
}, 2600);
}
})();
(function() {
let time, btn = document.getElementById('btn2');
btn.onclick = function() {
if (time) return;
time = setTimeout(function() {
alert("what the butts?!");
time = null;
}, 2600);
};
})();
<button id=btn1>Only reacts to last press</button>
<button id=btn2>Only reacts to first press</button>

Here's a quick example which answers your question and illustrates the wonder of closure.
document.getElementById('inputBox').addEventListener('keyup', Delay());
function MyFunction(){
console.log(this.value);
}
function Delay(){
var timer = 0;
return function(){
clearTimeout(timer);
timer = setTimeout(MyFunction.bind(this), 1000);
}
}
https://jsfiddle.net/tlynch001/7y3vnfjn/

Related

Javascript timer - How do I prevent the timer from speeding up each time .deck is clicked?

I am building a memory card game. the class .deck represents a deck of cards. Each time I click a card the timer speeds up. How do I prevent the timer from speeding up?
function startTimer() {
$(".deck").on("click", function () {
nowTime = setInterval(function () {
$timer.text(`${second}`)
second = second + 1
}, 1000);
});
}
You start multiple intervals, one each click. You probably should just start one. If you want to start it for the first card that is clicked:
function startTimer() {
// Maybe remove old timer? Should happen somewhere in your code.
// Possibly "stopTimer" if you have such a function.
clearInterval(nowTime);
let started = false;
$(".deck").on("click", function () {
if (started) return;
nowTime = setInterval(function () {
$timer.text(`${second}`)
second = second + 1
}, 1000);
started = true;
});
}
That code should have some more cleanup, though. Otherwise you accumulate a lot of dead event listeners.
(Furthermore, i believe that jQuery should never be used.)
You need to stop the previous timer before starting a new one because, if you don't, you wind up with multiple timer callback functions all executing one immediately after the other, which gives the illusion that your single timer is speeding up.
function startTimer() {
$(".deck").on("click", function () {
clearInterval(nowTime); // Stop previous timer
nowTime = setInterval(function () {
$timer.text(`${second}`);
second = second + 1;
}, 1000);
});
}
Another way to deal with this is to only allow the click event callback to run the very first time the button is clicked:
function startTimer() {
$(".deck").on("click", timer);
function timer() {
nowTime = setInterval(function () {
$timer.text(`${second}`);
second = second + 1;
}, 1000);
$(".deck").off("click", timer); // Remove the click event handler
}
}

jQuery Fade object after 20 seconds of inactivity

I want to fade out a div if a user hasn't made a mouse click for 20 seconds.
I have the following code:
if($('.main-popup2').is(":visible")){
setTimeout(function() {
$('.main-popup2').fadeOut('fast');
}, 20000);
}
Problem is I don't know how to reset the setTimeout after detecting a user mouse click.
Thanks!
The .setTimeout() method actually returns a reference to the timer it creates. This reference can be used in .clearTimeout to stop the timer before it executes.
Here is an example of how to use this:
var timer;
if($('.main-popup2').is(":visible")){
// create the timer and save its reference
timer = setTimeout(function() {
$('.main-popup2').fadeOut('fast');
}, 20000);
}
// when clicking somewhere on the page, stop the timer
$(document).click(function() {
clearTimeout(timer);
}):
var timeout = null;
var fadeElement = $('.main-popup2');
function fader() {
if(null !== timeout) {
clearTimeout(timeout);
}
fadeElement.stop();
timeout = setTimeout(function () {fadeElement.fadeOut('fast');}, 2000);
}
$(document).click(fader);
fader();
Use delay function.
(window).click(function () {
$('.main-popup2').delay(6000).fadeOut(300);
}
Each click restart 6 seconds, after it .main-popup2 fadeout if there isn't

On keypress, when stop after X seconds call function

I have a text input and a textarea and I'm passing the value from the input to the textarea. I am trying to do, when you type something in the input and you stop, after 2 seconds show the values to the textarea.
In this example the textarea gets the input's value instantly:
http://jsfiddle.net/DXMG6/
So i want, when you type and stop, after 2 seconds give the value.
How can I achieve this? I tried to use setTimeout but when the 2 seconds pass, then it keeps getting the value instantly. So basically it works for the first 2 seconds.
You have to reset the timer everytime the user presses the key again:
jQuery(function($){
function changeFn(){
alert('Changed');
}
var timer;
$("#string").bind("keyup", function(){
clearTimeout(timer);
timer = setTimeout(changeFn, 2000)
});
});
Once i made this plugin called bindDelay for jQuery:
$.fn.bindDelay = function( eventType, eventData, handler, timer ) {
if ( $.isFunction(eventData) ) {
timer = handler;
handler = eventData;
}
timer = (typeof timer === "number") ? timer : 300;
var timeouts;
$(this).bind(eventType, function(event) {
var that = this;
clearTimeout(timeouts);
timeouts = setTimeout(function() {
handler.call(that, event);
}, timer);
});
};
Used like a normal bind method but the last argument is the delay before firing the handler (in mil sec):
$("input").bindDelay('keyup', function() {
$("textarea").text( $(this).val() );
}, 2000);
See fiddle: http://jsfiddle.net/c82Ye/2/
And you unbind and trigger it like normal:
$("input").unbind("keyup");
$("input").trigger("keyup");
setTimeout returns an ID of the "job". what you have to do is to clearTimeout(id) every type and setTimeout again:
var tID = null;
onclick() {
if (tID !== null) clearTimeout(tID);
tID = setTimeout(function() { /*Do domething*/ }, 2000);
}
What you need to do is set a timeout, and save the resulting timeout id. Then you need to check if the timeout id has been saved at each keypress. If the timeout is set, clear the timeout and reset it. Something like this:
var timeoutId = null;
var myFunc = function() {
timeoutId = null;
// Do stuff
};
var myEventHandler = function() {
if (timeoutId) {
window.clearTimeout(timeoutId);
}
timeoutId = window.setTimeout(myFunc, 2000);
};
...or check the updated fiddle:
http://jsfiddle.net/DXMG6/5/
I've updated your fiddle
This will update the textarea value 2 seconds after you end editing the text.
The relevant part is this: we keep a reference to a timeout, when the keyup event is fired we clear the previous timeout and we start a new timeout, that will fire in 2 seconds.
var timeout = null;
$("#string").on("keyup keypress paste mouseup", function () {
clearTimeout(timeout);
timeout = setTimeout(function() {
// ... your code here
}, 2000);
});
Try something like this. Use setTimeout, but each time a key is pressed, reset the timer and start over...
http://jsfiddle.net/DXMG6/10/
var textTimer=null;
$("#string").on("keyup keypress paste mouseup", function () {
if (textTimer) clearTimeout(textTimer);
textTimer = setTimeout(function(){
var a = $('#string').val();
$('#rdonly').html(a);
}, 2000);
});
$('.btn').click(function() {
$('#rdonly').text('');
$('#string').val('');
});
You just need to modify your code as follows:
var timeoutId = 0;
$("#string").on("keyup keypress paste mouseup", function () {
var a = $('#string').val();
// Cancel existing timeout, if applicable
if (timeoutId > 0) {
window.clearTimeout(timeoutId);
}
// Start a timeout for 2 seconds- this will be cancelled above
// if user continues typing
timeoutId = window.setTimeout(function () {
$('#rdonly').html(a);
}, 2000);
});

setTimeout / clearTimeout problems

I try to make a page to go to the startpage after eg. 10sec of inactivity (user not clicking anywhere). I use jQuery for the rest but the set/clear in my test function are pure javascript.
In my frustation I ended up with something like this function that I hoped I could call on any click on the page. The timer starts fine, but is not reset on a click. If the function is called 5 times within the first 10 seconds, then 5 alerts will apear... no clearTimeout...
function endAndStartTimer() {
window.clearTimeout(timer);
var timer;
//var millisecBeforeRedirect = 10000;
timer = window.setTimeout(function(){alert('Hello!');},10000);
}
Any one got some lines of code that will do the trick?
- on any click stop, reset and start the timer.
- When timer hits eg. 10sec do something.
You need to declare timer outside the function. Otherwise, you get a brand new variable on each function invocation.
var timer;
function endAndStartTimer() {
window.clearTimeout(timer);
//var millisecBeforeRedirect = 10000;
timer = window.setTimeout(function(){alert('Hello!');},10000);
}
The problem is that the timer variable is local, and its value is lost after each function call.
You need to persist it, you can put it outside the function, or if you don't want to expose the variable as global, you can store it in a closure, e.g.:
var endAndStartTimer = (function () {
var timer; // variable persisted here
return function () {
window.clearTimeout(timer);
//var millisecBeforeRedirect = 10000;
timer = window.setTimeout(function(){alert('Hello!');},10000);
};
})();
That's because timer is a local variable to your function.
Try creating it outside of the function.
A way to use this in react:
class Timeout extends Component {
constructor(props){
super(props)
this.state = {
timeout: null
}
}
userTimeout(){
const { timeout } = this.state;
clearTimeout(timeout);
this.setState({
timeout: setTimeout(() => {this.callAPI()}, 250)
})
}
}
Helpful if you'd like to only call an API after the user has stopped typing for instance. The userTimeout function could be bound via onKeyUp to an input.
Not sure if this violates some good practice coding rule but I usually come out with this one:
if(typeof __t == 'undefined')
__t = 0;
clearTimeout(__t);
__t = setTimeout(callback, 1000);
This prevent the need to declare the timer out of the function.
EDIT: this also don't declare a new variable at each invocation, but always recycle the same.
Hope this helps.
Practical example Using Jquery for a dropdown menu !
On mouse over on #IconLoggedinUxExternal shows div#ExternalMenuLogin and set time out to hide the div#ExternalMenuLogin
On mouse over on div#ExternalMenuLogin it cancels the timeout.
On mouse out on div#ExternalMenuLogin it sets the timeout.
The point here is always to invoke clearTimeout before set the timeout, as so, avoiding double calls
var ExternalMenuLoginTO;
$('#IconLoggedinUxExternal').on('mouseover mouseenter', function () {
clearTimeout( ExternalMenuLoginTO )
$("#ExternalMenuLogin").show()
});
$('#IconLoggedinUxExternal').on('mouseleave mouseout', function () {
clearTimeout( ExternalMenuLoginTO )
ExternalMenuLoginTO = setTimeout(
function () {
$("#ExternalMenuLogin").hide()
}
,1000
);
$("#ExternalMenuLogin").show()
});
$('#ExternalMenuLogin').on('mouseover mouseenter', function () {
clearTimeout( ExternalMenuLoginTO )
});
$('#ExternalMenuLogin').on('mouseleave mouseout', function () {
clearTimeout( ExternalMenuLoginTO )
ExternalMenuLoginTO = setTimeout(
function () {
$("#ExternalMenuLogin").hide()
}
,500
);
});
This works well. It's a manager I've made to handle hold events. Has events for hold, and for when you let go.
function onUserHold(element, func, hold, clearfunc) {
//var holdTime = 0;
var holdTimeout;
element.addEventListener('mousedown', function(e) {
holdTimeout = setTimeout(function() {
func();
clearTimeout(holdTimeout);
holdTime = 0;
}, hold);
//alert('UU');
});
element.addEventListener('mouseup', clearTime);
element.addEventListener('mouseout', clearTime);
function clearTime() {
clearTimeout(holdTimeout);
holdTime = 0;
if(clearfunc) {
clearfunc();
}
}
}
The element parameter is the one which you hold. The func parameter fires when it holds for a number of milliseconds specified by the parameter hold. The clearfunc param is optional and if it is given, it will get fired if the user lets go or leaves the element. You can also do some work-arounds to get the features you want. Enjoy! :)
<!DOCTYPE html>
<html>
<body>
<h2>EJEMPLO CONOMETRO CANCELABLE</h2>
<button onclick="inicioStart()">INICIO</button>
<input type="text" id="demostracion">
<button onclick="finStop()">FIN</button>
<script>
let cuenta = 0;
let temporalTiempo;
let statusTime = false;
function cronometro() {
document.getElementById("demostracion").value = cuenta;
cuenta++;
temporalTiempo = setTimeout(cronometro, 500);
}
function inicioStart() {
if (!Boolean(statusTime)) {
statusTime = true;
cronometro();
}
}
function finStop() {
clearTimeout(temporalTiempo);
statusTime = false;
}
</script>
</body>
</html>

Resetting a setTimeout

I have the following:
window.setTimeout(function() {
window.location.href = 'file.php';
}, 115000);
How can I, via a .click function, reset the counter midway through the countdown?
You can store a reference to that timeout, and then call clearTimeout on that reference.
// in the example above, assign the result
var timeoutHandle = window.setTimeout(...);
// in your click function, call clearTimeout
window.clearTimeout(timeoutHandle);
// then call setTimeout again to reset the timer
timeoutHandle = window.setTimeout(...);
clearTimeout() and feed the reference of the setTimeout, which will be a number. Then re-invoke it:
var initial;
function invocation() {
alert('invoked')
initial = window.setTimeout(
function() {
document.body.style.backgroundColor = 'black'
}, 5000);
}
invocation();
document.body.onclick = function() {
alert('stopped')
clearTimeout( initial )
// re-invoke invocation()
}
In this example, if you don't click on the body element in 5 seconds the background color will be black.
Reference:
https://developer.mozilla.org/en/DOM/window.clearTimeout
https://developer.mozilla.org/En/Window.setTimeout
Note: setTimeout and clearTimeout are not ECMAScript native methods, but Javascript methods of the global window namespace.
You will have to remember the timeout "Timer", cancel it, then restart it:
g_timer = null;
$(document).ready(function() {
startTimer();
});
function startTimer() {
g_timer = window.setTimeout(function() {
window.location.href = 'file.php';
}, 115000);
}
function onClick() {
clearTimeout(g_timer);
startTimer();
}
var myTimer = setTimeout(..., 115000);
something.click(function () {
clearTimeout(myTimer);
myTimer = setTimeout(..., 115000);
});
Something along those lines!
For NodeJS it's super simple:
const timeout = setTimeout(...);
timeout.refresh();
From the docs:
timeout.refresh()
Sets the timer's start time to the current time, and reschedules the timer to call its callback at the previously specified duration adjusted to the current time. This is useful for refreshing a timer without allocating a new JavaScript object.
But it won't work in JavaScript because in browser setTimeout() returns a number, not an object.
This timer will fire a "Hello" alertbox after 30 seconds. However, everytime you click the reset timer button it clears the timerHandle then re-sets it again. Once it's fired, the game ends.
<script type="text/javascript">
var timerHandle = setTimeout("alert('Hello')",3000);
function resetTimer() {
window.clearTimeout(timerHandle);
timerHandle = setTimeout("alert('Hello')",3000);
}
</script>
<body>
<button onclick="resetTimer()">Reset Timer</button>
</body>
var redirectionDelay;
function startRedirectionDelay(){
redirectionDelay = setTimeout(redirect, 115000);
}
function resetRedirectionDelay(){
clearTimeout(redirectionDelay);
}
function redirect(){
location.href = 'file.php';
}
// in your click >> fire those
resetRedirectionDelay();
startRedirectionDelay();
here is an elaborated example for what's really going on http://jsfiddle.net/ppjrnd2L/
i know this is an old thread but i came up with this today
var timer = []; //creates a empty array called timer to store timer instances
var afterTimer = function(timerName, interval, callback){
window.clearTimeout(timer[timerName]); //clear the named timer if exists
timer[timerName] = window.setTimeout(function(){ //creates a new named timer
callback(); //executes your callback code after timer finished
},interval); //sets the timer timer
}
and you invoke using
afterTimer('<timername>string', <interval in milliseconds>int, function(){
your code here
});
$(function() {
(function(){
var pthis = this;
this.mseg = 115000;
this.href = 'file.php'
this.setTimer = function() {
return (window.setTimeout( function() {window.location.href = this.href;}, this.mseg));
};
this.timer = pthis.setTimer();
this.clear = function(ref) { clearTimeout(ref.timer); ref.setTimer(); };
$(window.document).click( function(){pthis.clear.apply(pthis, [pthis])} );
})();
});
To reset the timer, you would need to set and clear out the timer variable
$time_out_handle = 0;
window.clearTimeout($time_out_handle);
$time_out_handle = window.setTimeout( function(){---}, 60000 );

Categories

Resources