/*
###############################################################################
# Copyright 2001-2002, Nick Campbell, All Rights Reserved
#
# You are free to use this code within your own web sites,
# but you are expressly forbidden from selling or otherwise
# distributing this source code without prior written consent.
# This includes both posting free demo projects made from this
# code as well as reproducing the code in text or html format.
###############################################################################
*/
	//#### Setup the browser 'UDT'
function Browser() {
	with (navigator.userAgent) {
		this.isOpera = (indexOf('Opera') >= 0);
		this.isIE = (indexOf('MSIE') >= 0 && ! this.isOpera);
		this.isGecko = (indexOf('Gecko') >= 0);
		this.isMozilla = (indexOf('Mozilla') >= 0 && ! this.isIE && ! this.isGecko && ! this.isOpera);
	}
}

	//#### Declare the necessary global vars
var oBrowser = new Browser();
var iZTop = 100;

	//#### Returns a reference to the passed sElementID
function GetByID(sElementID) {
	if (oBrowser.isMozilla)						{ eval('var temp = document.' + sElementID + ';'); return temp; }
	else										{ return document.getElementById(sElementID); }
}

	//#### Return the true x/y coordinates of oElement (via recursion of all parent elements)
function TrueX(oElement) {
	return Number(oElement.offsetLeft + (oElement.offsetParent ? TrueX(oElement.offsetParent) : 0));
}
function TrueY(oElement) {
	return Number(oElement.offsetTop + (oElement.offsetParent ? TrueY(oElement.offsetParent) : 0));
}

	//#### Return the true x/y coordinates of the cursor
function TruePageX() {
		//#### Determine the cursor's x/y offset
	if (oBrowser.isIE) {
		return window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
	}
	else if (oBrowser.isGecko) {
		return event.clientX + window.scrollX;
	}
	else if (oBrowser.isOpera) {
		return event.clientX;
	}
	else {
		return event.pageX;
	}
}
function TruePageY() {
		//#### Determine the cursor's x/y offset
	if (oBrowser.isIE) {
		return window.event.clientY + document.documentElement.scrollTop + document.body.scrollTop;
	}
	else if (oBrowser.isGecko) {
		return event.clientY + window.scrollY;
	}
	else if (oBrowser.isOpera) {
		return event.clientY;
	}
	else {
		return event.pageY;
	}
}

	//#### Declare the constants
var cSTANDARD = 0;
var cPERSIST = 1;
var cCHILD = 2;

	//#### Declare the necessary global vars
var sCurrentDIV = '';
var bCloseDIV = true;
var iMozillaHOffset = 100;
var iMozillaVOffset = 0;
var iChildHOffset = -5;

	//#### Set the browser to HideCurrentDIV() on either a Body:MouseDown or Body:MouseMove (MouseMove in Gen 5's+ only)
if (oBrowser.isMozilla) {
	document.captureEvents(Event.MOUSEDOWN);
	document.onmousedown = HideCurrentDIV;

		//#### Set the mozilla vertical offset for the page from the A style definition (since the A tag is really the only tag that generated a OnMouseOver event in NS4)
	if (document.tags.A.fontSize && iMozillaHOffset == 0) {
		iMozillaVOffset = parseInt(document.tags.A.fontSize);
	}
}
else {
	document.onmouseover = HideCurrentDIV;
	document.onmousedown = HideCurrentDIV;
}

	//#### Hides the passed sDIVName
function HideDIV(sDIVName, bForce, sParentDIV) {
		//#### If sDIVName has a value and it's not the sParentDIV
	if (sDIVName.length > 0 && sDIVName != sParentDIV) {
		var oDIV = GetByID(sDIVName);

			//#### If this is not a persistant DIV or the caller is forcing its close
		if (! oDIV.persist || bForce) {
			if (oBrowser.isMozilla) {
				oDIV.visibility = 'hidden';
			}
			else {
				oDIV.style.visibility = 'hidden';
					//#### If there are values in the aHideElements array, unhide the troublesome form elements
				if (aHideElements.length > 0)	{ ShowHideElement(aHideElements, sDIVName, cSHOW); }
			}

				//#### If this DIV has a parent DIV, close it now and reset it's value
			if (oDIV.sParentDIV) {
				HideDIV(oDIV.sParentDIV, true, sParentDIV);
				oDIV.sParentDIV = '';
			}
		}
	}
}

	//#### Hides the child DIV of the passed sParentDIV
