The menu system is supposed to expand and collapse according to a given delay using the following statements (o_item.getprop('hide_delay') returns 200 and o_item.getprop('expd_delay') returns 0):
this.o_showtimer = setTimeout('A_MENUS['+ this.n_id +'].expand(' + n_id + ');',
o_item.getprop('expd_delay'));
and
this.o_hidetimer = setTimeout('A_MENUS['+ this.n_id +'].collapse();',
o_item.getprop('hide_delay'));
I tried placing the code for the first argument into separate functions and call these functions as the first argument to setTimeout like this:
this.o_showtimer = setTimeout( expandItem(this.n_id, n_id),
o_item.getprop('expd_delay'));
Firebug produced the following error message:
useless setTimeout call (missing quotes around argument?)
And there was no delay in the collapse.
I placed the argument in quotes (though recommended against here) like this:
this.o_showtimer = setTimeout( "expandItem(this.n_id, n_id)",
o_item.getprop('expd_delay'));
but this didn't work. It appeared that nothing was happening at all and throwing some console.log() messages into the code confirmed this.
I tried using an anonymous function call as recommended here and here like this:
this.o_showtimer = setTimeout( function() { expandItem(this.n_id, n_id); },
o_item.getprop('expd_delay'));
but this didn't work either. It produced undesirable results in IE (items not collapsing is the same manner as before) and nothing happening in Firefox (placing console.log() statements in expandItem and collapseItem functions confirmed that they weren't being called).
I even tried doing the following:
this.o_hidetimer = setTimeout( function() { alert('test'); },
o_item.getprop('hide_delay'));
and that didn't even work! Seems there's something up with calling the anonymous function.
Discovered that assigning the value of setTimeout to a variable other than this.o_showtimer made the left argument of setTimeout fire. Must be something to do with assigning something to this.
If I do this:
var o_showtimer = setTimeout( function() { expandItem(this.n_id, n_id); },
o_item.getprop('expd_delay'));
expandItem gets called. However, if I do this:
var o_showtimer = setTimeout( function() { expandItem(this.n_id, n_id); },
o_item.getprop('expd_delay'));
this.o_showtimer = o_showtimer;
As if setTimeout can predict the future! (expd_delay is 0!).
I think the problem is in Javascript's idiosyncratic treatment of 'this'. When you call 'expandItem' within your anonymous function, you are not calling it as a method, so 'this' gets set to the fundamental scope (window).
I would suggest using a local variable
var that = this;
this.o_showtimer = setTimeout( function() { expandItem(that.n_id, n_id); },
o_item.getprop('expd_delay'));
Related
In my jQuery scripts, when the user closes a menu with an animation, I have to call a function after the closing animation is finished. I want to assign this function dynamically by calling a function openStrip() with a parameter. My code looks like:
var FUNCTION_JUST_AFTER_MENU_CLOSE = function(){};
function openStrip(stripId){
FUNCTION_JUST_AFTER_MENU_CLOSE = function(){
createStrip(stripId);
});
}
if I call openStrip("aStripId"), I expect FUNCTION_JUST_AFTER_MENU_CLOSE to be:
// #1
function(){
createStrip("aStripId");
}
whereas my current code gives:
//#2
function(){
createStrip(stripId);
}
i.e, the parameter passed to the function openStrip() is lost while assigning the function() to the variable FUNCTION_JUST_AFTER_MENU_CLOSE.
How can I avoid this.
EDIT: I discovered that my code is actually working. The problem was elsewhere. I got confused because when I looked at Chrome's debugger, it was showing me the function definition as is (#2 in above). But when it actually went down executing that function later in the code, it did evaluate the values of the passed argument, and endedup executing #1.
Thanks for the answer though. I am marking it correct because that is perhaps a better way of assigning the function.
The best way is to return a function, from openStrip like this
function openStrip(stripId) {
return function() {
createStrip(stripId);
};
}
For example,
function openStrip(stripId) {
return function() {
console.log(stripId);
};
}
openStrip("aStripId")();
# aStripId
openStrip("bStripId")();
# bStripId
You can even assign the function objects returned to different variables and use them later on
var aStrip = openStrip("aStripId");
aStrip();
# aStripId
aStrip();
# aStripId
I made a jsfiddle for you:
http://jsfiddle.net/fyJP2/
This is the code:
var chat = {
init: function(){
setTimeout( comet , 10);
}
};
function comet()
{
alert('called');
}
$(document).ready(function(){
chat.init();
});
As you can see comet() is called immediately ignoring completely the delay of 10 seconds, why? I am passing comet and not comet() as setTimeout requires, but the function is still executed.
I originally thought it was a scope issue so I moved comet to its own function, but doing this: http://jsfiddle.net/fyJP2/1/ the result is the same.
Can someone explain me why?
As has been pointed out the second argument passed to window.setTimeout is in milliseconds.
Therefore your code should be:
init: function(){
setTimeout( comet , 10000);
}
Presuming you meant ten seconds, that is.
Read more here: https://developer.mozilla.org/en/docs/Web/API/window.setTimeout
I'm trying to write a code that adds a class to a div for a limited time, and then removes it.
I tried using javascript's setTimeout, and jQuery's delay, but nothing works.
The element is SET but never REMOVED.
Here's the come I came up with:
window.onload = function() {
$(".button").click(handler);
}
function handler() {
$(this).addClass("onclick");
setTimeout(function() { $(this).removeClass("onclick"); }, 3000); // JS's setTimeout
$(this).addClass("onclick").delay(3000).removeClass("onclick"); // jQuery's delay
}
I don't get what's wrong... I even tried writing a second handler for the setTimeout function.
Thanks in advanced.
The problem you're having is that this is different within the function you're passing to setTimeout than it is outside it. The usual fix is to use the closure by creating a variable to hold it, and using the variable instead:
function handler() {
var $elm = $(this);
$elm.addClass("onclick");
setTimeout(function() {
$elm.removeClass("onclick");
}, 3000);
}
There I've also use the var to cache the result of $(this) because there's no point in doing it more than once.
More background:
In JavaScript, unlike some languages that look similar, this is defined entirely by how a function is called. When you use setTimeout, the way the function gets called will make this be the global object (window, on browsers), so that's why $(this).removeClass(...) wasn't working.
More on this if you're interested:
Mythical methods
You must remember this
this inside the setTimeout call does not refer to the clicked element.
Change it to this:
function handler() {
var t = $(this);
t.addClass("onclick");
setTimeout(function() { t.removeClass("onclick"); }, 3000);
}
Working example - http://jsfiddle.net/5vakN/
Reference for how this works in javascript - http://bonsaiden.github.com/JavaScript-Garden/#function.this
I'm trying to create a javascript object that can call other methods within itself. However, I'm running into a weird problem that I just can't seem to figure out.
I have the following code
myObjectDef = function() {
this.init = function() {
//do some stuff
this.doSecondInit();
}
this.doSecondInit = function() {
//do some more stuff
}
}
myObject = new myObjectDef();
myObject.init();
I am getting an error that states "Message: Object doesn't support this property or method". And it ends at this.doSecondInit();. I can't quite figure out why it's doing this. My code runs great up to the call to the second method. How do I make this work?
There's an extra set of parenthesis here:
this.doSecondInit() = function() {
You can't assign to the result of a function call, let alone to the result of a function that doesn't even exist.
After your edit, your thing seems to work fine:
http://jsfiddle.net/nabVN/
You sure you didn't have the same typo in your actual code? Better start getting used to not putting that () after every function call, which is probably a bad habit carried over from languages where functions aren't values.
I'm trying to create a 6 second delay before the heartColor(e) function begins, the function will then continue to loop. I don't understand why it's starting the function immediatley, and not waiting the 6 seconds it's supposed to, what did I do wrong?
function heartColor(e) {
e.animate({
color: '#7ea0dd'
}, 1000).animate({
color: '#986db9'
}, 1000).animate({
color: '#9fc54e'
}, 1000, function(){
heartColor(e)
})
}
$('.something').hover(function(){
setTimeout(heartColor($(this)), 6000);
})
The setTimeout() function expects its first parameter to be a function reference (or a string, but that's not recommended for several reasons). You are not passing it a function reference, you are calling the heartColor() function and passing the result to setTimeout(). So the function executes immediately, and then after six seconds nothing happens because the return value was undefined so setTimeout() had nothing to work with.
Try this instead:
$('.something').hover(function(){
var $this = $(this);
setTimeout(function() {
heartColor($this);
}, 6000);
})
The reason I have included an anonymous function as the parameter to setTimeout is that your call to heartColor() needs to pass a parameter through. If it didn't have any parameters you could do this:
setTimeout(heartColor, 6000);
Note there are no parentheses after heartColor - that gets a reference to the function without calling it so that later setTimeout calls it for you. But you can't get a reference to the function and provide parameters at the same time so you need to wrap the call up in another function. You could do this:
var $this = $(this);
function callHeartColor() {
heartColor($this);
}
setTimeout(callHeartColor, 6000);
My original answer with the anonymous function is kind of short hand for that and (most people find it) more convenient.
The reason I have created a variable $this is because of the way the this keyword works in JavaScript, which depends on how a function is called. If you simply said heartColor($(this)) inside the anonymous function (or the callHeartColor() function) this would not be the element being hovered over.
you are invoking the function heartColor instead of passing it as a parameter. you have to do:
$('.something').hover(function(){
setTimeout(function(){heartColor($(this))}, 6000);
})
You want this:
$('.something').hover(function(){
setTimeout(function() {heartColor($(this));}, 6000);
})