www.webdeveloper.com
Results 1 to 5 of 5

Thread: Multiple timers across objects

  1. #1
    Join Date
    Aug 2009
    Posts
    3

    Question Multiple timers across objects

    Dear JS Ninjas,

    After reading a couple O'Reilly JS books I threw together the following code to make a simple menu for my new site. It works, for the most part, but the timers seem buggy. I imagine it has something to do with the global var I had to use with the setTimeout in my SlideMenu.prototype.startTimer function, but I do not know how else to abuse the setTimeout function.

    To replicate the issue, go to the following URL and pass the mouse over the menus fairly quickly. Usually the last one passed will close, sometimes two, but almost never all three.

    Can someone shed some light on this possibly?

    Also, if you have time, please please critique my code. I need to learn.

    (I am using jQuery BTW. I am on Ubuntu, running FF 3.0.13. Same thing in Windows FF 3.0.13 and IE7.)

    Thanks,
    Tom

    http://tridium-dev.tridiumtech.com/

    Code:
    function SlideMenu($button, $menu) {
    	this.$button = $button;
    	this.$menu = $menu;
    	this.timeout = 500;
    	this.timer = null;
    	
    	var _this = this;
    	
    	this.$button.click(function() {
    		_this.openMenu();
    	});
    	this.$button.mouseenter(function() {
    		_this.openMenu();
    	});
    	this.$button.mouseleave(function() {
    		_this.startTimer();
    	});
    	
    	this.$menu.mouseenter(function() {
    		_this.stopTimer();
    	});
    	this.$menu.mouseleave(function() {
    		_this.startTimer();
    	});
    }
    
    SlideMenu.prototype.openMenu = function() {
    	this.$menu.slideDown("medium");
    	this.$button.addClass("active");
    	return false;
    };
    
    SlideMenu.prototype.closeMenu = function() {
    	this.$menu.slideUp("medium");
    	this.$button.removeClass("active");
    };
    
    SlideMenu.prototype.startTimer = function() {
    	thisMenu = this;
    	
    	this.timer = setTimeout("thisMenu.closeMenu()", this.timeout);
    };
    
    SlideMenu.prototype.stopTimer = function() {
    	clearTimeout(this.timer);
    };
    
    $(document).ready(function(){
    
    	var businessSlideMenu = new SlideMenu($(".business"), $("#businesspanel"));
    	var residentialSlideMenu = new SlideMenu($(".residential"), $("#residentialpanel"));
    	var techTipsSlideMenu = new SlideMenu($(".techtips"), $("#techtipspanel"));
    	
    });

  2. #2
    Join Date
    Oct 2008
    Location
    U.S.
    Posts
    726
    I imagine it has something to do with the global var I had to use with the setTimeout in my SlideMenu.prototype.startTimer function, but I do not know how else to abuse the setTimeout function.
    You would be correct, the global variable being used to refer to an instance of SlideMenu is the problem, easily fixed:

    Code:
    SlideMenu.prototype.startTimer = function() {
    	var thisMenu = this; //localized variable, maintains reference to the current instance of SlideMenu
    	//now pass the reference in an anonymous function to the window.setTimeout function
    	this.timer = window.setTimeout(function () { thisMenu.closeMenu(); }, this.timeout);
    };

  3. #3
    Join Date
    Aug 2009
    Posts
    3
    Amazing. It works great. Thanks

    I had tried the localized variable before, but not the anonymous function, so it resulted in disaster (not working at all).

    Could you elaborate on what the anonymous function does for that statement to make it work, or possibly point me in the direction of a reference that explains what is happening there?

    Thanks,
    Tom

  4. #4
    Join Date
    Oct 2008
    Location
    U.S.
    Posts
    726
    Could you elaborate on what the anonymous function does for that statement to make it work
    Because the anonymous function which is passed to window.setTimeout is actually created each time within an instance of SlideMenu's startTimer method, the anonymous function retains a sort of 'hidden pointer' back to the local thisMenu variable within the object's startTimer method. So basically the setTimeout function when it encounters a reference to thisMenu within the anonymous function, setTimeout doesn't actually know what that is, so the scope chain is searched for thisMenu. It's sort of like setTimeout asks the anonymous function "who's your daddy" to which the anonymous function replies "well, I guess my daddy is businessSlideMenu.startTimer" which is confirmed when setTimeout finds the definition of thisMenu within the mentioned method. It then 'knows' that thisMenu refers to the particular instance of SlideMenu.
    For more info, lots of reading out there if you google "javascript object scope" or "javascript closures".
    Last edited by astupidname; 08-26-2009 at 12:41 PM.

  5. #5
    Join Date
    Aug 2009
    Posts
    3
    Great. I think I am understanding more.

    Basically the anonymous function is keeping the reference to the local var "thisMenu" alive so that it doesn't get recycled when the method ends, right?

    Thanks for your help!

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles