//This class implements the logic for a menu system.
//Each object is initialized with a menu element, its parent menu
//element, and its child menu element. There is no limit on the
//number of submenu level.

function dhtmlMenu(topElement, subDiv, parentMenu) {
	this.oElement = topElement; //top menu
	this.oDiv = subDiv; //sub menu container associated with top menu
	this.oParent = parentMenu; //parent container of top menu
	this.externalMainMenuEvent;
	this.externalSubMenuEvent;
	this.displayRight; //display the 1st sub-menu to right (default is bottom)
  this.clickToActivate = false;

	this.xadj = 0;
	this.yadj = 0;
	this.delayOpen = 50;
  this.delayClose = 100;
}	

//function properties - static variables

//the current active top level menu
dhtmlMenu.currentMenu = null;
dhtmlMenu.changeTopMenuEvent = null;
//next top level menu
dhtmlMenu.nextMenu = null;
//the timer to hide the current top level menu
//and all its submenu
dhtmlMenu.timeoutId = null;
//delay event for parent menu;
dhtmlMenu.parentMenu = null;
dhtmlMenu.timeoutId2 = null;

dhtmlMenu._collection = new Object();

//object methods inherited through the
//prototype object

dhtmlMenu.prototype.init = function() {
	var eventFunction = function(e) {dhtmlMenu._collection[this.id].onMainMenuEvent(e);};
	dhtmlMenu._collection[this.oElement.id] = this;
	this.oElement.onmouseover = eventFunction;
	this.oElement.onmouseout = eventFunction;
	this.oElement.onclick = eventFunction;
	
	eventFunction = function(e) {dhtmlMenu._collection[this.id].onSubMenuEvent(e);};
	this.oDiv.style.visibility = 'hidden';
	dhtmlMenu._collection[this.oDiv.id] = this;
	this.oDiv.onmouseover = eventFunction;
	this.oDiv.onmouseout = eventFunction;
}
	
dhtmlMenu.prototype.init2 = function _dhtmlMenu_init2() {
	this.oDiv.style.visibility = 'hidden';
}

//event handler of the parent menu
dhtmlMenu.prototype.onMainMenuEvent = function(evt, type) {
	if (evt && !window.event) {type = evt.type;}
	if (!type) type = window.event.type;
	switch (type) {
	case 'mouseover':
    if (!this.clickToActivate && !dhtmlMenu.currentMenu && !this.oParent) {
        dhtmlMenu.currentMenu = this.oElement;
		}
		else if (!dhtmlMenu.currentMenu) break;
		this._disableTimer(); //disable timer to close top level menu
		//check if mouse is over a top level menu
		//or a submenu
		if (!this.oParent) {
			//delay opening the top menu
			dhtmlMenu.nextMenu = this.oElement;
			dhtmlMenu.timeoutId = window.setTimeout('dhtmlMenu._collection[\'' + dhtmlMenu.nextMenu.id + '\']._changeTopMenu(); dhtmlMenu.timeoutId = null; dhtmlMenu.nextMenu = null;', this.delayOpen);
		}
		else {
			//delay opening the child menu
			this._disableTimer2();
			dhtmlMenu.parentMenu = this.oElement;
			dhtmlMenu.timeoutId2 = window.setTimeout('dhtmlMenu._collection[\'' + dhtmlMenu.parentMenu.id + '\']._displayChildMenu(); dhtmlMenu.parentMenu = null; dhtmlMenu.timeoutId2 = null', 350);
		}
		break;
	case 'mouseout':
    if (!dhtmlMenu.currentMenu) break;
		this._disableTimer(); //disable timer to close top level menu
		this._disableTimer2(); //disable timer to open child menu
		//reset timer to switch off the top level menu and its child menu
		if (!this.clickToActivate && !this.oParent && this.oDiv.style.visibility == 'hidden' && dhtmlMenu.currentMenu == this.oElement)
    	dhtmlMenu.currentMenu = null;
    else dhtmlMenu.timeoutId = window.setTimeout('dhtmlMenu._collection[\'' + dhtmlMenu.currentMenu.id + '\']._switchDiv(false); if (dhtmlMenu.changeTopMenuEvent) dhtmlMenu.changeTopMenuEvent(dhtmlMenu.currentMenu, null); dhtmlMenu.currentMenu = null; dhtmlMenu.timeoutId = null', this.delayClose);
		break;
	case 'click':
		//initiate automatic mouseover and mouseout responses
		//to the entire menu system. The click event is applied
		//only to the top level menu.
		if (!dhtmlMenu.currentMenu && !this.oParent) {
			dhtmlMenu.currentMenu = this.oElement;
			this._changeTopMenu();
		}
		break;
	}
	if (this.externalMainMenuEvent) this.externalMainMenuEvent(evt, type);
}

