/**
 *	Simple Menu - V1.00.080812 for jQuery
 *	---------------------------------------------
 *	(c) 2008 Lost Boys - http://www.lostboys.com
 *
 *	requires
 *		- jquery
 *		- jquery.lb.utils.js
 *
 *	SimpleMenu transforms a dom tree into a foldout menu. Only events and 
 *	actions are defined by this script, the actual visuals must be defined 
 *	in html and css. 
 */

(function($){

	var DELAY_OPEN		= 250,		// delay before a sub is opened (cold state)
		DELAY_SWITCH	= 100,		// delay before a sub is opened (hot state)
		DELAY_CLOSE		= 500,		// delay before the menu is closed (hot state)

		CLASS_HOVER		= 'hover',	// mouseover class, used by toggleItem
		CLASS_ACTIVE	= 'active',	// active class, used by toggleMenu
		ITEM_TYPE		= 'li',		// nodename of menu items
		MENU_TYPE		= 'ul',		// nodename of submenu's

		STATE_COLD		= 1,
		STATE_HOT		= 2;


	$.SimpleMenu = function(element, set) {
		this.root = element;
		this.state = STATE_COLD;
		this.stateChange = null;
		
		var settings = set || {};
		this.openDelay		= settings.openDelay || DELAY_OPEN;
		this.switchDelay	= settings.switchDelay || DELAY_SWITCH;
		this.closeDelay		= settings.closeDelay || DELAY_CLOSE;
		this.hoverClass		= settings.hoverClass || CLASS_HOVER;
		this.activeClass	= settings.activeClass || CLASS_ACTIVE;
		this.itemType		= settings.itemType || ITEM_TYPE;
		this.menuType		= settings.menuType || MENU_TYPE;

		if(settings.toggleMenu) { this.toggleMenu = settings.toggleMenu; }
		if(settings.toggleItem) { this.toggleItem = settings.toggleItem; }

		this.defaultItem = $('.'+this.activeClass, this.root)[0];
		$(this.root).bindScoped('mouseover', this.mouseover, this);
	}


	$.SimpleMenu.prototype = {
		
		toggleMenu:function(item, toggle) {
			$(item)[toggle? 'addClass' : 'removeClass'](this.activeClass);
		},

		toggleItem:function(item, toggle) {
			$(item)[toggle? 'addClass' : 'removeClass'](this.hoverClass);
		},

		mouseover: function(e) {
			var target = $(e.target).bubbleTo(this.itemType);
			var item = target? target[0] : null;
			if(item && item != this.item) {
				this.setCurrent(item);
				clearTimeout(this.stateChange);
				var self = this, toggle = function(){ self.toggle(item); };
				switch(this.state) {
					case STATE_COLD:
						this.stateChange = setTimeout(toggle, this.openDelay);
					break;
					case STATE_HOT: 
						this.stateChange = setTimeout(toggle, this.switchDelay);
					break;
				}

				this.mouseoutHandler = function(e) {
					self.mouseout(e);
				}

				if(!this.ping) {
					this.ping = true;
					$(document).bind('mouseover', this.mouseoutHandler);
				}
			}
		},

		mouseout: function(e) {
			var node = e.target;
			while(node) {
				if(node == this.root) return;
				node = node.parentNode;
			}

			this.setCurrent(null);
			clearTimeout(this.stateChange);

			var self = this;
			switch(this.state) {
				case STATE_COLD: break;
				case STATE_HOT:
					this.stateChange = setTimeout(function(){ 
						self.toggle(false);
					}, this.closeDelay);
				break;
			}

			if(this.ping) {
				$(document).unbind('mouseover', this.mouseoutHandler);
				this.ping = false;
			}
		},

		toggle: function(item) {
			var tree = item? item.parentNode : this.root;
			var lists = tree.getElementsByTagName(this.menuType);

			for(var list,i=0; list=lists[i++];)
				this.toggleMenu(list.parentNode, false);

			if(item) {
				var list = item.getElementsByTagName(this.menuType)[0];
				list && this.toggleMenu(list.parentNode, true);
			} else if(this.defaultItem) {
				this.toggleMenu(this.defaultItem, true);
			}
			
			this.state = item? STATE_HOT : STATE_COLD;
		},

		setCurrent:function(item) {
			if(this.item) this.toggleItem(this.item, false);
			if(this.item = item) this.toggleItem(this.item, true);
		}
	}

	$.registerPlugin('simpleMenu', $.SimpleMenu);

})(jQuery);
