(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.
Related
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 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);
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.
I'm writing a JavaSCript class that has a method that recursively calls itself.
Scheduler.prototype.updateTimer = function () {
document.write( this._currentTime );
this._currentTime -= 1000;
// recursively calls itself
this._updateUITimerHandler = window.setTimeout( arguments.callee , 1000 );
}
Property description:
_currentTime: the currentTime of the timer in miliseconds.
_updateUITimerHandler: stores the reference so can be used later with clearTimeout().
my problem is where I'm using recursion with setTimeout(). I know setTimeout() will accept some string to execute, or a reference to a function. since this function is method of an object, I don't know how to call it from outside. so I used the second format of setTimeout() and passed in a reference to the method itself. but it does not work.
Try this:-
Scheduler.prototype.startTimer = function() {
var self = this;
function updateTimer() {
this._currentTime -= 1000;
self.hTimer = window.setTimeout(updateTimer, 1000)
self.tick()
}
this.hTimer = window.setTimeout(updateTimer, 1000)
}
Scheduler.prototype.stopTimer = function() {
if (this.hTimer != null) window.clearTimeout(this.hTimer)
this.hTimer = null;
}
Scheduler.prototype.tick = function() {
//Do stuff on timer update
}
Well the first thing to say is that if you're calling setTimeout but not changing the interval, you should be using setInterval.
edit (update from comment): you can keep a reference from the closure if used as a class and setInterval/clearInterval don't require re-referencing.
edit2: it's been pointed out that you wrote callee which will work quite correctly and 100% unambiguously.
Out of completeness, this works:
function f()
{
alert('foo');
window.setTimeout(arguments.callee,5000);
}
f();
so I tried out document.write instead of alert and that is what appears to be the problem. doc.write is fraught with problems like this because of opening and closing the DOM for writing, so perhaps what you needed is to change the innerHTML of your target rather than doc.write
You could hold a pointer towards it...
/* ... */
var func = arguments.callee;
this._updateUITimerHandler = window.setTimeout(function() { func(); }, 1000);
/* ... */