//event handler of the child menu
dhtmlMenu.prototype.onSubMenuEvent = function(evt, type) {
	if (evt && !window.event) {type = evt.type;}
	if (!type) type = window.event.type;
	switch (type) {
	case 'mouseover':
		this._disableTimer();
		break;
	case 'mouseout':
		this._disableTimer();
		//set timer to switch off the top level menu
		dhtmlMenu.timeoutId = window.setTimeout('dhtmlMenu._collection[\'' + dhtmlMenu.currentMenu.id + '\']._switchDiv(false); if (dhtmlMenu.changeTopMenuEvent) dhtmlMenu.changeTopMenuEvent(dhtmlMenu.currentMenu, null); dhtmlMenu.currentMenu = null; dhtmlMenu.timeoutId = null', this.delayClose);
		break;
	}
	if (this.externalSubMenuEvent) this.externalSubMenuEvent(evt, type);
	//if (window.event) event.cancelBubble = true;
	//else evt.stopPropagation();
}

//toggle the child menu on-off
dhtmlMenu.prototype._switchDiv = function(active) {
	if (active) {
		//the top level menu is active
		var pos = this._calcPos(this.oElement);
		if (!this.oParent) {
			//parent menu is the top level menu
			//calculate the display position of the child menu
			if (this.displayRight) pos.x += this.oElement.offsetWidth;
			else pos = {x:pos.x, y:pos.y + this.oElement.offsetHeight};
			this.oDiv.style.left = pos.x + this.xadj;
			this.oDiv.style.top = pos.y + this.yadj;
		}
		else {
			//parent menu is not a top level menu
			//calculate the display position of the child menu
			this.oDiv.style.left = pos.x + this.oParent.offsetWidth + this.xadj;
			this.oDiv.style.top = pos.y + this.yadj;
		}
		//display child menu
		this.oDiv.style.visibility = 'visible';
	}
	else {
		//the top level menu is no longer active
		if (this.oDiv.childMenu) {
			//switch off all child's child-menu
			this.oDiv.childMenu._switchDiv(active);
			this.oDiv.childMenu = null;
		}
		//switch off the child menu of the top level menu
		this.oDiv.style.visibility = 'hidden';
    this.oDiv.style.top = '0';
    this.oDiv.style.left = '0';
	}
}

//disable the timer to switch off the top level menu
dhtmlMenu.prototype._disableTimer = function() {
	if (dhtmlMenu.timeoutId) {
		window.clearTimeout(dhtmlMenu.timeoutId);
		dhtmlMenu.timeoutId = null;
	}
}

//disable the timer to switch off the top level menu
dhtmlMenu.prototype._disableTimer2 = function() {
	if (dhtmlMenu.timeoutId2) {
		window.clearTimeout(dhtmlMenu.timeoutId2);
		dhtmlMenu.timeoutId2 = null;
	}
}

dhtmlMenu.prototype._changeTopMenu = function() {
	//switch off previous active top level menu
	var prevMenu = dhtmlMenu.currentMenu;
	if (prevMenu && (prevMenu != this.oElement)) {
		dhtmlMenu._collection[prevMenu.id]._disableTimer();
		dhtmlMenu._collection[prevMenu.id]._switchDiv(false);
	}
	//set current menu and switch it on
	dhtmlMenu.currentMenu = this.oElement;
	this._switchDiv(true);
	if (dhtmlMenu.changeTopMenuEvent) dhtmlMenu.changeTopMenuEvent(prevMenu, this.oElement);
}

dhtmlMenu.prototype._displayChildMenu = function() {
	var prevChild = this.oParent.childMenu;
	if (prevChild) prevChild._switchDiv(false);
	this.oParent.childMenu = this;
	this._switchDiv(true);
}

//calculate the position relative to the client screen
dhtmlMenu.prototype._calcPos = function(thisElement) {
	var oParent = thisElement.offsetParent;
	var i = 50; //limit to 50 iteration
	var oBody = document.body;
	var pos = {x:thisElement.offsetLeft, y:thisElement.offsetTop};
	while (i-- > 0 && oParent != oBody) {
		pos.x += oParent.offsetLeft - 0; //position correction for padding
		pos.y += oParent.offsetTop - 0; //position correction for padding
		oParent = oParent.offsetParent;
	}
	return pos;
}


