/*

Example HTML
------------
<div id="nav">
<ul>
<li><a href="../one.html">one</a></li>
<li><a href="../two.html">two</a></li>
<ul>
<li><a href="../twoone.html">two.one</a></li>
<li><a href="../twotwo.html">two.two</a></li>
<ul>
<li><a href="../three.html">three</a></li>

Javascript DataStructure
------------------------
above will be translated to

topNav (<ul> element)
topNav.items = ...( collection of <li> elements)
item.href = "one.html"
item.href = "two.html"
item.subnav = ... (<ul> element)
nav.items = ... (collection of <li> elements)
item.href = "twoone.html"
item.href = "twotwo.html"


Element properties and methods
------------------------------
each items has the following properties and methods:

item.pos = the position of the item in it's navigation
item.parentItem = the <li>-element that belongs to the upper navlevel
item.parentNav = the <ul>-element that contains this <li>-item

nav (<ul>) items have the properties and methods:
nav.parentItem = the <li>-element associated with this subnav
nav.active = the currently active item.


Methods
-------


showNav(), hideNav():
displays or hides the navigation

navSync():
activates the level that matches the current url

findItemByHref(nav, href):
returns the item that has an url pointing to href

*/


var ITEM_TAG = "P";
var LEVEL_TAG = "UL";

var divNav;
var topNav;

var navAct;
var overAcc;

function initNav() {
	if (typeof divNav != "undefined")
		return;
	
	divNav = findId('nav');
	topNav = initNavItems(divNav);
	
	//hideNav();
	traverseNav(topNav, initItem);
	navSync();
	//dbgNav(topNav);

}

function initNavItems(nav) {
	var children, items, item, i, previousItem;
	children = nav.childNodes;
	
	items = Array();
	previousItem = false;
	for (i=0; i < children.length; ++i) {
		item = children[i]; 
		if (item.nodeName == ITEM_TAG) {
			item.pos = i;
			items[items.length] = item;
			previousItem = item;
		}
		else
		if (item.nodeName == LEVEL_TAG) {
			item.items = initNavItems(item);
			if (previousItem) {
				previousItem.subnav = item;
				item.parentItem = previousItem;
				item.active = false;
			} else {
				// top navigation
				return item;
			}
		}
	}
	return items;
}

function navSync() {
	// TODO: navSync only works, if all the links in the original
	// html code are relative and in the same directory
	// now we can just chop off the directory part and compare with a.href
	var item = findItemByHref(topNav, window.location.href);
	if (item) {
		navAct = item;
		activateItem(item, true);
	}
}

var showTimer;
function showNav() {
	if (typeof divNav == "undefined")
		initNav();
	if (showTimer)
		clearTimeout(showTimer);
	if (divNav.open)
		return;
	showTimer = setTimeout('doShow()', 100);
}

function doShow() {
	divNav.style.display = "block";
	divNav.open = true;
	navExpand();
}

function hideNav() {
	if (showTimer)
		clearTimeout(showTimer);
	if (!divNav.open)
		return;
	showTimer = setTimeout('doHide()', 100);
}

function doHide() {
	//divNav.style.display = "none";
	//divNav.open = false;
}

function navExpand() {
	slideTo(findId('i2'), 139, 500, 2);
	slideTo(findId('i3'), 274, 500, 2);
}

function navCollapse() {
	slideTo(findId('i2'), 20, 500, 2);
	slideTo(findId('i3'), 40, 500, 2);
}

function dbgNav(nav, indent) {
	traverseNav(nav, printItem);
}

function navTopOver(item, evt) {
	item.anchor.className = "active";
	return;
	
}

function navTopOut(item, evt) {
	if (item != item.parentNav.active)
		item.anchor.className = "";
	return;
}

function navSubOver(item, evt) {
	item.anchor.className = "active";
	return;
}

function navSubOut(item, evt) {
	if (item != item.parentNav.active)
		item.anchor.className = "";
	return;
		
}

