// JavaScript Document

// Assume that MooTools Core Library is currently included

/*
 * DropdownMenu Constructor
 *
 *	The DropdownMenu Object will manage the opening and closing of dropdown menus to any depth.
 *
 *	@param delay	Sets how long to delay before closing a dropdown menu after hovering off of it
 */
function DropdownMenu(delay)
{
	this.layers = new Array()
	this.delay	= (typeof(delay) == 'undefined')? 1 : delay;
	this.timeoutId = null;
	this.onDropdownClose = null;
	
	/*
	 * open function 
	 * opens the dropdown menu
	 *
	 * @param depth	The level of depth where the menu is opening
	 * @param currentId	The element id of the current dropdown menu to open
	 * @param relativeId	The element id of the html element that the dropdown menu should dock to
	 * @param vAlign	The vertical placement of the dropdown menu in relation to the relative element
	 * @param hAlign	The horizontal placement of the dropdown menu in relation to the relative element
	 */
	
	this.open = function(depth, currentId, relativeId, vAlign, hAlign)
	{
		var x, y;
		var div, relObj;
		var divOffset, relObjOffset;
		this.clearTimeout();

		div		= $(currentId);
		relObj	= $(relativeId);
		if(div && relObj)
		{
			relObj.addClass('active');
			div.breadcrumb = relObj;
			div.style.display = 'block'; //Needs to display first, so that the offset values are not 0 - dduong 20090827
			divOffset		= div.getCoordinates();
			relObjOffset	= relObj.getCoordinates();

			switch(String(vAlign).toLowerCase())
			{
				case 'top':
					y = (depth == 0)? (relObjOffset.top - divOffset.height) : (relObj.offsetTop - div.offsetHeight);
					break;
				case 'bottom':
					y = (depth == 0)? (relObjOffset.top + relObjOffset.height) : (relObj.offsetTop + relObj.offsetHeight);
					break;
				default:
					y = (depth == 0)? (relObjOffset.top) : (relObj.offsetTop);
			}
			
			switch(String(hAlign).toLowerCase())
			{
				case 'left':
					x = (depth == 0)? (relObjOffset.left) : (relObj.offsetLeft);
					break;
				case 'right':
					x = (depth == 0)? (relObjOffset.left + relObjOffset.width - divOffset.width) : (relObj.offsetLeft + relObj.offsetWidth);
					break;
				default:
					x = (depth == 0)? (relObjOffset.left) : (relObj.offsetLeft);
			}
			
			this.setDepth(depth, currentId);
			div.style.left	= x + 'px';
			div.style.top	= y + 'px';

		}
	}
	
	/*
	 * setDepth function 
	 * Sets the depth of provided dropdown menu element
	 *
	 * @param depth	The level of depth of the menu
	 * @param currentId	The element id of the current dropdown menu
	 */
	this.setDepth = function(depth, currentId)
	{
		if(typeof(this.layers[depth]) == 'undefined')
		{
			this.layers[depth] = new Array();
		}
		
		this.layers[depth][this.layers[depth].length] = currentId;
	}
	
	/*
	 * close function 
	 * closes the current dropdown menu item and any dropdowns that are currently inactive
	 *
	 * @param event	The window event of type mouseout or mouseover
	 */
	
	this.close = function(event)
	{
		var currentTarget, relatedTarget;
		var self = this;
		var timeoutFunction;
		
		event = (event)? event : window.event;
		
		currentTarget	= (window.event)? event.srcElement: event.target;
		relatedTarget	= (event.toElement)? event.toElement: event.relatedTarget;

		switch(event.type)
		{
			case 'mouseout':
				this.clearTimeout();
				timeoutFunction = function(object)
				{
					self.closeInactiveDepths(object);
				}
				this.timeoutId = window.setTimeout(timeoutFunction, this.delay * 1000, relatedTarget);
				break;
			case 'mouseover':
				this.closeInactiveDepths(currentTarget);
				break;
		}
	}
	
	/*
	 * closeInactiveDepths function 
	 * closes the inactive depths in relation to the current html element provided.  Starting from the deepest
	 * layer and moving to the hightest; If the html element is inside a dropdown menu of a certain depth,
	 * don't close it.  Otherwise, close all dropdown layers at that depth.
	 *
	 * @param event	The window event of type mouseout or mouseover
	 */
	this.closeInactiveDepths = function(object)
	{
		var i, j;
		var value = false;

		this.clearTimeout();
		for(i = this.layers.length - 1; i >= 0; i--)
		{
			if(typeof(this.layers[i]) !== 'undefined')
			{
				for(j = 0; j < this.layers[i].length; j++)
				{
					if(this.inContainer(object, $(this.layers[i][j])))
					{
						return true;
					}
				}
				this.closeDepth(i);
			}
		}
		this.layers.length = 0;
		
		return value;
	}
	
	/*
	 * inContainer function 
	 * Checks to see if an html element is inside of another
	 *
	 * @param object	The html element in question
	 * @param container	The container we're checking to see if the object is inside of
	 */
	this.inContainer = function(object, container)
	{
		var tempObject = object;
		
		while(tempObject)
		{
			tempObject = tempObject.offsetParent;
			if(tempObject == container) {
				return true;
			}
		}
		return false;
	}
	
	/*
	 * closeDepth function 
	 * Closes all the dropdown menus at a certain depth
	 *
	 * @param depth	The depth at witch to close all dropdown menus
	 */
	this.closeDepth = function(depth)
	{
		var obj, i;
		
		if(typeof(this.layers[depth]) !== 'undefined')
		{
			for(i = 0; i < this.layers[depth].length; i++)
			{
				obj = $(this.layers[depth][i]);
				if(obj)
				{
					obj.style.display = 'none';
					if(obj.breadcrumb)
					{
						$(obj.breadcrumb).removeClass('active');
					}
				}
			}
			this.layers[depth].length = 0;
		}
	}
		
	/*
	 * clearTimeout function 
	 * Clears the timeout function used when the timer to close a dropdown menu has started
	 */
	this.clearTimeout = function()
	{
		if(this.timeoutId !== null)
		{
			window.clearTimeout(this.timeoutId);
			this.timeoutId = null;
		}
	}
}