Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setTimeout issue in Firefox

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!).

like image 207
the_new_mr Avatar asked Dec 09 '10 12:12

the_new_mr


1 Answers

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'));
like image 185
Colin Fine Avatar answered Sep 22 '22 05:09

Colin Fine