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);
Related
It might be a beginner question but I'm facing with the next situation:
$(function f() {
function test2() {
//.....
}
function GetData() {
//.....
}
function update() {
test2();
GetData();
//...
}//end update
update();
});//end f()
function stop() {
clearInterval(multipleCalls);
}
function start() {
multipleCalls=null; //this is a global variable
setTimeout(update, 1000);
}
The stop function stops a graphic when a button is pressed and everything works fine. The start function should restart a graphic when a button is pressed. My guess is that the update function is not well invoked in start function. How could I do so everything to work fine?
You have currently commented out the } that closes the update function, so the line that says end f doesn't in fact end f(). In its present state, your code would not execute. (I note that someone else edited your code after which this remark is no longer valid; I don't know if the edit is closer to your actual code, or if it did in fact obscure a real error)
You're referring to both multiplecalls and multipleCalls. Note that javascript is case sensitive.
You're clearing multipleCalls but never setting it to anything but null. Did you intend to write multipleCalls = setTimeout(update, 1000) ?
start, being placed outside of f, won't have access to update. Either define update and the functions it is dependent upon outside of f(), or make it globally accessible, i.e.
window.update = function() { ... }
Which you'd then be able to access as setTimeout(window.update, 1000);
You have a scoping issue. The update is only known within the f.
You are trying to call it from outside f in start. The only way to achieve this is to either expose function update to the same scope as where start is, or bring start to the same scope as update.
The first option is easiest (and ugliest):
function update() {
//...
}
// assign it to the global scope (window is the global scope for browsers)
window.update = update;
Now update is available from `starts.
The more appropriate approach would be to define your handlers (which call start and stop within the scope of f, for example
$(function f() {
//.. everything there now
$('.start').on('click', function(e) {
setTimeout(update, 1000);
});
});
Working example
$(function f() {
var timer; // no need to be 'global'
function update() {
$('.result').text(new Date() + ' GetData();');
}
$('.start').on('click', function() {
// always clear a timer before setting it
clearTimeout(timer);
// and always set a timer variable, so it can be cancelled
timer = setTimeout(update, 1000);
});
$('.stop').on('click', function() {
// cancel the timer
clearTimeout(timer);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class=start>start</button>
<button class=stop>stop</button>
<div class=result>..</div>
You could try this:
window.update = function update() {...}
and then:
setTimeout(window.update, 1000);
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.
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);
I'm using in a project the following code which is not working:
window.onload=function(){
//code here
};
but if I add at the end () it works:
window.onload=function(){
//code here
}();
My question is, what's the difference? What does the () at the end?
I presume that the first one doesn't work because somewhere else the "onload" has been already called killing this one.
Would it have the same behaviour if I always use the second option ?
() at the end of function, calls this function immediately after declaration
window.onload=function(){
//code ehere
}() // function is called
And in this case
window.onload=function(){
//code here
};
function will be called after
window.onload()
When you have () after a lambda function such as that, it means you're calling the function immediately on that line.
So, for example,
var x=function() {
return 5;
}();
console.log(x);
would log 5 in the console. In the case of
window.onload=function() {
//code here
}();
that function most likely returns another function that gets called when the page loads.
For example,
window.onload=function() {
return function() {
console.log("Hello!");
};
}();
will log "Hello!" in the console when the page loads.
function is assigned to onload
window.onload=function(){
//code ehere
};
result of function is assigned to onload
window.onload=function(){
//code ehere
}();
With the () the function you define is called immediately. In that case, it better return a function to assign to window.onload.
I have the following code:
function fn($){
return function(){
innerFn = function(){
setTimeout(show, 1000);
};
show = function(){
$.alert("TEST");
}
}
}
But, after one second, when the function show is run, it says $ is undefined. How do I resolve this issue?
how to pass arguments to a function in setTimeout
setTimeout has a built in mechanism for adding params
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
use it.
If you're going to use this - you should be careful. but that's another question.
There are a number of things at play here. The most important being that your setTimeout never gets called, since innerFn never gets called. This should do the trick.
function fn($){
return function(){
setTimeout(function(){
$.alert("TEST");
}, 1000);
}
}
fn(window)(); //triggers your alert after 1000ms
Your code makes no any sense, because nothing is called:
function fn($){
return function(){
innerFn = function(){
setTimeout(show, 1000);
};
show = function(){
$.alert("TEST");
}
}
}
Let's say I'm calling fn passing window, then a function is returned, that I can executed. But because this function is containing only function declaration - you also forget var so you pollute the global scope, that is bad - nothing is happen.
You'll need at least one function call inside, like:
function fn($){
return function(){
var innerFn = function(){
setTimeout(show, 1000);
};
var show = function(){
$.alert("TEST");
}
innerFn();
}
}
fn(window)();
And that will works. However, it's definitely redundant. You can just have:
function fn($){
return function(){
function show(){
$.alert("TEST");
}
setTimeout(show, 1000);
}
}
To obtain the same result. However, if you're goal is just bound an argument to setTimeout, you can use bind. You could use the 3rd parameter of setTimeout as the documentation says, but it seems not supported in IE for legacy reason.
So, an example with bind will looks like:
function show() {
this.alert('test');
}
setTimeout(show.bind(window), 1000);
Notice also that window is the global object by default, so usually you do not have to do that, just alert is enough. However, I suppose this is not your actual code, but just a mere test, as the alert's string says.
If you prefer having window as first parameter instead, and you're not interested in the context object this, you can do something like:
function show($) {
$.alert('test');
}
setTimeout(show.bind(null, window), 1000);