// REQUIRE: /_js/dom/abbr.js
/*****

AUTHOR:
	Andrew Chow - drew4work@gmail.com
FUNCTION:
	- Drop down menu, as 2-level Nested <ul>-list.
 	- Only one customizable DOM-ID (for the top-level <ul>) is needed for the javascript
	  to control the list.
	- All styles & positioning are controlled by CSS.
	- Search Engine Friendly, since all links are exposed as plain HTML.

EXAMPLE:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<script type="text/javascript" src="_js/dom/abbr.js"></script>
<script type="text/javascript" src="_js/dom/event.js"></script>
<script type="text/javascript" src="_js/drop-down-menu/drop-down-menu.js"></script>
<script type="text/javascript">
var ddm = new DropDownMenu('ddm', 'site-menu'); // 'site-menu' is the id of the top level <ul>
addListener(window, "load", function() {ddm.start();});
</script>

<ul id="site-menu">
	<li><a href="">Apple</a>
		<ul><li><a href="">AAA</a></li>
			<li><a href="">BBB</a></li>
			<li><a href="">CCC</a></li>
		</ul></li>
	<li><a href="">Banana</a></li>
	<li><a href="">Cherry</a></li>
</ul>


<style>
/*
  SITE MENU
~~~~~~~~~~~~~/

ul#site-menu,
ul#site-menu li {
margin: 0px;
padding: 0px;
list-style-type: none;
}

ul#site-menu {
margin: 23px auto 1px auto;
width: 648px;
}
ul#site-menu, {
margin-top: 24px;
}
ul#site-menu li {
float: left;
width: 107px;
height: 65px;
border-right: 1px solid #F2F0E4;
}
ul#site-menu li.last {
border-right: 0px;
}

ul#site-menu li a {
display: block;
width: 100%;
height: 22px;
padding-top: 43px;
text-align: center;
background: #cccccc;
text-decoration: none;
font-weight: bold;
color: #ffffff;
}
ul#site-menu li a:hover,
ul#site-menu li a.on {
color: #333333;
}

/*
  SITE MENU > DROP DOWN MENU
~~~~~~~~~~~/

ul#site-menu li ul {
margin: 0px;
background: green;
padding: 10px 0px 5px 0px;
width: 200px;
border: 1px solid #cccccc;
display: none;
position: absolute;
}
ul#site-menu li ul li {
float: none;
height: auto;
padding: 0px;
width: 190px;
border: 0px;
}
ul#site-menu li ul li a {
padding: 2px 0px 0px 10px;
background: green;
white-space: nowrap;
text-align: left;
}
ul#site-menu li ul li a:hover {
background: #ffffff;
color: #924719;
}
</style>


</body>
</html>

*****/


