/* SWIM2.0 :: Simple website menu
****************************************************************
* DOM scripting by brothercake -- http://www.brothercake.com/
* Licensed under GPL -- http://www.gnu.org/copyleft/gpl.html
****************************************************************
* For professional menu solutions visit -- http://www.udm4.com/ 
****************************************************************
*/

//initialise the menu(s)
//you can replace this with an encapsulated onload if necessary
//http://www.brothercake.com/site/resources/onload/
//you can also take it out of this script and put it somewhere else

if (typeof(addLoadEvent) != "undefined") {
	addLoadEvent(menuLoad);
}
else {
	window.onload = menuLoad;
}

function menuLoad() {
	//create a new menu ('menu-id', 'orientation')
	verticals = new simpleMenu('menu-v', 'vertical');
	horizontals = new simpleMenu('menu-h', 'horizontal');
}

//menu object constructor
function simpleMenu(navid, orient)
{
	//if the dom is not supported, or this is opera 5 or 6, don't continue
	if(typeof document.getElementById == 'undefined' || /opera[\/ ][56]/i.test(navigator.userAgent)) { return; }
	
	//identify konqueror
	this.iskde = navigator.vendor == 'KDE';

	//identify internet explorer [but both opera and konqueror recognise the .all collection]
       	this.isie = typeof document.all != 'undefined' && typeof window.opera == 'undefined' && !this.iskde;

	//identify old safari [< 1.2]
	this.isoldsaf = navigator.vendor == 'Apple Computer, Inc.' && typeof XMLHttpRequest == 'undefined';

	//ul tree
	this.tree = document.getElementById(navid);


	// indicates which menu is currently dropped-down
	this.previous = null;

	//if it exists
	if(this.tree != null)
	{
		//get trigger elements
		this.items = this.tree.getElementsByTagName('li');
		this.itemsLen = this.items.length;

		//initialise each trigger, using do .. while because it's faster
		var i = 0; 
		do
		{
			this.init(this.items[i], this.isie, this.isoldsaf, this.iskde, navid, orient);
			// Added by bleathem to prevent the dropdown menus from disapearing
			var className = this.items[i].className;
			if (( className == 'parent') || (className == 'grandparent') || (className == 'parent hand')) {
			    this.SetDropdown(this.items[i],className);
			}
			if ((className == 'highlight') || (className == 'previous')) {
			    this.current = this.items[i].id;
			}
		}
		while (++i < this.itemsLen);
	}
}


//trigger initialiser
simpleMenu.prototype.init = function(trigger, isie, isoldsaf, iskde, navid, ishoriz)
{
	//store menu object, or null if there isn't one
	//extend it as a property of the trigger argument
	//so it's global within [and unique to] the scope of this instantiation
	//which is the same trick as going "var self = this"
	trigger.menu = trigger.getElementsByTagName('ul').length > 0 ? trigger.getElementsByTagName('ul')[0] : null;

	//store link object
	trigger.link = trigger.getElementsByTagName('a')[0];

	trigger.parent = trigger.parentNode.parentNode;
	
	//store whther this is a submenu or child menu
	//a submenu's parent node will have the navbar id
	trigger.issub = trigger.parentNode.id == navid;
	
	//whether this is a horizontal navbar
	trigger.ishoriz = ishoriz == 'horizontal';
	

	//contains method by jkd -- http://www.jasonkarldavis.com/
	//not necessary for ie because we're re-creating in ie-proprietary method
	//and it would throw errors in mac/ie5 anyway
	//not actually necessary for opera 7 either, because it's already implemented

	this.SetMouseovers(trigger);

	//but it won't do any harm, so spoofing doesn't matter
	if(!isie)
	{
		trigger.contains = function(node)
		{
			if (node == null) { return false; }
			if (node == this) { return true; }
			else { return this.contains(node.parentNode); }
		};
	}
}

