How to clear timeout in javascript? - javascript

Why is this not working?
$('#plugbot-likebox').hover(function () {
$('#plugbot-ui').slideDown();
$('#ZobrazNastavenia').fadeOut("fast");
}, function () {
toUi = setTimeout(function(){
$('#plugbot-ui').slideUp();
}, 1500);
toNastavenia = setTimeout(function(){
$('#ZobrazNastavenia').fadeIn("fast");
}, 2000);
});
I need clear timeout but this not working. Please tell me why. Thanks.

timeoutUI and timeoutNastavenia are variables that are locally scoped to the anonymous functions you define them in.
If you want them available in a wider scope, then you have to declare them in a wider scope.
Don't use var inside the anonymous functions. Do use var variableName outside of those functions. (e.g. just before the first line of the code in the question).

this is an example to clear timeout:
var myVar;
function myFunction()
{
myVar = setTimeout(function(){alert("Hello")},3000);
}
function myStopFunction()
{
clearTimeout(myVar);
}
as you can see myVar is defined in global scope, so in your code it will not work because timeoutUI and timeoutNastavenia are private variables, you should use timeoutUI=... instead of var timeoutUI=..

If I'm using jQuery and timeouts, then I always set them on the element itself:
$('#plugbot-ui').data(
'timeout-toUi',
setTimeout(function(){
$('#plugbot-ui').slideUp();
}, 1500)
);
This way you can clear the timeout by getting the ID off of the element itself:
clearTimeout($('#plugbot-ui').data('timeout-toUi'));
By the way, when using jQuery you can just use .delay():
$('#plugbot-ui').delay(1500).slideUp();
And you can use .stop() to stop the animation and clear and finish all animations:
$('#plugbot-ui').stop(true, true);

Related

Javascript : setTimeout use on an anonymous function expression

I recently started learning javascript to help maintain some stuff and ran into this issue today:
this.moveChar = function(){
// body here
setTimeout(moveChar,1000);
}
this.initialise= function(){
this.moveChar();
}
When initialise is called, I expected moveChar to be called, then repeated call itself once every 1000ms
However, what actually happens is moveChar gets called once then that's it. Based on other stackoverflow posts I read, I suspected it might be something to do with the function being expressed rather than declared. I have tried to use
this.moveChar = function recMove(){
// body here
setTimeout(recMove,1000);
}
without luck either.
Any suggestions on how I can fix this?
EDIT: Main thing I need to do is have the moveChar function called once every second. If there is a better approach than setTimeout recursion, I'm open to it
this.moveChar is not the same as moveChar, unless this is the global scope object like window.
this.moveChar is a property on an object, while moveChar would reference any variable in a visible scope chain.
You can change it to a couple of things in order to keep scope of whatever object is being used:
Using an arrow function
this.moveChar = function(){
// body here
setTimeout(()=>this.moveChar(),1000);
}
Using .bind()
this.moveChar = function(){
// body here
setTimeout(this.moveChar.bind(this),1000);
}
You might want to consider using setInterval() which is the more appropriate API for this task.
What setInterval() does is - it will repeatedly call the given function upon a certain interval is reached.
See:
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval
Quote:
Repeatedly calls a function or executes a code snippet, with a fixed
time delay between each call. Returns an intervalID.
Example:
Assuming moveChar() contains your operation logic. Then to repeat it you'll do this 1 line.
let moveChar = function(){
// Do stuff
console.log("Hi thanks for calling me!");
}
setInterval(moveChar, 1000);
Are you using this in side body here?
If so, you should bind correct context while call.
this.moveChar = function(){
// body here
setTimeout(this.moveChar.bind(this), 1000);
}
Or use anonymous function:
this.moveChar = function(){
// body here
var that = this;
setTimeout(function(){
that.moveChar();
}, 1000);
}
Or arrow function:
this.moveChar = function(){
// body here
setTimeout(() => this.moveChar(), 1000);
}
Same notes apply to setInterval variant:
this.initialise= function(){
setInterval(this.moveChar.bind(this), 1000);
// var that = this;
// setInterval(function(){that.moveChar();}, 1000);
// setInterval(() => this.moveChar(), 1000);
}
this.moveChar = function(){
// body here
alert('called moveChar');
}
this.initialise= function(){
setInterval(function(){moveChar();},1000);
}
this.initialise();//call here

Why doesn't setTimeout recognize function name?

