window.all_menus_locked = false;

function openMenu(o_src, p_group, p_div, o_init) {

	if (isSubmenuUnsupported()) return;

	if (window.all_menus_locked) return;

	// unfocus on the A tag

	if (o_src.blur) o_src.blur();

	//traceFocus();

	// find the target div

	var o_div = MM_findObj(p_div);

	if (o_div) {

		// set up group

		var c_group = "menu_group_" + p_group;

		if (typeof(window[c_group]) == "undefined") window[c_group] = new MenuGroup(c_group);

		// set up controller

		var c_controller = getMenuControllerName(o_src, p_group, p_div, o_init);

		if (typeof(window[c_controller]) == "undefined") window[c_controller] = new MenuController(c_controller, o_src, o_div, window[c_group], o_init);

		// show menu

		window[c_controller].show(o_src); // call controller directly - used to be: o_div.controller.show(o_src);

	}

}

function closeMenu(p_group, p_div) {

	var o_div = MM_findObj(p_div);

	if (o_div) {

		o_div.controller.timerid=1;

		o_div.controller.hideNow();

	}

}

function getMenuControllerName(o_src, p_group, p_div, o_init) {

	var controllerName = "menu_controller_" + p_div;

	if (typeof(o_init.controllerName) == "string") controllerName = o_init.controllerName;

	return controllerName;

}



function MenuGroup(p_name) {

	this.name = p_name;

	this.menus = new Object(); // []

	this.currentmenu = "";

	// register a controller with this menu group

	this.register = function(o_controller) {

		if (this.menus[o_controller.name]) return; // use index

		//this.menus.push(o_controller); // add controller to menus array

		this.menus[o_controller.name] = o_controller; // create indexed entry too

	}

	// check if allowed to show a menu

	this.allowShow = function() {

		return (!window.all_menus_locked);

	}

	// a controller has shown a menu (hide any other menus in this group)

	this.onShow = function(o_controller) {

		if (window.all_menus_locked) return;

		if (this.currentmenu != "") {

			this.menus[this.currentmenu].hideNow(); // use index

		}

		this.currentmenu = o_controller.name;

	}

	// a controller has hidden itself

	this.onHideNow = function(o_controller) {

		if (window.all_menus_locked) return;

		if (o_controller.name == this.currentmenu) this.currentmenu = "";

	}

	// return the current controller (the menu in this group that is active)

	this.getCurrentController = function() {

		return this.getController(this.currentmenu);

	}

	// return a specific controller from this menu group

	this.getController = function(p_name) {

		if (this.menus[p_name]) {

			return this.menus[p_name]; // use index

		} else {

			return false;

		}

	}

	// lock the menus; usually comes from a MenuController; this stops menus from affecting each other

	this.lock = function() {

		window.all_menus_locked = true;

	}

	// unlock the menus; usually comes from a MenuController; this allows menus to affecting each other

	this.unlock = function() {

		window.all_menus_locked = false;

	}

	// simple string representation

	this.toString = function() {

		return "[object MenuGroup:" + this.name + "]";

	}

}

