// Parses document for all UL's of class "menu" and converts them to be
// drop-down menus.  Currently only works for region-selection menu - should
// be updated to be more flexible.

// Currently expands submenus on mouseover on LI's.  Since the LI's & UL's
// are nested, this can cause a lot of mouseover events which this script
// knows to ignore.  This should be changed to use mouseovers on <a> links
// instead, which then change the state of their parent.

// Id of list items determines which thumbnail map to use
// Main selector item should have id of "selector".  It has to be clicked to
// display submenus.

// Time to wait until hiding if mouse leaves menu
var menu_delay = 800; // milliseconds

// Automatically prepare drop-down menus at window onload
xAddEventListener(window, "load", initMenu, false);

// Must be run on page load.  Parses menu structure identifying submenus
// and setting mouse event handlers.
function initMenu() {
//alert('menu initialized');
	var items = xGetElementsByClassName('menu');
	for (var i=0; i<items.length; i++) {
		items[i].onmouseover = function(e) { cancelHide(e, this); };
		items[i].onmouseout = function(e) { hideAll(e, this); };
		litems = xGetElementsByTagName('LI', items[i]);
		for (var j=0; j < litems.length; j++) {
			var gotsub = false;
			for (var k=0; k<litems[j].childNodes.length; k++) {
				var kid = litems[j].childNodes[k];
				if (!gotsub && kid.nodeName == 'UL') {
					gotsub = true;
					k=-1;
					kid.onmouseout = function(e) { hideMap(e, this); };
					// Create map thumbnail
					var myimg = document.createElement('img');
					myimg.className = "mapbox";
					kid.appendChild(myimg);
					kid.map = myimg;
				} else if (kid.nodeName == 'A') {
					kid.onclick = function() { return false; };
					kid.onmouseover = function() { return true; };
					kid.onmousedown = function() { return false; };
					kid.href = "selectregion:";
					var mytxt = document.createTextNode(kid.firstChild.nodeValue.replace(/^\s*/,'').replace(/\s*$/,''));
					kid.innerHTML = '';
					var myinnerblock = kid;
					if (gotsub) {
						kid.className = 'submenu';
						// Create arrow icon
						var myarrow = document.createElement('div');
						myarrow.className = "arrow";
						kid.appendChild(myarrow);
						myinnerblock = myarrow;
					}
					myinnerblock.appendChild(mytxt);
					litems[j].innerblock = myinnerblock;
				}
			}
			litems[j].onclick = function(e) { selectRegion(e, this); };
			litems[j].onmouseover = function(e) { showMap(e, this); };
			if (gotsub) {
				litems[j].onmouseover = function(e) { showMenu(e, this); showMap(e, this); };
				litems[j].onmouseout = function(e) { offMenu(e, this); };
				litems[j].className = 'folder';
			}
			if (litems[j].id == 'selector') litems[j].onmouseover = null;
		}
	}
}

function selectRegion(event, current) {
	var e = new xEvent(event);
	var a = current;
	var b = e.target;
	var ok = false;
	while (xDef(b) && b.parentNode) {
    	if (b == a) ok=true;
		if (b.tagName == 'UL') break;
		b = b.parentNode;
	}
	if (!ok) return false;
	// if this is the main selector item and it hasn't been clicked on yet,
	// then we want to pass this off to show menu
	if (current.id == 'selector' && current.className == 'folder') return( showMenu(event, current) );
	var region = current.id;
	var main = getContainerWith(current, 'UL', 'menu');
	var mainitem = xGetElementsByTagName('LI', main)[0];
	if (mainitem != current && mainitem.region != region) {
		// New Region -> Lookup region extent, and inform mapping object
		if (regions[region] && regions[region].length >= 4) {
			var extent = regions[region].slice(0,4);
			// Fit label on one line, use 5th value in regions array as alt text if it exists
			var shorttxt = current.innerblock.firstChild.nodeValue.substr(0,19);
			if (regions[region][4]) shorttxt = regions[region][4];
			//setRegion( { mainitem:mainitem, region:region, extent:extent, label:shorttxt } );
			setRegion( { mainitem:mainitem, regioncode:region, extent:extent, label:shorttxt } );
		}
	}
	hideMenu(main);
}
var tmp=0;
// Pass object with mainitem, extent, [regioncode], and [label] properties
// regioncode and label are optional
function setRegion(o) {
	if (!(o.mainitem) || !(o.extent)) return false;
	if (!(o.regioncode)) o.regioncode = o.extent.join('_');
	if (!(o.label)) o.label = "Select Region...";
	o.mainitem.region = o.regioncode;
	o.mainitem.innerblock.firstChild.nodeValue = o.label;
	setRegionExtent(o.extent);  // This is an externally overridden function
}