(function( $ ){
$.fn.hash = function(){
function activate()
{
setTimeout('checkHash()', 100);
}
activate();
var previousHashTag = location.hash;
var previousHashProperty = '';
function checkHash()
{
if( previousHashTag !== location.hash )
{
$('body').trigger("hashchange", [ getHashObj() ]);
previousHashTag = location.hash;
setTimeout( "checkHash()", 200);
}
setTimeout( "checkHash()", 100);
}
This is my hash plugin I'm trying to make.
I would like to call the activate() function when user loads the plugin.
The activate function would set a timeout to check for a hash every 100 miliseconds.
How can I pull this off since checkHash is outside of the function in this object?
You are using string argument in setTimeout, which means that the code will be run in global object. As your called function is defined inside a closure of another function, you have to pass a reference
setTimeout(checkHash, 100);
or use anonymous function
setTimeout(function(){
checkHash();
});
You have to use the second approach when you want to pass any arguments to function called from setTimeout.
setTimeout(function(){
checkHash(arg);
});
You are passing strings to setTimeout and evaluating them. This breaks the normal scope. Don't do that, pass functions instead.
setTimeout(checkHash, 100);
Now scope will be preserved, and you can access activate from checkHash and vice versa as they are declared in the same scope.

Javascript Restart Timer From Within Closure

I'm trying to figure out how I can reset a timer created inside of an immediately invoking function from within the setTimeout closure. Here is my function:
var triggerHeightRecalc = function() {
setTimeout(function() {
if(imagesLoaded()) {
adjustHeight();
} else {
triggerHeightRecalc();
}
}, 100);
}();
In the event that imagesLoaded() returns false, I receive the following error from attempting to call triggerHeightRecalc():
Uncaught TypeError: undefined is not a function
So I'm not sure if the issue is the function is not in the scope, or maybe it just cannot call itself? I've tried passing triggerHeightRecalc as a parameter in the setTimeout closure, but that doesn't seem to work either.
I've also tried this after reading this SO question:
var triggerHeightRecalc = function() {
var that = this;
var callback = function() {
if(imagesLoaded()) {
adjustHeight();
} else {
that.triggerHeightRecalc();
}
};
timeDelay = window.setTimeout(callback, 100);
}();
What am I doing wrong here, or is there a better way? Is this something that should be a setInterval() instead and I clear the interval when images are loaded?
Side Note: I'm calculating the height of a div inside a jQuery plugin, but I need to wait until the images are loaded in order to get the correct height (not sure if that is relevant).
Since you are invoking the function right from the declaration triggerHeightRecalc is getting set to the return of that function call, which is undefined since you in fact do not return anything.
You can do two things
1. Declare then invoke
var triggerHeightRecalc = function() {
setTimeout(function() {
if(imagesLoaded()) {
adjustHeight();
} else {
triggerHeightRecalc();
}
}, 100);
};
triggerHeightRecalc();
2. Wrap the declaration in () and invoke
var triggerHeightRecalc;
(triggerHeightRecalc = function() {
setTimeout(function() {
if(imagesLoaded()) {
adjustHeight();
} else {
triggerHeightRecalc();
}
}, 100);
})();
The second one will create a global variable unless you do the var triggerHeightRecalc; before hand.
Already answered, but I'll put this in.
First of all, if you just want to wait until all images have loaded you can use:
https://github.com/desandro/imagesloaded and then run the above code.
If that's not what you want, and you you just want a function that your setTimeout can run, then you can remove the () at the end of the function.
Here is what's happening in your current code
Your function is missing the opening bracket or similar character !+( (function.
Also your IIFE has no return keyword, and will return undefined to triggerHeightCalc.
If you do want an IIFE then you can either have a private version that is only callable within itself.
(function myModule(){
myModule(); //calls itself
})();
Or a public version that can be called both inside and outside.
var myModule = (function(){
return function myMod(){
myMod();
}
})();
myModule();
Patrick Evans has the right reasons, but there is a neater way to solve it :)
(function triggerHeightRecalc() {
setTimeout(function() {
if(imagesLoaded()) {
adjustHeight();
} else {
triggerHeightRecalc();
}
}, 100);
})();
Here you are give an internal name to the (still) anonymous function. The name is only visible from within the function itself, its not visible in the global scope. Its called a Named function expression.

clearTimeout() Doesnt work

When I double click, it seems that the clearTimeout(timer) doesnt work, and the code calls the function activated(currentactiveid);
But also the function inside the setTimeout("activated2('" + currentactiveid + "')", 2000); references timer. So at the end I think that the problem is that the clearTimeout cannot find the variable timer.
HTML:
<td class='td2' id='currentid1' ondblclick='activatedd(this);' onclick='dclickornot(this);'>Some Text</td>
Javascript:
// Single Click
function dclickornot(e)
{
var currentactiveid = e.id;
var timer = setTimeout("activated2('" + currentactiveid + "')", 2000);
}
// Double Click
function activatedd(e)
{
clearTimeout(timer);
var currentactiveid = e.id;
activated(currentactiveid);
}
In JavaScript, variables are defined in the scope of the function. So you must use a global variable instead. This still doesn't prevent multiple single clicks, though.
(function () {
'use strict';
var timer, currentactiveid;
// Single Click
function dclickornot(e) {
currentactiveid = e.id;
timer = window.setTimeout(function () {activated2(currentactiveid); }, 2000);
}
// Double Click
function activatedd(e) {
window.clearTimeout(timer);
timer = undefined;
currentactiveid = e.id;
activated(currentactiveid);
}
}());
You need to remove 'var' from in front of your timer. It's scope is locked to the dclickornot() function.
Your timer variable is declared inside a function, and is out of scope in the activatedd function. To resolve it, declare timer in global scope, outside the two functions.
In javascript, the "var" keyword used inside a function creates a local variable that can only be seen from inside this function or from the scope chain created underneath this function.
In your case, "clearTimeout(timer);" is using a timer variable that is always undefined.

setInterval odd (buggy?) behavior within a $(document).ready(function() { ... }); block

Let me start here. At w3cshools.com - http://www.w3schools.com/jsref/met_win_setinterval.asp - they have a snippet demo-ing how to use javascript setInterval function (surprisingly it has a mismatched </form> but thats beside the point).
I needed to use setInterval() and at times I like referring to some "standard" body to take a glimpse of the recommended usage. In my development environment, something seems to be mangling setInterval() behavior/working when I use it within a jquery $(document).ready(function() { ... }); block.
Illustration 1 - WORKS: Typical/Traditional <script> block
<script type="text/javascript">
var refreshIntervalId;
function testMessage() {
window.alert("Hello");
}
refreshIntervalId = setInterval("testMessage()", 5000);
</script>
Illustration 2 - DOES NOT WORK: jQuery block
<script type="text/javascript">
$(document).ready(function() {
var refreshIntervalId;
function testMessage() {
window.alert("Hello");
}
refreshIntervalId = setInterval("testMessage()", 5000);
});
</script>
Illustration 3 - WORKS:
jQuery block - using setInterval(testMessage, 5000) instead of setInterval("testMessage()", 5000)
<script type="text/javascript">
$(document).ready(function() {
var refreshIntervalId;
function testMessage() {
window.alert("Hello");
}
refreshIntervalId = setInterval(testMessage, 5000);
});
</script>
It turns out that if I try to pass the function as a string from with the $(document).ready(function() {}); block, I get an error indicating that the function is not defined. Just so we dont get side-tracked IE, Chrome, and Firefox all report errors:
IE: Microsoft JScript runtime error: The value of the property 'testMessage' is null or undefined, not a Function object
Chrome: Uncaught ReferenceError: testMessage is not defined (anonymous function)
Firefox: testMessage is not defined.
What I would like to find out (if possible) is, could this be a result of standards non-conformance or what be going wrong when I try to use setInterval("testMessage()", 5000) from within the jQuery block? Could some mangling be happening or is this the right behavior?
setTimeout and setInterval break scope, so it can't find testMessage when it goes looking for it (because that function is scoped inside the anonymous function you pass to ready). Browsers are behaving correctly.
This is one of the reasons you should never, ever use the string format … or try to learn from the dreadful W3Schools.
The reason that the browsers say that the function isn't defined, is that it's not defined in the scope where the interval runs. You have declared the function locally inside another function, so it doesn't exist in the global scope where the interval runs.
This is not due to jQuery, simply due to the anonymous function that you wrap the code in. This code shows the same error:
(function() {
function testMessage() {
window.alert("Hello");
}
var refreshIntervalId = window.setInterval("testMessage()", 5000);
})();
You can declare the function globally instead, then you can use a string for the interval:
function testMessage() {
window.alert("Hello");
}
(function() {
var refreshIntervalId = window.setInterval("testMessage()", 5000);
})();
Common practice is to use the function itself rather than a string in the interval call:
(function() {
function testMessage() {
window.alert("Hello");
}
var refreshIntervalId = window.setInterval(testMessage, 5000);
})();
If you need to pass a value to the function, you can use an anonymous function in the call:
(function() {
function testMessage(msg) {
window.alert(msg);
}
var refreshIntervalId = window.setInterval(function() { testMessage("Hello"); }, 5000);
})();
function testMessage() and any other function must be declared OUTSIDE $(document).ready()
as #Quentin mentioned it's because the testMessage function is defined within the document ready and so outside the scope of the interval.
If you must define you're interval within the document ready you could do
refreshIntervalId = setInterval(function() {
window.alert("Hello");
}, 5000);

Categories

Resources