function MenuController(p_name, o_src, o_div, o_group, o_init) {

	// default init variables

	this.parentGroup = null; // if a child DHTML menu, parentGroup should contain the ID of the parent group - this will create relationships to current open menu, and keep parent menu(s) open while it is open - also overrides "align" and "valign" init features

	this.method = "nav"; // one of [ nav , visible ] - nav is for standard menus, visible is for single div show / hide functionality

	this.slide = false; // whether or not to slide the menu into place (vertically downward sliding)

	this.slideDuration = 0.5; // slide duration in seconds - never really accurate for some reason - probably window.setInterval issues

	this.slideFPS = 15; // approximate slide FPS - used to calculate time between movements

	this.align = null; // align to source - right side or left side of source (auto defaults if child menu or not) one of [ left , right , leftside , rightside ]

	this.valign = null; // align to source - bottom or top of source (auto defaults if child menu or not) one of [ top , bottom , bottomtop, bottombottom ]

	this.width = null; // width of submenu - null = CSS or HTML defined, 0 = resize to source width, [n] = actual px width

	this.onShow = null; // custom function to call when menu appears

	this.onHide = null; // custom function to call when menu disappears

	this.relativeID = null; // unique ID of DHTML element to position the submenu relative to

	this.offsetX = 0; // place the submenu n pixels to the right of the source (negative is to the left)

	this.offsetY = 0; // place the submenu below the source (negative is above)

	this.zIndex = 1000; // z-index for the menu (all the menus can be the same z-index, just need to know so the iFrame can lay below the menu)

	this.overlayMode = "iframe"; // method used to overlay the submenu on <select> tags: one of [ iframe , hide ] (any other mode means "off")

	this.overlayInset = null; // method used to insert the overlay (used for iFrames) when a portion of the menu is supposed to show through to the page beneath (ie: and shouldn't show a white corner)

	this.openMode = "onmouseover"; // one of [ onmouseover , onclick ] - if onclick, the onmouseover event will be set on the calling entity

	this.mouseGroup = []; // array of other objects' IDs that should qualify as a mouseover/out trigger once this menu has opened (these items keep it open)

	this.autoclose = []; // array of other menus to close when this one is opened

	// accept init variables

	if (typeof(o_init) == "object") for (var a in o_init) if (typeof(this[a]) != "undefined") this[a] = o_init[a];

	// set custom defaults

	if (this.valign == null) this.valign = (this.parentGroup == null) ? "bottom" : "top";

	if (this.align == null) this.align = (this.parentGroup == null) ? "right" : "auto";

	// build variables

	this.name = p_name;

	this.timerid = 0;

	this.submenu = 0;

	this.status = 0;

	this.inslide = 0;

	this.parent = null;

	// timeouts

	this.hidePause = 200;

	this.unlockHidePause = 30;

	// assign to group

	this.group = o_group;

	this.group.register(this);

	// build relationships

	this.menu = o_div;

	this.menu.controller = this;

	// assign source of menu popup

	this.assignSource = function(o_src) {

		this.source = o_src;

		this.source.controller = this;

		this.source.controllerOnShow = this.onShow; // assign onshow and onhide function to the source element

		this.source.controllerOnHide = this.onHide; // so that "this" references are intact

		this.placementSource = o_src;

	}

	this.assignSource(o_src);

	// build placement relationship

	if (typeof(this.relativeID) == "string") {

		var o_tmp = MM_findObj(this.relativeID);

		if (o_tmp) {

			this.placementSource = o_tmp;

			this.placementSource.controller = this;

		}

	}

	// functionality

	this.show = MenuController_show;

	this.hide = MenuController_hide;

	this.hideNow = MenuController_hideNow;

	this.forceHideNow = MenuController_forceHideNow;

	this.catchHide = MenuController_catchHide;

	this.slideSetup = MenuController_slideSetup;

	this.slideStep = MenuController_slideStep;

	this.stopSlider = MenuController_stopSlider;

	this.showIFrame = MenuController_showIFrame;

	this.hideIFrame = MenuController_hideIFrame;

	this.setWidth = MenuController_setWidth;

	this.showOverlay = MenuController_showOverlay;

	this.hideOverlay = MenuController_hideOverlay;

	this.assignParent = MenuController_assignParent;

	this.includeObjectInMenuGroup = MenuController_includeObjectInMenuGroup;

	this.unincludeObjectInMenuGroup = MenuController_unincludeObjectInMenuGroup;

	this.catchFormSelects = MenuController_catchFormSelects;

	this.uncatchFormSelects = MenuController_uncatchFormSelects;

	this.lockMenu = MenuController_lockMenu;

	this.unlockMenu = MenuController_unlockMenu;

	this.catchUnlockHide = MenuController_catchUnlockHide;

	this.toString = function() { return "[object MenuController:" + this.name + "]"; };

	// complete initialization

	this.slideSetup();

	this.setWidth();

}



function MenuController_includeObjectInMenuGroup(o) {

	o.controller = this;

	o.onclick = function() { this.controller.catchUnlockHide(); };

	o.onmouseover = function() { this.controller.catchHide(); };

	o.onmouseout = function() { this.controller.hide(); };

}

function MenuController_unincludeObjectInMenuGroup(o) {

	// leave o.controller for subsequent mouseovers

	o.onfocus = function() {};

	o.onmouseover = function() {};

	o.onmouseout = function() {};

}