function HideChildDIV(sParentDIV) {
		//#### Hide the DIVs up to the new sParentDIV and set sCurrentDIV
	HideDIV(sCurrentDIV, true, sParentDIV);
	sCurrentDIV = sParentDIV;
}

	//#### Hides sCurrentDIV
function HideCurrentDIV() {
		//#### If we are allowed to hide the menu
	if (bCloseDIV) {
		HideDIV(sCurrentDIV, false);
		sCurrentDIV = '';
	}
}

	//#### Shows the passed sDIVName
function ShowDIV(oCaller, sDIVName, iFlag, iX, iY) {
	var iWidth, iZIndex;
	var oDIV = GetByID(sDIVName);

		//#### Blur focus to get rid of the focus box
	if (! oBrowser.isMozilla)				{ oCaller.blur(); }

		//#### In order for the menu items to work correctly under IE, set the width of oDIV if there is one
	if (oBrowser.isIE && oDIV.firstChild.offsetWidth)	{ oDIV.firstChild.style.width = oDIV.firstChild.offsetWidth; }
		//#### Else if this is Opera, setup oCaller.offsetHeight as it does not directly support it
	else if (oBrowser.isOpera)				{ oCaller.offsetHeight = oCaller.style.pixelHeight; }

		//#### If this is a child DIV request set oDIV.sParentDIV and iZIndex, else see if this is a new request
	if (iFlag == cCHILD) {
		oDIV.sParentDIV = sCurrentDIV;
		if (oBrowser.isMozilla)					{ iZIndex = GetByID(sCurrentDIV).zIndex + 1; }
		else									{ iZIndex = GetByID(sCurrentDIV).style.zIndex + 1; }
	}
	else if (sCurrentDIV != sDIVName) {
			//#### Hide sCurrentDIV and set oDIV.sParentDIV to null, as it has no parent DIV because it's not a child request
		HideDIV(sCurrentDIV, false);
		oDIV.sParentDIV = null;
		iZIndex = iZTop + 1;
	}

		//#### Setup the iX/iY coords for oDIV if they were not passed in
	if (! iX || iX < 0) {
		iX = TrueX(oCaller);

			//#### Set the value of iWidth
		if (oBrowser.isIE || oBrowser.isGecko)	{ iWidth = oDIV.offsetWidth; }
		else if (oBrowser.isOpera)				{ iWidth = Number(oDIV.style.pixelWidth); }

			//#### Make sure the whole DIV is on the screen, if not right align it to the window
		if (oBrowser.isIE && (iX + iWidth) > document.body.clientWidth) {
			iX = document.body.clientWidth - iWidth;
		}
		else if (oBrowser.isMozilla) {
			iX = oCaller.x;
		}
		else if (iX + iWidth > window.innerWidth) {
			iX = window.innerWidth - iWidth;
		}
	}
//!
	if (! iY || iY < 0) {
		iY = TrueY(oCaller) + oCaller.offsetHeight;
		if (oBrowser.isIE || oBrowser.isOpera)	{ iY += 2; }
		else if (oBrowser.isMozilla)			{ iY = oCaller.y; }
	}

		//#### Show oDIV
	if (oBrowser.isMozilla) {
		with (oDIV) {
			left = iX;
			top = iY + iMozillaVOffset;
			zIndex = (isNaN(iZIndex) ? 1 : iZIndex);
			visibility = 'visible';
		}
	}
	else {
		with (oDIV.style) {
			left = iX;
			top = iY;
			zIndex = iZIndex;
			visibility = 'visible';
		}
	}
		//#### If there are values in the aHideElements array, unhide the troublesome form elements
	if (aHideElements.length > 0)				{ ShowHideElement(aHideElements, sDIVName, cHIDE); }

		//#### Set sCurrentDIV and set the passed persist value
	sCurrentDIV = sDIVName;
	oDIV.persist = (iFlag == cPERSIST);
}

	//#### Shows the passed sDIVName as a child DIV of sParentDIV
