function areSiblings(navItemA, navItemB) {
    if(navItemA==null || navItemB==null) return false; // needed because if top-level item open on load, navItemA has no context.

    if(navItemA.parentNavItem == navItemB.parentNavItem && navItemA != navItemB) {
			if(IS_DEBUG)debug('siblings: ' + navItemA.li.id + ' :: ' + navItemB.li.id);
			return true;
		} else {
    	return false;
    }
}

function cleanStack(stack) {
	if(IS_DEBUG)debug('cleaning stack.');
	
	var item = stack.pop();
	while(item != -1) {
		if(item!=null) item.mouseout("clean stack");
		item = stack.pop();
	}
}

function isSame(navItem, stackItem) {
    if(navItem==null) return false;
    else if(stackItem==null || stackItem==-1) return false;
    else if(navItem != stackItem) return false;
    else if(navItem == stackItem) return true;
    else alert("Stack isSame exception.");
}

// find parent and fire its event of the same type
function onFireParent(myEvent) { // can't call ele fireEvent in Firefox 1.5
	var e = new xEvent(myEvent);
	if(IS_DEBUG)debug("<b>firing parent for tag:</b> " + e.target.tagName);
	var li = findAncestor(e.target.parentNode,"LI");

  if(e.type=="mouseover" || e.type=="click") {
		if(IS_DEBUG)debug("direct call to parent mouseOver handler for: " + li.id);
		onNavItemOver(myEvent, li);
	} else if(e.type=="mouseout") { // workingHere:not seeing mouseOut in logger, but 2x mouseOver. Leads to prob when 2_b_1 --> 2_b in IE because they aren't touching.
		if(IS_DEBUG)debug("direct call to parent mouseOut handler.");
		onNavItemOut(myEvent, li);
	} else {
	  alert("Trying to fire parent, but encountered unsupported event type: " + e.type);
	}
}

function findAncestor(ele, tagName, loopCount) {
	if(loopCount!=null) loopCount++; // removeMe: all this loop stuff - it was for debugging.
	else loopCount=0;
	
	if(ele==null) return false;

	if(ele.tagName!=tagName) {
		if(IS_DEBUG)debug("Not find LI for child: " + tagName);
		return findAncestor(ele.parentNode, tagName, loopCount);
	} else {
		if(IS_DEBUG)debug("Found LI for child: " + tagName);
		return ele;
	}
}

function findTopLevelItem(eDescendant) {
	var nav = NAVMASTERS.getNavMaster(eDescendant);
	var item = nav.getItem(findAncestor(eDescendant,"LI"));
	return item.getTopLevelItem(item);
}

// In certain nav configurations, a user can mouseover a subitem w/o first being over its parent
// assumption is still that one can never mouseover children unless the root level item is in context
function addParentToStack(item, stack, xEvent) {
	if(!item.isToplevel && stack.getTop()!=item.parentNavItem && !areSiblings(stack.getTop(),item)) {
		onNavItemOver(xEvent, item.parentNavItem.li);
	}
}


function hasChildTag(ele,tagName) {

	if(ele==null || tagName==null) {
		return false;
	}

	var myKids = ele.childNodes;

	for(var x=0; x<myKids.length; x++) {
		var foundName = myKids[x].tagName;
		if(foundName!=null && foundName.toLowerCase()==tagName.toLowerCase()) {
			return true;
		}
	}
	return false;
}

/**
* The hybrid mode must distinquish between leaf and non-leaf
*/
function getItemSpecificEventMode(navItem) {
	if(navItem.getMasterNav().attachEventHandlersMode==EVENTMODE_OVEROUT) {
		return attachMouseOverEventHandlersItem;
	} else if(navItem.getMasterNav().attachEventHandlersMode==EVENTMODE_CLICK) {
		return attachClickEventHandlersItem;
	} else if(navItem.getMasterNav().attachEventHandlersMode==EVENTMODE_CLICK2ON_MOUSEOUT) {
		if(navItem.isToplevel) return attachHybridClickOutEventHandlersItem;
		else return attachMouseOverEventHandlersItem;
	} else { alert("Unsupported attachEventHandlerMode: " + navItem.getMasterNav().attachEventHandlersMode); }
}

/** String representation of xEvent object */
function getEventType(xEvent) {
    if(xEvent==null) return "";
    else return xEvent.type;
}