function MenuController_catchFormSelects() {

	// find all the form selects inside the menu element

	var ar_selects = this.menu.getElementsByTagName("SELECT");

	for (var i=0; i<ar_selects.length; i++) {

		// when select is in focus, lock the menu, when blur unlock the menu

		ar_selects[i].controller = this;

		ar_selects[i].onfocus = function() { this.controller.lockMenu(); };

		ar_selects[i].onblur = function() { this.controller.unlockMenu(); this.controller.hide(); };

	}

}

function MenuController_uncatchFormSelects() {

	// find all the form selects inside the menu element

	var ar_selects = this.menu.getElementsByTagName("SELECT");

	for (var i=0; i<ar_selects.length; i++) {

		// when select is in focus, lock the menu, when blur unlock the menu

		ar_selects[i].onfocus = function() { };

		ar_selects[i].onblur = function() { };

	}

}



function MenuController_lockMenu() {

	this.group.lock();

	this.locked = true;

}

function MenuController_unlockMenu() {

	this.locked = false;

	this.group.unlock();

}

function MenuController_catchUnlockHide() {

	this.unlocktimerid = window.setTimeout(this.name + ".catchHide();", this.unlockHidePause);

}



function MenuController_show(o_src) {

	// verify parent is same

	if (o_src && o_src != this.source) this.assignSource(o_src);

	// check if group allows showing a menu currently

	if (!this.group.allowShow()) return;

	// check for parent groups - if this is a subnav

	this.assignParent();

	// if currently visible, just stop any pending hide calls

	if (this.status) {

		this.catchHide();

	} else {

		// tell group

		this.group.onShow(this);

		// assign functions

		if (this.openMode == "onclick") this.source.onmouseover = function() { this.controller.catchHide(); };

		this.source.onmouseout = function() { this.controller.hide(); };

		this.includeObjectInMenuGroup(this.menu);

		// assign functions to additional mouse-group items

		for (var i=0; i<this.mouseGroup.length; i++) {

			var o=MM_findObj(this.mouseGroup[i]);

			if (o) this.includeObjectInMenuGroup(o);

		}

		// check for forms with select tags

		this.catchFormSelects();

		// close other menus as specified

		for (var i=0; i<this.autoclose.length; i++) {

			var o=MM_findObj(this.autoclose[i]);

			if (o && o.controller) o.controller.forceHideNow();

		}

		// standard navigation popup

		if (this.method == "nav") {

			// find x,y for menu

			var ar_loc = findPos(this.placementSource); // item to align to

			ar_loc[0] += this.offsetX;

			ar_loc[1] += this.offsetY;

			if (this.valign.toLowerCase() == "bottom") ar_loc[1] += this.placementSource.offsetHeight;

			if (this.valign.toLowerCase() == "bottomtop") ar_loc[1] -= this.menu.offsetHeight;

			if (this.valign.toLowerCase() == "bottombottom") ar_loc[1] -= (this.menu.offsetHeight - this.placementSource.offsetHeight);

			// position the menu

			if (this.parent) {

				// sub menus

				var my_align = this.align.toLowerCase();

				if (my_align == "auto") { // determine if it will fit to the right, else place at left

					if (ar_loc[0] + this.placementSource.offsetWidth + this.menu.offsetWidth > document.body.clientWidth) {

						my_align = "left";

					} else {

						my_align = "right";

					}

				}

				var my_left = (my_align == "right") ? ar_loc[0] + this.placementSource.offsetWidth : ar_loc[0] - this.menu.offsetWidth;

			} else {

				// primary menus

				var my_align = this.align.toLowerCase();

				var my_left = 0;

				if (my_align == "right") my_left = ar_loc[0] - this.menu.offsetWidth + this.placementSource.offsetWidth;

				if (my_align == "left") my_left = ar_loc[0];

				if (my_align == "leftside") my_left = ar_loc[0] - this.menu.offsetWidth;

				if (my_align == "rightside") my_left = ar_loc[0] + this.placementSource.offsetWidth;

				//var my_left = (this.align.toLowerCase() == "right") ? ar_loc[0] - this.menu.offsetWidth + this.placementSource.offsetWidth : ar_loc[0];

			}

			this.menu.style.left = my_left + "px";

			if (this.slide) {

				// start sliding

				this.clipTop = ar_loc[1];

				this.slideStart = ar_loc[1] - this.menu.offsetHeight;

				this.slideEnd = (ar_loc[1]);

				this.sliderid = window.setInterval(this.name + ".slideStep();", this.slidems);

			} else {

				this.menu.style.top = (ar_loc[1]) + "px";

				this.menu.style.visibility = "visible";

			}

			this.menu.style.zIndex = this.zIndex;

		} else if (this.method == "visible") {

			// simply make the div visible

			this.menu.style.visibility = "visible";

		}

		if (this.method == "nav" && !this.slide) this.showOverlay();

		this.status=true;

		// call user-defined function for onShow

		if (typeof(this.source.controllerOnShow) == "function") this.source.controllerOnShow();

	}

}