simpleMenu.prototype.SetMouseovers = function(trigger) {
	//identify konqueror
        iskde = navigator.vendor == 'KDE';

	//identify internet explorer [but both opera and konqueror recognise the .all collection]
	isie = typeof document.all != 'undefined' && typeof window.opera == 'undefined' && !this.iskde;

	//identify ie7 
	isie7 = typeof document.body.style.maxHeight != "undefined" && isie;

	//menu opening events
	//onfocus doesn't bubble in ie, but its proprietary 'onactivate' event does
	//which works in win/ie5.5+
	this.openers = { 'm' : 'onmouseover', 'k' : (isie ? 'onactivate' : 'onfocus') };
	//bind menu openers
	for(var i in this.openers)
	{
		trigger[this.openers[i]] = function(e)
		{
			//set rollover persistence classname -- we have to check for an existing value first
			//because some opera builds don't allow the class attribute to have a leading space
			//don't do persistent rollovers for konqueror, because they stick in kde <= 3.0.4
			if(!iskde) { trigger.link.className += (trigger.link.className == '' ? '' : ' ') + 'rollover'; }

			//if trigger has a menu
			if(trigger.menu != null)
			{
				//show the menu by positioning it back on the screen
				//we can use the same positions as in pure CSS for most browsers ['css']
				//but we have to compute the positions for ie ['compute'] 
				//because it uses position:relative on <a> 
				//whereas the others have position:relative on <li>
				//we also need to use those values for old safari builds ['compute']
				//because the regular positioning doesn't work 
				
				//if this is a horizontal navbar
				//set the left position to auto [css] or compute a position [compute]
				if(trigger.ishoriz) { trigger.menu.style.left = (isie || isoldsaf) ? trigger.offsetLeft + 'px' : 'auto'; }
				
				//if this is a horizontal navbar and a first-level submenu 
				//set the top position to auto [css] or compute a position [compute]
				//otherwise set it to 0 [css] or compute a position [compute]
				//trigger.menu.style.top = (trigger.ishoriz && trigger.issub) ? (isie || (trigger.ishoriz && isoldsaf)) ? trigger.link.offsetHeight + 'px' : 'auto' : (isie || (trigger.ishoriz && isoldsaf)) ? trigger.offsetTop + 'px' : '0';
				trigger.menu.style.top = (trigger.ishoriz && trigger.issub) ? (isie || (trigger.ishoriz && isoldsaf)) ? trigger.link.offsetHeight + 'px' : 'auto' : ((!isie7 && isie) || (trigger.ishoriz && isoldsaf)) ? trigger.offsetTop + 'px' : '0';
			}
		};
	}


	//menu closing events
	//'ondeactivate' is the equivalent blur handler for 'onactivate'
	this.closers = { 'm' : 'onmouseout', 'k' : (isie ? 'ondeactivate' : 'onblur') };

	//bind menu closers
	for(i in this.closers)
	{
		trigger[this.closers[i]] = function(e)
		{
			//store event-related-target property
			this.related = (!e) ? window.event.toElement : e.relatedTarget;

			//if event came from outside current trigger branch
			if(!this.contains(this.related))
			{
				//reset rollover persistence classname; not for konqueror
				if(!iskde) { trigger.link.className = trigger.link.className.replace(/[ ]?rollover/g, ''); }
				
				//if trigger has a menu
				if(trigger.menu != null)
				{
					//hide menu using left for a horizontal menu, or top for a vertical
				    trigger.menu.style[(trigger.ishoriz ? 'left' : 'top')] = trigger.ishoriz ? '-10000px' : '-5000px';
				}
			}
		};
	}
}

simpleMenu.prototype.ClearMouseovers = function(trigger) {
    //identify konqueror
    this.iskde = navigator.vendor == 'KDE';
    
    //identify internet explorer [but both opera and konqueror recognise the .all collection]
    this.isie = typeof document.all != 'undefined' && typeof window.opera == 'undefined' && !this.iskde;
    //menu opening events
    //onfocus doesn't bubble in ie, but its proprietary 'onactivate' event does
    //which works in win/ie5.5+
    this.openers = { 'm' : 'onmouseover', 'k' : (isie ? 'onactivate' : 'onfocus') };
    //menu closing events
    //'ondeactivate' is the equivalent blur handler for 'onactivate'
    this.closers = { 'm' : 'onmouseout', 'k' : (isie ? 'ondeactivate' : 'onblur') };
    for(var i in this.openers)
	{
	    trigger[this.openers[i]] = '';
	}
    for(var i in this.closers)
	{
	    trigger[this.closers[i]] = '';
	}

}

function is_ancestor(parent,child) {
    var ancestor=child;
    while (!ancestor.issub) {
	if (ancestor == parent) return true;
	ancestor=ancestor.parent;
    }
    if (ancestor == parent) return true;
    else return false;
}

// Used to expand/contract the menus without reloading the page
simpleMenu.prototype.ToggleNode = function(id) {
    var trigger = document.getElementById('m'+id); 

    if (!this.previous) this.Dropdown(trigger);
    else {
	// An menu was previously expanded
	var previous = this.previous;  // The methods below may alter this.previous, so we work with a copy of it
	this.Popup(previous);

	if (is_ancestor(trigger,previous)) {
	    if (trigger.issub) {
		this.previous = null;
	    }
	    else {
		this.Dropdown(trigger.parent);
	    }
	}
	else this.Dropdown(trigger);
    }
    return false;
}

simpleMenu.prototype.Dropdown = function(trigger) {
    this.SetDropdown(trigger,'parent');
    if (!trigger.issub) {
	var ancestor=trigger.parent;
	while (!ancestor.issub) {
	    this.SetDropdown(ancestor,'grandparent');
	    ancestor=ancestor.parent;
	}
	if (ancestor != trigger) this.SetDropdown(ancestor,'grandparent');
    }
}

simpleMenu.prototype.Popup = function(trigger) {
	// Collapse all ancestors
	var ancestor=trigger;
	while (!ancestor.issub) {
	    this.SetPopup(ancestor);
	    ancestor=ancestor.parent;
	}
	this.SetPopup(ancestor);
}

// Set a menu to be dropped-down
simpleMenu.prototype.SetDropdown = function(trigger,age) {
    if (trigger.issub) var url = '';
    else { var url = '?opid='+trigger.parent.id.substring(1); }

    if (age == 'parent' || age == 'parent hand') { 
	trigger.className='parent hand';
	trigger.menu.className = 'dropdown';
	this.previous = trigger;
    }
    else if (age == 'grandparent') { 
	trigger.className='grandparent';
	trigger.menu.className = 'predropdown';
    }
    trigger.menu.style.top='0'
    this.ClearMouseovers(trigger);
    trigger.link.setAttribute('href',url);
}

// Set a menu to pop-up
simpleMenu.prototype.SetPopup = function(trigger) {
    trigger.className='';
    trigger.menu.className='popup'; 
    this.SetMouseovers(trigger);
    var url = '?opid='+trigger.id.substring(1); 
    trigger.link.setAttribute('href',url);
    trigger.menu.style.top='-5000px';
    if (this.current) {
	current = document.getElementById(this.current);
	if (is_ancestor(trigger,current)) {
	    trigger.className='previous';
	}
    }
}
