// =================================================================================
// Class properties
// =================================================================================
DropMenu.registry = [];
DropMenu.submenuRegistry = [];
DropMenu.animationLength = 150;
DropMenu.minCPUResolution = 10;
DropMenu.hideDelay = 200;
DropMenu.openDelay = 300;
// =================================================================================
// End Class properties
// =================================================================================


// =================================================================================
// Define constructor
// =================================================================================
function DropMenu(id,direction,useOpenDelay) {
	// Define instance properties
	//
	// Class variables
	this.id = id;
	this.direction = direction;
	DropMenu.registry[id] = this;
	this.useOpenDelay = useOpenDelay ? true : false;
	//
	// HTML variables
	this.htmlVariablesSet = false;
	this.menu_rootNode = null;
	this.menuNode = null;
	this.height = null;
	this.width = null;
	this.iFrameNode = 0;
	//
	// Animation variables
	this.hideTimer = false;
	this.showTimer = false;
	this.submenuHideTimer = false;
	this.aniTimer = false;
	this.open = false;
	this.over = false;
	this.startTime = 0;
	this.animationHeight = null;
}
// =================================================================================
// End define constructor
// =================================================================================


// =================================================================================
// Define Class methods
// =================================================================================
DropMenu.initialize = function(node) {
	// id is a string value of the node id from the current menu
	var id = node.id;
	// thisMenu is an instance of the object controling the current menu
	var thisMenu = DropMenu.registry[id];
	// Save some html variables if they not already saved
	if (!thisMenu.htmlVariablesSet) {
		// Set flag to true so we are only doing this once
		thisMenu.htmlVariablesSet = true;
		// Save the root menu node
		thisMenu.menu_rootNode = node;
		// Find the first UL child and save it, it will be our menu
		var kids = thisMenu.menu_rootNode.childNodes;
		var numKids = kids.length;
		for(var i = 0; i < numKids ; i++){
			// Look for iframes and save them
			if (kids[i].nodeName == 'IFRAME') {
				thisMenu.iFrameNode = kids[i];
			}
			if (kids[i].nodeName == 'UL') {
				// Save the first UL child, this is our menu
				thisMenu.menuNode = kids[i];
			}
		}
		// Save the width and height
		thisMenu.width = thisMenu.menuNode.offsetWidth;
		thisMenu.height = thisMenu.menuNode.offsetHeight;
		// show the menu and hide it with clip
		thisMenu.menuNode.style.visibility = "visible";
		thisMenu.menuNode.style.clip ="rect(0px 0px 0px 0px)";
		// Set up the iframe
		if (thisMenu.iFrameNode) {
			thisMenu.iFrameNode.style.width = thisMenu.width + "px";
			thisMenu.iFrameNode.style.height = thisMenu.height + "px";
			thisMenu.iFrameNode.style.visibility = "visible";
			thisMenu.iFrameNode.style.clip ="rect(0px 0px 0px 0px)";
			thisMenu.iFrameNode.style.overflow = "hidden";
		}
		// Find out if there are any submenus and safe them to an array
		var kids = thisMenu.menuNode.childNodes;
		var numKids = kids.length;
		for(var i = 0; i < numKids ; i++){
			// if the childNode has an id then it's probable be a submenu
			if (kids[i].id) {
				// Save a reference of the submenu Class instance in var thisSubmenu
				var thisSubmenu = DropMenu.registry[kids[i].id];
				// Save the root of this submenu node
				thisSubmenu.menu_rootNode = kids[i];
				// Save a reference in an array linking the submenu to the root menu parent node
				DropMenu.submenuRegistry[kids[i].id] = node;
				// Create mouseover and mouseout functions for the root submenu node
				thisSubmenu.menu_rootNode.onmouseover=DropMenu.submenuOnMouseOver;
				thisSubmenu.menu_rootNode.onmouseout=DropMenu.submenuOnMouseOut;
				// Find the first UL child and save it, it will be our submenu
				var kids = thisSubmenu.menu_rootNode.childNodes;
				var numKids = kids.length;
				for(var i = 0; i < numKids ; i++){
					if (kids[i].nodeName == 'UL') {
						// Save the first UL child, this is our submenu
						thisSubmenu.menuNode = kids[i];
					}
				}
				// Save the width and height
				thisSubmenu.width = thisSubmenu.menuNode.offsetWidth;
				thisSubmenu.height = thisSubmenu.menuNode.offsetHeight;
			}
		}
		// Create mouseover and mouseout functions for the root menu node
		thisMenu.menu_rootNode.onmouseover=DropMenu.onMouseOver;
		thisMenu.menu_rootNode.onmouseout=DropMenu.onMouseOut;
		
		// Call DropMenu.onMouseOver
		node.onmouseover();
	}
}
//
//
DropMenu.closeAll = function() {}
//
//
DropMenu.onMouseOver = function(mouseEvent) {
	// id is a string value of the node id from the current menu
	var id = this.id;
	
	// reg is an instance of the DropMenu.registry array which holds a referance to
	// all the menu objects created with the constructor
	var reg = DropMenu.registry;
	var obj = DropMenu.registry[id];
	
	obj.over = true;
	
	// loop through all the menus in the registry and close other menus.
	for (menu in reg) if (id != menu) DropMenu.hide(menu);
	
	// if this menu is scheduled to close, cancel it.
	if (obj.hideTimer) { reg[id].hideTimer = window.clearTimeout(reg[id].hideTimer) }
	
	// if this menu is closed, open it.
	if (!obj.open && !obj.aniTimer && !obj.useOpenDelay) reg[id].startSlide(true);
	
	if (!obj.open && !obj.aniTimer && obj.useOpenDelay) {
		//reg[id].startSlide(true);
		if (obj.showTimer) window.clearTimeout(obj.showTimer);
		obj.showTimer = window.setTimeout(function(){obj.startSlide(true);},DropMenu.openDelay);
	}
}
//
//
DropMenu.onMouseOut = function(mouseEvent) {
	// id is a string value of the node id from the current menu
	var id = this.id;
	
	// schedules the menu to close after <hideDelay> ms, which
	// gives the user time to cancel the action if they accidentally moused out
	var obj = DropMenu.registry[id];
	if (obj.hideTimer) window.clearTimeout(obj.hideTimer);
	if (obj.showTimer) window.clearTimeout(obj.showTimer);
	obj.hideTimer = window.setTimeout("DropMenu.hide('" + id + "')", DropMenu.hideDelay);
}
//
//
DropMenu.submenuOnMouseOver = function(mouseEvent) {
	// id is a string value of the node id from the current menu
	var id = this.id;
	var rootMenu = (DropMenu.submenuRegistry[id]).id;
	var submenuObj = DropMenu.registry[id];
	var rootMenuObj = DropMenu.registry[rootMenu];
	
	window.clearTimeout(submenuObj.submenuHideTimer);
	// flag that this scheduled event has occured.
	submenuObj.submenuHideTimer = 0;
	
	submenuObj.menuNode.style.visibility = "visible";
	//rect (top, right, bottom, left)
	rootMenuObj.menuNode.style.clip ="rect(0px "+ (rootMenuObj.width + submenuObj.width) +"px "+ ((rootMenuObj.height)+(submenuObj.height)) +"px "+ (submenuObj.width)*-1 +"px)";
}
//
//
DropMenu.submenuOnMouseOut = function(mouseEvent) {
	// id is a string value of the node id from the current menu
	var id = this.id;
	var submenuObj = DropMenu.registry[id];
	
	if (submenuObj.submenuHideTimer) window.clearTimeout(submenuObj.submenuHideTimer);
	submenuObj.submenuHideTimer = window.setTimeout(function(){submenuObj.menuNode.style.visibility = "hidden";},DropMenu.hideDelay);
}
//
//
DropMenu.hide = function(id) {
	var obj = DropMenu.registry[id];
	obj.over = false;

	if (obj.hideTimer) window.clearTimeout(obj.hideTimer);
	
	// flag that this scheduled event has occured.
	obj.hideTimer = 0;

	// if this menu is open, close it.
	if (obj.open && !obj.aniTimer) obj.startSlide(false);

}
// =================================================================================
// End define Class methods
// =================================================================================