function MenuController_hide() {

	if (!this.locked && !this.timerid) {

		this.timerid = window.setTimeout(this.name + ".hideNow();", this.hidePause);

		if (this.parent) this.parent.hide();

	}

}

function MenuController_hideNow() {

	if (this.timerid) {

		// unset functions

		this.source.onmouseout = function() {};

		this.unincludeObjectInMenuGroup(this.menu);

		// assign functions to additional mouse-group items

		for (var i=0; i<this.mouseGroup.length; i++) {

			var o=MM_findObj(this.mouseGroup[i]);

			if (o) this.unincludeObjectInMenuGroup(o);

		}

		// check for forms with select tags

		this.uncatchFormSelects();

		// hide

		this.menu.style.visibility = "hidden";

		this.group.onHideNow(this);

		this.timerid = 0;

		// standard navigation popup

		if (this.method == "nav") {

			this.menu.style.left = "0px"; // keeps menus inside page, if page is resized when menus are hidden

			// stop slider

			this.stopSlider();

			this.hideOverlay();

		}

		this.status=false;

		// hide submenu

		if (this.submenu) this.submenu.hideNow();

		// call user-defined function for onHide

		if (typeof(this.source.controllerOnHide) == "function") this.source.controllerOnHide();

	}

}

function MenuController_forceHideNow() {

	this.timerid = 1;

	this.hideNow();

}

function MenuController_catchHide() {

	if (this.timerid) {

		window.clearTimeout(this.timerid);

		this.timerid = 0;

		if (this.parent) this.parent.catchHide();

	}

}

function MenuController_slideSetup() {

	if (this.slide == true && !isNaN(this.slideDuration) && !isNaN(this.slideFPS)) {

		this.slidems = Math.floor(1000 / this.slideFPS);

		this.slideFrames = this.slideDuration * this.slideFPS;

		this.slidePosition = 0;

		this.inslide = 0;

	}

}

function MenuController_slideStep() {

	this.slidePosition++;

	if (this.slidePosition > this.slideFrames) this.slidePosition = this.slideFrames;

	if (!this.inslide) {

		this.inslide = 1;

		var slideOffset = (this.slideEnd - this.slideStart) * (this.slidePosition / this.slideFrames);

		var myClipTop = this.clipTop - slideOffset;

		// build clip and show menu

		if (this.menu.style.visibility != "visible") this.menu.style.visibility = "visible";

		this.menu.style.clip = "rect(" + Math.ceil(myClipTop - this.slideStart) + "px " + this.menu.offsetWidth + "px " + this.menu.offsetHeight + "px 0px)";

		this.menu.style.top = (this.slideStart + slideOffset) + "px";

		// stop sliding if at end

		if (this.slidePosition >= this.slideFrames) this.stopSlider();

		this.inslide = 0;

	}

}

function MenuController_stopSlider() {

	if (this.sliderid) {

		if (this.slide) this.showOverlay();

		window.clearInterval(this.sliderid);

		this.sliderid = 0;

		this.slidePosition = 0;

	}

}

function MenuController_showOverlay() {

	if (this.overlayMode.toLowerCase() == "iframe") {

		this.showIFrame();

	} else if (this.overlayMode.toLowerCase() == "hide") {

		hideF();

	}

}

function MenuController_hideOverlay() {

	if (this.overlayMode.toLowerCase() == "iframe") {

		this.hideIFrame();

	} else if (this.overlayMode.toLowerCase() == "hide") {

		showF();

	}

}