function ShowChildDIV(oCaller, sDIVName, sParentDIV, iX, iY) {
	var iWH, iParentW;
	var oDIV = GetByID(sDIVName);
	var oParentDIV = GetByID(sParentDIV);

		//#### Hide any child DIVs of sParentDIV
	HideChildDIV(sParentDIV);

		//#### Setup the iX/iY coords for oDIV if they were not passed in
	if (! iX || iX < 0) {
			//#### Set the value of iWH and in turn iX
		if (oBrowser.isIE || oBrowser.isGecko) {
			iWH = oDIV.offsetWidth;
			iParentW = oParentDIV.offsetWidth;
		}
		else if (oBrowser.isOpera) {
			iWH = Number(oDIV.style.pixelWidth);
			iParentW = Number(oParentDIV.style.pixelWidth);
		}
		iX = TrueX(oCaller) + iWH - oCaller.offsetLeft + iChildHOffset;

			//#### Make sure the whole DIV is on the screen, if not right align it to the window (- 2 * iChildHOffset to undo the + iChildHOffset above and to overlap by iChildHOffset)
		if (oBrowser.isIE && (iX + iWH) > document.body.clientWidth) {
			iX = iX - iWH - iParentW - (2 * iChildHOffset);
		}
		else if (oBrowser.isMozilla) {
			iX = oCaller.x + oParentDIV.left + iMozillaHOffset;
		}
		else if ((iX + iWH) > window.innerWidth) {
			iX = iX - iWH - iParentW - (2 * iChildHOffset);
		}

			//#### If after all of the calculations we are in the negetive, left align iX
		if (iX < 1)								{ iX = 1; }
	}
	if (! iY || iY < 0) {
		iY = TrueY(oCaller);

			//#### Set the value of iWH
		if (oBrowser.isIE || oBrowser.isGecko)	{ iWH = oDIV.offsetHeight; }
		else if (oBrowser.isOpera)				{ iWH = Number(oDIV.style.pixelHeight); }

			//#### Make sure the whole DIV is on the screen, if not align it to the bottom of the window
		if (oBrowser.isIE && (iY + iWH) > document.body.clientHeight) {
			iY = document.body.clientHeight - iWH - 1;
		}
		else if (oBrowser.isMozilla) {
			iY = oCaller.y + oParentDIV.top;
		}
		else if ((iY + iWH) > window.innerHeight) {
			iY = window.innerHeight - iWH - 1;
		}
	}

		//#### Now show the new child DIV
	ShowDIV(oCaller, sDIVName, cCHILD, iX, iY);
}

	//#### Sets the value of bCloseDIV to bValue (a stupid function that mearly saves on errors and keystrokes in the DIV's events)
function CloseDIV(bValue) {
	bCloseDIV = bValue;
}

	//#### Setup the constants and global var
var cHIDE = 0;
var cSHOW = 1;
var cDRAG = 2;
var aHideElements = '';

	//#### Setup the array of troublesome form elements (those elements that appear above DIVs)
if (oBrowser.isIE || oBrowser.isOpera)		{ aHideElements = new Array('SELECT'); }
//if (oBrowser.isIE)							{ aHideElements = new Array('SELECT'); } //, ' 'IFRAME', 'APPLET'); }
//else if (oBrowser.isOpera)					{ aHideElements = new Array('SELECT', 'TEXTAREA', 'TEXTBOX', 'CHECKBOX', 'RADIO', 'BUTTON'); }

	//#### Shows/Hides all of the element types passed in aHideList on the page that are under the sDIVName