// =================================================================================
// Define Class instance methods
// =================================================================================
DropMenu.prototype.startSlide = function(open) {
	this[open ? "onactivate" : "ondeactivate"]()
	this.open = open;
	//if (open) this.setVisibility(true);
	var self = this;
	this.startTime = (new Date()).getTime();
	this.aniTimer = window.setInterval(function(){self.slide();},DropMenu.minCPUResolution);
}
//
//
DropMenu.prototype.endSlide = function() {
	this.aniTimer = window.clearTimeout(this.aniTimer)
	//this.moveTo(this.open ? this.outPos : this.homePos)
	if (this.open) {
		// open position
		//rect (top, right, bottom, left)
		this.menuNode.style.clip ="rect(auto auto auto auto)";
		if (this.iFrameNode) {
			this.iFrameNode.style.clip ="rect(auto auto auto auto)";
		}
	} else {
		// closed position
		this.menuNode.style.clip ="rect(0px 0px 0px 0px)";
		if (this.iFrameNode) {
			this.iFrameNode.style.clip ="rect(0px 0px 0px 0px)";
		}
	}
	//if (!this.open) this.setVisibility(false)
	if ((this.open && !this.over) || (!this.open && this.over)) {
		this.startSlide(this.over);
	}
}
//
//
DropMenu.prototype.slide = function() {
	var elapsed = (new Date()).getTime() - this.startTime;
	if (elapsed > DropMenu.animationLength) this.endSlide()
	else {
		// Open or close the menu by animating clip
		var percentElapsed = elapsed/DropMenu.animationLength;
		this.animationHeight = Math.round(this.height * percentElapsed);
		//
		if (this.open) {
			// open it
			if (this.direction == "up") {
				//rect (top, right, bottom, left)
				this.animationHeight = this.height +(this.animationHeight*-1);
				this.menuNode.style.clip ="rect("+ this.animationHeight +"px " + this.width + "px "+ this.height +"px 0px)";
				if (this.iFrameNode) {
					this.iFrameNode.style.clip ="rect("+ this.animationHeight +"px " + this.width + "px "+ this.height +"px 0px)";
				}
			} else if (this.direction == "down") {
				// animate clip down
				this.menuNode.style.clip ="rect(0px " + this.width + "px "+ this.animationHeight +"px 0px)";
				if (this.iFrameNode) {
					this.iFrameNode.style.clip ="rect(0px " + this.width + "px "+ this.animationHeight +"px 0px)";
				}
			}
			//
			//var debugNode2 = document.getElementById('debug02');
			//debugNode2.innerHTML = "this.animationHeight: " + this.animationHeight;
		} else {
			// close it
			if (this.direction == "up") {
				//
				this.menuNode.style.clip ="rect("+ this.animationHeight +"px " + this.width + "px "+ this.height +"px 0px)";
				if (this.iFrameNode) {
					this.iFrameNode.style.clip ="rect("+ this.animationHeight +"px " + this.width + "px "+ this.height +"px 0px)";
				}
			} else if (this.direction == "down") {
				// animate clip closed
				this.animationHeight = this.height +(this.animationHeight*-1);
				this.menuNode.style.clip ="rect(0px " + this.width + "px "+ this.animationHeight +"px 0px)";
				if (this.iFrameNode) {
					this.iFrameNode.style.clip ="rect(0px " + this.width + "px "+ this.animationHeight +"px 0px)";
				}
			}
		}
	}
}
// Events
DropMenu.prototype.onactivate		= function() { }
DropMenu.prototype.ondeactivate	= function() { }
// =================================================================================
// End define Class instance methods
// =================================================================================