function initItem(item) {
	// find the anchor (a href) for this item and delete it
	// so that we do not have to deal with event bubbling.
	item.anchor = itemAnchor(item);
	item.href = itemHref(item);
	/*
	if (item.anchor) 
		item.anchor.href = "javascript:;";
	*/
	// helper references
	item.parentNav = item.parentNode;
	item.parentItem = item.parentNav.parentItem;
	
	item.evtItemClick = evtItemClick;
	
	// init events
	evtListen(item, "click", item.evtItemClick, true);
	evtListen(item, "mouseover", evtItemOver, false);
	evtListen(item, "mouseout", evtItemOut, false);
	// may be needed so that nav doesn't hide when going out of an anchor
	//evtListen(item.anchor, "mouseout", evtItemOut, false);
}

function evtItemClick(evt) {
	var item;
	//evt = new DOM2Event(evt, window.event, this);
	
	// stop event propagation
	evtStop(evt);
	item = evtTarget(evt);
	
	// execute link if any case
	if (item.href)
			window.location.href = item.href;
	return;
	
	// activateItem
	if (item == item.parentNav.active) {
		deactivateItem(item);
		item.parentNav.active = false;
	}
	else
		activateItem(item);
	
	// prevent the event to reach the default a href handler
	evtStop(evt);
}

function activateItem(item, quick) {
	old = item.parentNav.active;
	if (item == old)
		return;
	// deactivate currently active item of this level
	if (old)
		deactivateItem(old);
	
	// change the css-class of the items anchor to "active"
	if (item.anchor)
		item.anchor.className = "active";
	
	// display the subnav, if there is one
	if (item.subnav)
		openSubNav(item.subnav, quick);
	
	// recursively activate parent
	if (item.parentItem) {
		activateItem(item.parentItem, quick);
	}
	// remeber active item in current nav level
	item.parentNav.active = item;
}

function deactivateItem(item) {
	
	// change the css-class of the items anchor back to normal
	if (item.anchor)
		item.anchor.className = "";
	if (item.subnav) {
		closeSubNav(item.subnav);
		if (item.subnav.active) {
			deactivateItem(item.subnav.active);
		}
	}
	if (item.parentNav) {
		deactivateItem(item.parentNav);
	}
}


function evtItemOver(evt) {
	var item = evtTarget(evt);
	if (item.subnav) {
		navTopOver(item, evt);
	}
	else
		navSubOver(item, evt);
}

function evtItemOut(evt) {
	var item = evtTarget(evt);
	if (item.subnav)
		navTopOut(item);
	else
		navSubOut(item);
}

function openSubNav(div, quick) {
	div.style.display = "block";
}

function closeSubNav(div) {
	div.style.display = "none";
}

function findItemByHref(nav, url) {
	var i, file;
	file = url.substring(url.lastIndexOf('/')+1);
	for (i=0; i < nav.items.length; ++i) {
		if (nav.items[i].href == file || nav.items[i].href == url)
			return nav.items[i];
		if (nav.items[i].subnav) {
			var recurse = findItemByHref(nav.items[i].subnav, url);
			if (recurse)
				return recurse;
		}
	}
	return false;
}

function printItem(item) {
	active = item.parentNav.active == item ? " *ACTIVE*": "";
}

function traverseNav(nav, func) {
	var i;
	for (i=0; i < nav.items.length; ++i) {
		func(nav.items[i]);
		if (nav.items[i].subnav)
			traverseNav(nav.items[i].subnav, func);
	}
}

function getNavItem(nav) {
	var item, i;
	item = nav;
	for (i=1; i<arguments.length; i++) {
		item = item.getItem(arguments[i]);
	}
	return item;
}

function itemAnchor(item) {
	var anchors = findTag(item, 'a');
	if (anchors && anchors.length)
		return anchors[0];
}

function itemHref(item) {
	var a = itemAnchor(item);
	if (a)
		return itemAnchor(item).getAttribute("href");
}

function itemImage(item) {
	var a = itemAnchor(item);
	if (!a) 
		return;
	img = findTag(a, 'img')[0];
	if (!img)
		return;
	return img;
}

/*
* utility functions
*/

function dbg(args) {
	var i, div, msg;
	div = findId("log");
	msg = "";
	for (i=0; i<arguments.length; ++i)
	msg += msg ? ", " + arguments[i] : arguments[i];
	div.innerHTML += msg + "<br/>";
}