function MenuController_showIFrame() {

	if (isexplorer) {

		if (!this.frameBackground) {

			var o_frame = document.createElement("IFRAME")

			o_frame.style.position = "absolute";

			o_frame.style.border = "0px";

			o_frame.frameBorder = "0px";

			o_frame.style.zIndex = (this.zIndex - 1);

			document.body.appendChild(o_frame);

			this.frameBackground = o_frame;

		}

		if (this.overlayInset) {

			this.frameBackground.style.top = (this.menu.offsetTop + this.overlayInset[0]) + "px";

			this.frameBackground.style.left = (this.menu.offsetLeft + this.overlayInset[3]) + "px";

			this.frameBackground.style.height = (this.menu.offsetHeight - this.overlayInset[0] - this.overlayInset[2]) + "px";

			this.frameBackground.style.width = (this.menu.offsetWidth - this.overlayInset[1] - this.overlayInset[3]) + "px";

		} else {

			this.frameBackground.style.top = (this.menu.offsetTop) + "px";

			this.frameBackground.style.left = (this.menu.offsetLeft) + "px";

			this.frameBackground.style.height = (this.menu.offsetHeight) + "px";

			this.frameBackground.style.width = (this.menu.offsetWidth) + "px";

		}

	}

}

function MenuController_hideIFrame() {

	if (isexplorer) {

		if (this.frameBackground) {

			document.body.removeChild(this.frameBackground);

			this.frameBackground = null;

			delete(this.frameBackground);

		}

	}

}

function MenuController_setWidth() {

	if (!isNaN(this.width)) {

		if (this.width == 0) this.menu.style.width = this.source.offsetWidth;

		else this.menu.style.width = this.width;

	}

}

function MenuController_assignParent() {

	if (this.parentGroup) {

		var o_parentGroup = window["menu_group_" + this.parentGroup];

		if (o_parentGroup) {

			var o_parent = o_parentGroup.getCurrentController();

			if (o_parent) {

				this.parent = o_parent;

				this.parent.child = this;

				//alert("assigned " + this.name + " as child to " + this.parent.name);

			}

		}

	}

}



/*function trace(t) {

	var o = MM_findObj("txt_stdout"); if (o) o.value += t + "\n";

}

function traceFocus() {

	var o = MM_findObj("txt_stdout")

	if (o) o.focus();

}*/





// ================================================= //

// Show and hide all <select> objects in all forms   //

// ================================================= //

function hideF(){for(var i=document.forms.length-1;i>=0;i--){var form=document.forms[i];for(var j=form.elements.length-1;j>=0;j--){var elmt=form.elements[j];var e_s=elmt.style;if((elmt.type=="select-one"||elmt.type=="select-multiple")&&elmt.className!='donthide'&&e_s.vbak==null){e_s.vbak=e_s.visibility;e_s.visibility="hidden";}}}};



function showF(){for(var i=document.forms.length-1;i>=0;i--){var form=document.forms[i];for(var j=form.elements.length-1;j>=0;j--){var elmt=form.elements[j];var e_s=elmt.style;if((elmt.type=="select-one"||elmt.type=="select-multiple")&&e_s.vbak!=null){e_s.visibility=e_s.vbak;e_s.vbak=null;}}}};



// ================================================= //

// Find object location in pixels as array [x,y]     //

// ================================================= //

isopera = (navigator.userAgent.indexOf("Opera")>=0);

isexplorer = (!isopera && navigator.userAgent.indexOf("MSIE")>=0);

issafari = (navigator.userAgent.indexOf("Safari")>=0);

isgecko = (navigator.userAgent.indexOf("Gecko")>=0) && !issafari;

function findPos(obj) {

	var curleft = 0;

	var curtop = 0;

	var self = true;

	while (obj.offsetParent) {

		curleft += obj.offsetLeft;

		curtop += obj.offsetTop;

		if (isexplorer && !self) {

			// fix for IE - some CSS borders cause offset

			curleft += obj.clientLeft;

			curtop += obj.clientTop;

		}

		obj = obj.offsetParent;

		self = false;

	}

	if (issafari) {

		// safari doesn't consider

		curleft += document.body.offsetLeft;

		curtop += document.body.offsetTop;

	}

	return [curleft,curtop];

}

function isSubmenuUnsupported() {

	if (isexplorer) {

		var loc = navigator.userAgent.indexOf("MSIE") + 5;

		var ver = parseFloat(navigator.userAgent.substr(loc, 3));

		if (!isNaN(ver) && ver < 5) return true;

	}

	return false;

}