setRegionExtent = function(extent) {
	// Nothing here, something external can overwrite setRegionExtent to use it.
}

function showMap(event, current) {
	var e = new xEvent(event);
	e.relatedTarget = getRelated(event, 'from');
	if (!contains(current, e.relatedTarget)) {
		var list = getContainerWith(current, 'UL');
		if (xDef(list.map) && current.id != '') {
			list.map.src = 'images/map_thumbs/' + current.id + '.gif';
			xShow(list.map);
		}
	}
}

function showMenu(event, current) {
	var e = new xEvent(event);
	e.relatedTarget = getRelated(event, 'from');
	if (e.type == 'click' || !contains(current, e.relatedTarget)) {
		// Turn off all submenus that were paused when menu went into delayed hide
		var main = getContainerWith(current, 'UL', 'menu');
		if (main.paused == null) main.paused = new Array();
		for (var i=main.paused.length-1; i >= 0; i--) {
			var o = main.paused[i];
			if (!contains(o, current) && o != current) hideMenu(o);
			main.paused.length--;
		}
		if (current.className == 'folder') {
			hideChildren(current);
			var kid = xGetElementsByTagName('UL', current)[0];
			kid.style.left = null;
			current.className = 'folder_ON';
			if ((xPageX(kid) + xWidth(kid)) > xClientWidth()) {
				xLeft(kid, -xWidth(current)+10);
				if ((xPageX(current) - xWidth(kid)) < 0) xLeft(kid, 35);
			}	
		}
		//var myparent = getContainerWith(current, 'LI');
		//
	}
}

function hideMap(event, current) {
	var e = new xEvent(event);
	e.relatedTarget = getRelated(event);
	if (current != e.relatedTarget && !contains(current, e.relatedTarget)) {
		if (getContainerWith(e.relatedTarget, 'UL', 'menu')) {
			hideChildren(current);
		}
	}
}

function offMenu(event, current) {
	var e = new xEvent(event);
	e.relatedTarget = getRelated(event);
	if (current != e.relatedTarget && !contains(current, e.relatedTarget)) {
		if (getContainerWith(e.relatedTarget, 'UL', 'menu')) {
			// mouse moved off an active folder onto another element in the menu, so hide this menu
			hideMenu(current);
		} else {
			// mouse moved off the entire menu, whole menu will hide after delay
			// handled in hideAll()
			// save link to folder so that we can turn it off at next showMenu
			var main = getContainerWith(current, 'UL', 'menu');
			if (main.paused == null) main.paused = new Array();
			main.paused[main.paused.length] = current;
		}
	}
}

function hideMenu(m) {
	if (m.className == 'folder_ON') m.className = 'folder';
	//xHide(m.parentNode.map);
	hideChildren(m);
}

function hideChildren(m) {	
	var items = xGetElementsByClassName('folder_ON', m);
	for (var i=0; i < items.length; i++) {
		if (items[i].className == 'folder_ON') items[i].className = 'folder';
	}
	var mapitems = xGetElementsByClassName('mapbox', m);
	for (var i=0; i < mapitems.length; i++) {
		xHide(mapitems[i]);
	}
}

function hideAll(event, current) {
	var e = new xEvent(event);
	e.relatedTarget = getRelated(event);
	if (current != e.relatedTarget && !contains(current, e.relatedTarget)) {
		current.timer = setTimeout("hideChildren(xGetElementById('"+current.id+"'));", menu_delay);
	}
}

function cancelHide(event, current) {
	clearTimeout(current.timer);
}

function getRelated(evt) { // cross-browser event relatedTarget getter
	var e = evt ? evt : window.event;
	if(!e) return null;
	if(e.relatedTarget) return e.relatedTarget;
	else if(e.toElement) {
		if (e.type == "mouseout") return e.toElement;
		else if (e.type == "mouseover") return e.fromElement;
	}
	return e.target;
}

function contains(a, b) {
  // Return true if node a contains node b.
  while (xDef(b) && b.parentNode)
    if ((b = b.parentNode) == a) return true;
  return false;
}

function getContainerWith(node, tagName, className) {
	// Starting with the given node, find the nearest containing element with
	// with the specified tag name and style class.
	while (node != null) {
		if (node.tagName != null && node.tagName == tagName && (className == null || hasClassName(node, className)))
			return node;
		node = node.parentNode;
	}
	return node;
}

function hasClassName(el, name) {
	var list = el.className.split(" ");
	for (var i = 0; i < list.length; i++) {
		if (list[i] == name) return true;
	}
	return false;
}
