
// trapping things
var cm_oD = new Array();
var cm_lO = new Array();

// define constants
var CM_EXPAND_LEFT = 0;
var CM_EXPAND_DOWN = 1;
var CM_EXPAND_RIGHT = 2;
var CM_EXPAND_UP = 4;	// look, if they want right, they'll want up as well

var CM_POSITION_NONE = 0;	// don't arrange
var CM_POSITION_HORIZ = 1;	// arrange horizontally
var CM_POSITION_VERT = 2;	// arrange vertially

var CM_LATENCY = 300;		// menu latency in milliseconds

/**
 * Initialises the dropdown menus... generally called on document load.
 *
 * @param	elid	the ID of the root UL object...
 */
function menuinicioul(){
text1 = '<ul id="mainMenu">';
		document.write(text1);
}
function menufinul(){
text2 = "</ul>";
		document.write(text2);
}
function cm_init (elid)
{
 
	var el = document.getElementById(elid);
	if (null == el)
		return;		// drop out
	_cm_pU(el, false, 0);
	externalLinks();
}

/**
 * Positions and does other various stuff to a UL object.
 *
 * @param	el		the UL element to process
 * @param	hide	whether or not we want to hide the UL once we're finished
 * @param	lv		the level of the UL
 */
function _cm_pU(el, hide, lv)
{
	// make them visible
	el.style.display = "block";
	
	// array stuffery
	cm_oD[lv] = null;
	cm_lO[lv] = null;
	
	
	// firstly, which way are we building this menu?
	var or = CM_POSITION_VERT;
	if (el.className.indexOf("cm_posHoriz") != -1)
		or = CM_POSITION_HORIZ;
	else if (el.className.indexOf("cm_posNone") != -1)
		or = CM_POSITION_NONE;
	
	// which way are children dropping off it?
	var ex = CM_EXPAND_LEFT;
	if (el.className.indexOf("cm_expDown") != -1)
		ex = CM_EXPAND_DOWN;
	else if (el.className.indexOf("cm_expRight") != -1)
		ex = CM_EXPAND_RIGHT;
	else if (el.className.indexOf("cm_expUp") != -1)
		ex = CM_EXPAND_UP;
	
	// now, we toddle off through child elements because we're cool like that
	var childEl = el.firstChild;
	while (childEl != null)
	{
		if (childEl.nodeName == "LI")
			_cm_pL(childEl, or, ex, lv);		
		childEl = childEl.nextSibling;	
	}
	if (hide)
		el.style.visibility = "hidden";
}

/**
 * Processes an LI node. This does alignment and event handler stuff.
 *
 * @param	el	the LI element
 * @param	or	the orientation we're using
 * @param	ex	which way children are being expanded...
 * @param	lv	how far down the menu structure we are
 */
function _cm_pL (el, or, ex, lv)
{
	// if we have any child ULs...
	var uls = el.getElementsByTagName("ul");
	if (uls.length == 0)
		return; // no, so drop out.
	
	// yes, so add ourselves some kind of funkiness
	var theUL = uls[0];
	el.onmouseover = function () { _cm_dOO(theUL, lv, true); }
	el.onmouseout  = function () { _cm_dOO(theUL, lv, false); }
	el.className += " cm_hasSubMenu";
	
	// move the UL...
	// step one, where are we?
	var xPos = 0;
	var yPos = 0;
	var xDim = el.scrollWidth;
	var yDim = el.scrollHeight;
	
	// movage
	switch (ex)
	{
		case CM_EXPAND_LEFT:
			xPos += xDim;
			break;
		case CM_EXPAND_RIGHT:
			xPos -= (xDim);
			break;
		case CM_EXPAND_DOWN:
			yPos += yDim;
			break;
		case CM_EXPAND_UP:
			// not supported yet :)
			break;
	}
	theUL.style.left = xPos+"px";
	theUL.style.top = yPos+"px";
		
	// recurse
	_cm_pU(theUL, true, lv+1);
}

/**
 * Event-handling class - delegates to _cm_sH.
 *
 * @param	el	the UL element to show/hide
 * @param	lv	the depth of the UL element
 * @param	sh	whether to show or not
 */
function _cm_dOO (el, lv, sh)
{
	if (sh)
	{
		if (cm_lO[lv] != null)
			if (_cm_iDO(el, cm_lO[lv]))
				clearTimeout(cm_oD[lv]);
			else
				_cm_sH(false, null, lv);
		
		_cm_sH(true, el, lv);
	}
	else
	{
		cm_lO[lv] = el;
		clearTimeout(cm_oD[lv]);
		cm_oD[lv] = setTimeout("_cm_sH(false, null, "+lv+");", CM_LATENCY);
	}
}

/**
 * Actually shows and hides stuff.
 *
 * @param	show	true to show
 * @param	el		the LI element to show child UL of. If null, use cm_lO
 * @param	lv		the 'level' of the element in the menu system
 */
function _cm_sH (show, el, lv)
{
	if (el == null)
	{
		el = cm_lO[lv];
		cm_lO[lv] = null;
	}
	if (null == el)
		return;
	
	el.style.visibility = (show) ? "visible" : "hidden";
	
	if (!show && _cm_aKE(cm_oD, lv+1) && (cm_oD[lv+1] != null))
		_cm_sH (false, null, lv+1);
}

/**
 * Finds out whether one element is a descendant of another
 *
 * @param	el	the element in question
 * @param	ref	the element to reference against
 * @return	true if el and ref are the same, or el is a descendant of ref
 */
function _cm_iDO (el, ref)
{	
	var test = el;
	while (test != null)
	{
		if (test == ref)
			return true;
			
		test = test.parentNode;
	}
	
	return false;
}

/**
 * Gets the absolute x coordinate of an element on a page.
 *
 * @param	el	the element
 * @return 	the x-coordinate
 */
function _cm_getX (el)
{
	var x = 0;
	if (el.offsetParent)
	{
		while (el.offsetParent)
		{
			x += el.offsetLeft;
			el = el.offsetParent;
		}
	}
	else if (el.x)
		x += el.x;
	
	return x;
}

/**
 * Gets the absolute y coordinate of an element on a page.
 *
 * @param	el	the element
 * @return 	the y-coordinate
 */
function _cm_getY (el)
{
	var y = 0;
	if (el.offsetParent)
	{
		while (el.offsetParent)
		{
			y += el.offsetTop;
			el = el.offsetParent;
		}
	}
	else if (el.y)
		y += el.y;
	
	return y;
}

/**
 * Returns true if a specific key exists within an array.
 *
 * @param	ar	the array
 * @param	ke	the key
 * @return	true if ar[ke] exists.
 */
function _cm_aKE(ar, ke)
{
	try
	{
		var t = ar[ke];
	}
	catch (ex)
	{
		return false;
	}
	
	return (t != null);
}