/*
 * flyoutMenu.js - DHTML fly-out menus
 *
 * PREREQUISITES:
 * - prototype.js v1.6
 * - lowpro.js v0.5
 *
 * TO-DO:
 * - 
 *
 * v0.1   - 2007-08-21 - Morgan Aldridge <morgant@makkintosshu.com>
 *                       Initial development.
 * v0.2   - 2008-01-17 - Morgan Aldridge <morgant@makkintosshu.com>
 *                       Better utilization of Prototype.js library and now
 *                       supports Prototype.js 1.6 & Lowpro.js 0.5.
 * v0.2.1 - 2008-01-18 - Morgan Aldridge <morgant@makkintosshu.com>
 *                       Continued Prototype.js 1.6 optimizations.
 * v0.2.2 - 2008-01-21 - Morgan Aldridge <morgant@makkintosshu.com>
 *                       Modifications to not add the behavior until page is
 *                       fully ready.
 * v0.2.3 - 2008-02-12 - Morgan Aldridge <morgant@makkintosshu.com>
 *                       Switched from using lowpro's AddBehavior() to just
 *                       calling each().
 * v0.2.4 - 2008-02-13 - Morgan Aldridge <morgant@makkintosshu.com>
 *                       Switched from using lowpro's Event.onReady() to
 *                       observing 'dom:loaded' events.
 * v0.3   - 2008-03-27 - Juriy Zaytsev <kangax@gmail.com>
 *                       Complete rewrite, incapsulated in a class and caches
 *                       everything for speed. Tested in IE7, Firefox 2, Opera
 *                       9, Safari 3. Untested in IE6.
 */

var FlyoutMenu = Class.create({
	
	initialize: function(element) {
		this.element = $(element);
		this.nodes = this.element.childElements().map(function(child) {
			return child.down();
		});
		this.initObservers();
		this.positionSubnodes();
	},
	
	initObservers: function() {
		this.nodes.invoke('observe', 'mouseover', this.onOver).invoke('observe', 'mouseout', this.onOut);
	},
	
	// positions subnodes, caches them and attaches observers
	positionSubnodes: function() {
		this.nodes.each(function(node) {
			var position = node.cumulativeOffset(),
				subnode = node.up().down('ul.flyout');
			if (subnode) {
				subnode.hide();
				subnode.setStyle({
					top: (position.top - 1) + 'px',
					left: ((position.left + subnode.getWidth()) - 5) + 'px'
				})
				subnode.observe('mouseout', this.onSubnodeOut);
			}
			// cache subnode and parent as expando properties 
			// of element for faster access
			node.__subnode = subnode;
			node.__parent = node.up();
		}, this);
	},
	
	onOver: function(e) {
		var target = e.target;
		target.__parent.addClassName('selected');
		target.__subnode && target.__subnode.show();
	},
	
	onOut: function(e) {
		var target = e.target,
			pointer = Event.pointer(e),
			x = pointer.x,
			y = pointer.y,
			dimensions;
	      
		if (target.__subnode) {
			if (Position.within(target.__subnode, x, y)) return;
			target.__subnode.hide();
		}
		//console.log(this);
		target.__parent.removeClassName('selected');
	},
	
	onSubnodeOut: function(e) {
		if (e.relatedTarget.descendantOf(this))
			return;
		this.hide();
	}
});
	    
document.observe('dom:loaded', function() {
	$$('ul.flyoutMenu').each(function(menu) {
		new FlyoutMenu(menu);
	});
});