function DropDownMenu(objName, topListId) {

me = this;
this.topListId;
this.topList;

/*
	this.ulHidingTimer:
	pointer of setTimeout: delay for hiding the submenu, so that it buys time
	for the mouse to move over to the submenu to keep it active.  otherwise,
	the leaving of mouse from main menu LI into submenu UL will turn off the
	submenu immediately
*/
this.ulHidingTimer;
this.ulHidingDelayTime = 1000; // delay time in millisec.  used for this.ulHidingTimer

this.init = function() {
	this.topListId = topListId;
	this.topList = ge(me.topListId);
}

this.getChildUL = function(elem) {
	var aUL = gt(elem, 'ul');
	if (aUL.length > 0) {
		return aUL[0];
	}
}
this.getAllChildUL = function() {
	return gt(me.topList, 'ul');
}

this.showULInElem = function(elem) {
	var ul = me.getChildUL(elem);
	if (ul) {
		ul.style.display = 'block';
	}
}
this.hideULInElem = function(elem) {
	var ul = me.getChildUL(elem);
	if (ul) {
		ul.style.display = 'none';
	}
}
this.hideAllChildUL = function() {
	var aUL = me.getAllChildUL();
	for (var ii=0;ii<aUL.length;ii++) {
		aUL[ii].style.display = 'none';
	}
}


this.showChildUL = function(e, display) { // boolean display: true (of null) = show, false = hide
	// hide all child UL first
	me.hideAllChildUL();
	
	/* [START] cancel event bubbling */
	if (!e) var e = window.event;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();	
	/* [END] *///	me.debug('over LI');
	var e = (window.event)?window.event:e;
	var src = (e.srcElement)?e.srcElement:e.target;
	if (display == null) {
		var display = true;
	}
	// get the source element's parents until <li> is found
	var fuse = 100;
	var counter = 0;
	while (src.tagName != 'LI' && counter < fuse) {
		src = src.parentNode;
		counter++;
	}
	if (src.tagName == 'LI') {
		if (display) {
			me.showULInElem(src);
		} else {
			me.hideULInElem(src);
		}
	}
}
this.hideChildUL = function(e) {
	/* [START] cancel event bubbling */
	if (!e) var e = window.event;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();	
	/* [END] *///	me.debug('out LI');
	me.showChildUL(e, false);
}

this.showThisUL = function(e, display, delay) {
		// boolean display: true (of null) = show, false = hide
		// int delay: milli seconds to delay the action, if given
	/* [START] cancel event bubbling */
	if (!e) var e = window.event;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();	
	/* [END] *///	me.debug('over UL');
	var e = (window.event)?window.event:e;
	var src = (e.srcElement)?e.srcElement:e.target;
	if (display == null) {
		var display = true;
	}
	// get the source element's parents until <UL> is found
	var fuse = 100;
	var counter = 0;
	while (src.tagName != 'UL' && counter < fuse) {
		src = src.parentNode;
		counter++;
	}
	if (src.tagName == 'UL') {
		// if to delay
		if (delay) {
			// get elem id
			var srcId = src.id;
			if (srcId=='') {
				var oDate = new Date();
				srcId = 'tempid-' + oDate.getTime();
				src.id = srcId;
			}
			// delay the action!
			var displayString = (display)?'block':'none';
			var actionCommand = 'ge(\'' + srcId + '\').style.display = \'' + displayString + '\'';
			me.ulHidingTimer = setTimeout(actionCommand, delay);
			
		// else: just do it now
		} else {
			// clear previous timer
			clearTimeout(me.ulHidingTimer);
			// show/hide
			src.style.display = (display)?'block':'none';
		}
	}
}
this.hideThisUL = function(e) {
	/* [START] cancel event bubbling */
	if (!e) var e = window.event;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();	
	/* [END] *///	me.debug('out UL');
	// get event target
	if (!e) var e = window.event;
	var src = (e.target)?e.target:e.srcElement;
	me.showThisUL(e, false, me.ulHidingDelayTime);
}

this.debug = function(msg) {
	var box = ge('ac_message');
	if (box) { ge('ac_message').innerHTML += ' | ' + msg; }
}

this.patchOnMouseEventToTopUL = function() {
	me.topList.onmouseover = function() {/*	me.debug('over TOP'); */ }
	me.topList.onmouseout = function() {/*	me.debug('out TOP'); */ }
}
this.patchOnMouseEventToTopLI = function() {
	var aa = me.topList.childNodes;
	for (var ii=0;ii<aa.length;ii++) {
		if (aa[ii].tagName == 'LI') {
			aa[ii].onmouseover = me.showChildUL;
			aa[ii].onmouseout = me.hideChildUL;
			// get child UL
			var ul = me.getChildUL(aa[ii]);
			if (ul) {
				ul.onmouseover = me.showThisUL;
				ul.onmouseout = me.hideThisUL;
			}
		}
	}
}

this.start = function() {
	me.init();
	if (!me.topList) return;	
	me.patchOnMouseEventToTopUL();
	me.patchOnMouseEventToTopLI();
}

}

