﻿///////////////////////////////////////////
// Menu Functionality
///////////////////////////////////////////

//wrapper functions to prevent null references to menus variable
function menus_hideMenu(id)
{
	if (menus)
		menus.hideMenu(id);
}

function menus_showMenu(id,element)
{
	if (menus)
		menus.showMenu(id,element);
}

///////////////////////////////////////////
// Menu Manager Class
///////////////////////////////////////////
function MenuManager(id,direction,hidingDelay,useSliding,animationTime,minInterval,positionFixed)
{
	//properties
	this.activeMenu = null;
	this.animationTime = animationTime;
	this.direction = direction;
	this.directionMod = (direction == "down" || direction == "right") ? "-" : "+";
	this.hidingDelay = hidingDelay;
	this.id = id;
	this.menus = new Array();
	this.menusList = new Array();
	this.minInterval = minInterval;
	this.orientation = (direction == "left" || direction == "right") ? "h" : "v";
	this.positionFixed = positionFixed;
	this.useSliding = useSliding;

	//this.log = new Array();

	//methods
	this.attachMenus = menuManager_attachMenus;
	this.hideAllMenus = menuManager_hideAllMenus;
	this.hideMenu = menuManager_hideMenu;
	this.showLog = menuManager_showLog;
	this.showMenu = menuManager_showMenu;
}

function menuManager_showLog()
{
	alert(this.log.join("\n"));
}

function menuManager_attachMenus()
{
	var id, left, top;

	//load menus into array
	for (var i=0;i<arguments.length;i++)
	{
		if (i % 3 == 0)
			id = arguments[i];
		else if (i % 3 == 1)
			left = parseInt(arguments[i]);
		else if (i % 3 == 2)
		{
			top = parseInt(arguments[i]);
			var menu = new Menu(this,id,left,top);
			if (menu.init(left,top))
			{
				this.menus[id] = menu;
				this.menusList[this.menusList.length] = menu;
			}
		}
	}
}

function menuManager_hideAllMenus(id)
{
	for (var i=0; i < this.menus.length; i++)
		if (this.menus[i])
			this.menus[i].hide(true);
}

function menuManager_hideMenu(id,hideImmediately)
{
	var menu = this.menus[id];
	if (menu)
		menu.hide(hideImmediately);
}

function menuManager_showMenu(id,element)
{
	var menu = this.menus[id];
	if (menu)
		menu.show(element);
}

///////////////////////////////////////////
// Menu Class
///////////////////////////////////////////
function Menu(manager,id)
{
	//properties
	this.acceleration = 0;
	this.animationTimer = null;
	this.closedPosition = 0;
	this.container = null;
	this.hideTimer = null;
	this.id = id;
	this.isOpen = false;
	this.manager = manager;
	this.menu = null;
	this.relevantDimension = 0;
	this.slideStartTime;

	//methods
	this.finishSlide = menu_finishSlide;
	this.hide = menu_hide;
	this.init = menu_init;
	this.moveTo = menu_moveTo;
	this.show = menu_show;
	this.slide = menu_slide;
	this.slideIncrement = menu_slideIncrement;
}

function menu_finishSlide()
{
	if (this.manager.useSliding)
	{
		this.moveTo(this.isOpen ? 0 : this.closedPosition);
		if (this.animationTimer)
			window.clearInterval(this.animationTimer);
	}

	//hide container
	if (!this.isOpen)
		this.container.style.visibility = "hidden";
}

function menu_hide(hideImmediately)
{
	//this.manager.log[this.manager.log.length] = "menu hide: " + this.id + " immed: " + hideImmediately;

	if (hideImmediately)
	{
		if (this.hideTimer)
			window.clearTimeout(this.hideTimer);
		if (this.isOpen)
			this.slide(false);
	}
	else
	{
		if (this.manager.useSliding && this.hideTimer)
			window.clearTimeout(this.hideTimer)
		this.hideTimer = window.setTimeout(this.manager.id + ".hideMenu('" + this.id + "',true);", this.manager.hidingDelay);
	}
}

function menu_init(left,top)
{
	this.container = document.getElementById(this.id + "MenuContainer");
	this.menu = document.getElementById(this.id + "Menu");
	if (this.container && this.menu)
	{
		this.relevantDimension = this.manager.orientation == "v" ? this.menu.offsetHeight : this.menu.offsetWidth;
		this.container.style.left = left + "px";
		this.container.style.top = top + "px";
		this.closedPosition = eval("0" + this.manager.directionMod + this.relevantDimension);
		this.acceleration = (-this.closedPosition) / this.manager.animationTime / this.manager.animationTime;
		this.menu.onmouseover = new Function(this.manager.id + ".showMenu('" + this.id + "');");
		this.menu.onmouseout = new Function(this.manager.id + ".hideMenu('" + this.id + "');");
		if (this.manager.useSliding)
			this.moveTo(this.closedPosition);

		return true;
	}
	return false;
}

function menu_moveTo(position)
{
	if (this.manager.orientation == "h")
		this.menu.style.left = position + "px";
	else
		this.menu.style.top = position + "px";
}

function menu_show(element)
{
	//this.manager.log[this.manager.log.length] = "menu show: " + this.id;

	//immediately hide all other menus
	for (var i=0; i<this.manager.menusList.length; i++)
	{
		var menu = this.manager.menusList[i];
		if (menu != this && menu.isOpen)
			menu.hide(true);
	}

	//cancel hiding action
	if (this.hideTimer)
		window.clearTimeout(this.hideTimer);

	if (!this.isOpen)
	{
		//reposition menu, if necessary
		if (!this.manager.positionFixed)
			item_reposition(element,this.container);
		this.slide(true);
	}
}

function menu_slide(isOpening)
{
	//this.manager.log[this.manager.log.length] = "menu slide: " + this.id + " isOpening: " + isOpening;

	this.isOpen = isOpening;

	if (isOpening)
		this.container.style.visibility = "visible";

	if (this.manager.useSliding)
	{
		if (this.animationTimer)
			window.clearInterval(this.animationTimer);
		this.slideStartTime = (new Date()).getTime();
		this.animationTimer = window.setInterval(this.manager.id + ".menus['" + this.id + "'].slideIncrement();", this.manager.minInterval);
	}
	else
		this.finishSlide();
}

function menu_slideIncrement()
{
	var elapsedTime = (new Date()).getTime() - this.slideStartTime;
	if (elapsedTime <= this.manager.animationTime)
	{
		var position = Math.round(Math.pow(this.manager.animationTime - elapsedTime, 2) * this.acceleration)
		if (this.isOpen && this.manager.directionMod == "-")
			position = -position;
		else if (this.isOpen && this.manager.directionMod == "+")
			position = -position;
		else if (!this.isOpen && this.manager.directionMod == "-")
			position = -this.relevantDimension + position;
		else
			position = this.relevantDimension + position;

		this.moveTo(position);
	}
	else
		this.finishSlide()
}