function ShowHideElement(aHideList, sDIVName, iMode) {
	var aElements, oElement, i, j;
	var oDIV = GetByID(sDIVName);

		//#### For each of the elements in aHideList
	for (i = 0; i < aHideList.length; i++) {
			//#### Build the array of elements from the DOM
		aElements = document.getElementsByTagName(aHideList[i].toUpperCase());

			//#### If the oElement is not null and overlapping sDIVName, set the visiblity based on iMode
		if (iMode == cDRAG) {
				//#### Traverse the array, hiding all the elements under sDIVName
			for (j = 0; j < aElements.length; j++)	{
				oElement = aElements[j];
//				oElement.style.visibility = (Overlap(oElement, oDIV) ? 'hidden' : 'visible');
				if (isNaN(oElement.iOverlap))	{ oElement.iOverlap = 0; }

					//#### If the elements overlap
				if (Overlap(oElement, oDIV)) {
						//#### Determine if the element is currently visible
					if (! oElement.style.visibility || oElement.style.visibility.toLowerCase() == 'visible') {
						if (oElement.iOverlap == 0) {
							oElement.style.visibility = 'hidden';
							oElement.iOverlap = 1;
						}
					}
				}

					//#### Else they do not overlap but if the object is currently hidden
				else if (oElement.style.visibility.toLowerCase() == 'hidden') {
					if (oElement.iOverlap == 1) {
						oElement.style.visibility = 'visible';
						oElement.iOverlap = 0;
					}
				}
			}
		}
		else {
				//#### Traverse the array, hiding all the elements under sDIVName
			for (j = 0; j < aElements.length; j++)	{
				oElement = aElements[j];
//				if (Overlap(oElement, oDIV))	{ oElement.style.visibility = (iMode ? 'visible' : 'hidden'); }

					//#### If the elements overlap
				if (Overlap(oElement, oDIV)) {
						//#### Determine if the element is currently visible
					if (! oElement.style.visibility || oElement.style.visibility.toLowerCase() == 'visible') {
						if (iMode == cHIDE) {
							oElement.style.visibility = 'hidden';
							oElement.iOverlap = 1;
						}
					}
					else {
						if (iMode == cSHOW) {
							if (oElement.iOverlap == 1) {
								oElement.style.visibility = 'visible';
							}
							oElement.iOverlap--;
						}
						else {
							oElement.iOverlap++;
						}
					}
				}
			}
		}
	}
}

	//#### Returns true/false if the two passed elements overlap in the 2D plane
function Overlap(oE1, oE2) {
	var iX1, iX2, iA1, iA2, iY1, iY2, iB1, iB2;

		//#### If this is Opera, setup the properties that it does not directly support
	if (oBrowser.isOpera) {
		oE1.pixelHeight = oE1.style.pixelHeight;
		oE1.offsetWidth = oE1.style.pixelWidth;
		oE2.offsetHeight = oE2.style.pixelHeight;
		oE2.offsetWidth = oE2.style.pixelWidth;
	}

		//#### Set the Y coords
	iB1 = TrueY(oE1);
	iB2 = iB1 + oE1.offsetHeight;
	iY1 = TrueY(oE2);
	iY2 = iY1 + oE2.offsetHeight;

		//#### If the elements seem to be in the way verticially, check the horozontal
	if ((iY1 <= iB1 && iY2 > iB1) || (iY1 >= iB1 && iY1 < iB2)) {
		iA1 = TrueX(oE1);
		iA2 = iA1 + oE1.offsetWidth;
		iX1 = TrueX(oE2);
		iX2 = iX1 + oE2.offsetWidth;

			//#### If the elements overlap
		if ((iX1 <= iA1 && iX2 > iA1) || (iX1 >= iA1 && iX1 < iA2)) {
			return true;
		}
	}

		//#### If we get here they did not overlap
	return false;
}

	//#### Prevents the passed event from perculating up to its parent element(s)
function KillBubble(event) {
	if (oBrowser.isIE) {
		window.event.cancelBubble = true;
		window.event.returnValue = false;
	}
	else if (oBrowser.isGecko) {
		event.preventDefault();
	}
}