function dbgObj(obj, showNull) {
	dbg("Object: "+obj);
	dbg("--------------------");
	for (k in obj)
	if (obj[k] || showNull)
		dbg(k + ": "+obj[k]);
}

function evtListen(obj, evt, func, phase) {
	if (!obj)
		return;
	if (obj.addEventListener) {
		obj.addEventListener(evt, func, phase)
	}
	else
	if (obj.attachEvent) {
		obj.attachEvent("on"+evt, func);
	}
	else
	throw new Error("can't attach event to "+obj);
}

function evtStop(evt) {
	//window.event.cancelBubble = true;
	if (evt.stopPropagation)
		evt.stopPropagation();
	if (evt.preventDefault)
		evt.preventDefault();
	evt.returnValue = false;
	evt.cancelBubble = true;
}


function evtTarget(evt) {
	// find the target navitem for this event
	// mozilla points evt.target to the anchor
	// safari points it to the text in the anchor
	var item = evt.srcElement ? evt.srcElement : evt.target;
	if (item.nodeType == 3)
		item = item.parentNode;
	if (item.nodeName == 'IMG')
		item = item.parentNode;
	if (item.nodeName == 'A')
		item = item.parentNode;
	return item;
}

function evtPreventDefault(evt) {
	evt = (evt) ? evt : ((event) ? event : null);
	if (evt) {
		evt.returnValue = false;
		if (evt.preventDefault) {
			evt.preventDefault();
		}
	}
	return false;
}



function findId(n, d) {
	var p,i,x;
	if(!d)
	d = document;
	// fuck the quirks!
	return d.getElementById(n);
	
	// ie
	if (!(x = d[n]) && d.all)
		x = d.all[n];
	// netscape4 in forms
	for (i = 0; !x && i < d.forms.length; i++)
		x = d.forms[i][n];
	// netscape4 in layers
	for(i = 0; !x && d.layers && i < d.layers.length; i++)
		x = find(n, d.layers[i].document);
	// dom
	if (!x && d.getElementById)
		x = d.getElementById(n);
	return x;
}

function findTag(elem, tagname) {
	return elem.getElementsByTagName(tagname);
}


function getStyle(elem, styleProp, jsStyleProp) {
	if (window.getComputedStyle)
		return window.getComputedStyle(elem, null)[styleProp];
	else
	if (elem.currentStyle)
		return elem.currentStyle[(jsStyleProp ? jsStyleProp : styleProp)];
	else
		return elem.style[(jsStyleProp ? jsStyleProp : styleProp)];
}

function findPosX(obj) {
	var curleft = 0;
	if (obj.offsetParent) {
		while (obj.offsetParent) {
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj) {
	var curtop = 0;
	if (obj.offsetParent) {
		while (obj.offsetParent) {
			curtop += obj.offsetTop;
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}


var _onload_func;
var _onload = Array();
function doOnLoad(f, waitFor) {
	// if the element with id waitFor is already loaded, then immediately execute f
	if (f)
	  _onload_func = f
	  
	if (waitFor) {
	  ok = document.getElementById(waitFor);
	  if (ok) 
	    _onload_func();
	  else 
	    setTimeout('doOnLoad(false, "'+waitFor+'")', 250);
	  return;
	}
	// add window.onload-function and reroute existing callbacks

	// called without a function: execute onload!
	if (typeof f != "function") {
		var i
		for (i=0; i<_onload.length; ++i)
			_onload[i]();
		return;
	}
	
	// first function added ? install this callback in window.onload
	if (window.onload && window.onload != doOnLoad) {
		_onload[_onload.length] = f;
	}
	_onload[_onload.length] = f;
	window.onload = doOnLoad;
}

function swapImg(elem, src) {
	elem.origSrc = elem.src;
	elem.src = src;
}

function restoreImg(elem) {
	elem.src = elem.origSrc;
}

window.onerror = dbg;

doOnLoad(initNav, "nav");

var isIE = document.all ? true : false;
var isDOM = document.addEventListener ? true : false;
