var menuIdCounter=0;

// Menu Item
function MenuItem(title,url,iconClass,submenu)
{
	this.title = title;
	this.url = url;
	this.iconClass = iconClass;
	this.submenu = submenu;
};
MenuItem.prototype.title;
MenuItem.prototype.url;
MenuItem.prototype.iconClass;
MenuItem.prototype.submenu;
MenuItem.prototype.onMouseOver = function(li)
{
	li['origClass'] = li.className;
	li.className += ' hover';
	var a = li.firstChild;
	if(a)
	{
		a['origClass'] = a.className;
		a.className += ' hover';
	}
	if(this.submenu.menuEl)
	{
		// move menu item to left side if it goes over the edge of the screen
		// this is by no means correct... just works for the first one over the edge
		// problem with menuGetObjRect?
		this.submenu.menuEl.className = '';
		var rect = menuGetObjRect(this.submenu.menuEl);
		var screen = menuGetScreenSize();
		if(rect.left+rect.width+20 > screen.width)
			this.submenu.menuEl.className = 'left';
	}
	this.submenu.show();
};
MenuItem.prototype.onMouseOut = function(li)
{
	li.className = li['origClass'];
	var a = li.firstChild;
	if(a)
		a.className = a['origClass'];
	this.submenu.hide();
};

// SubMenu
function SubMenu()
{
	this.menuEl = null;
	this.menu = [];
	this.level = 0;
	this.id = menuIdCounter++;
};
SubMenu.prototype.menu;
SubMenu.prototype.menuEl;
SubMenu.prototype.level;
SubMenu.prototype.id;
SubMenu.prototype.show = function(ul)
{
	if(this.menuEl)
		menuEfx.add(this,'show');
};
SubMenu.prototype.hide = function(ul)
{
	if(this.menuEl)
		menuEfx.add(this,'hide');
};
SubMenu.prototype.createMenu = function(container,menu,level)
{
	this.menu = [];
	if(!menu || !(menu.length > 0))		// sometimes undefined.. why? is "[]" not an empty array?
		return;
	
	this.level = level;
	this.menuEl = document.createElement('UL');
	this.menuEl.style.zIndex = 500+level;
	this.menuEl.style.visibility = 'hidden';
	for(var i=0; i<menu.length; i++)
	{
		var mi = menu[i];
		var li = document.createElement('LI');
		li.onmouseover = function() { this.menuItem.onMouseOver(this); };
		li.onmouseout = function() { this.menuItem.onMouseOut(this); };
		if(mi.title.length > 0)
		{
			var a = document.createElement('A');
			a.href = mi.url;
			a.innerHTML = mi.title;
			if(mi.iconClass)
			{
				var s = document.createElement('SPAN');
				s.className = mi.iconClass;
				a.appendChild(s);
			}
			li.appendChild(a);
		}
		else
			li.className = 'separator';
		li['menuItem'] = mi;
		var subMenu = new SubMenu();
		subMenu.createMenu(li,mi.submenu,level+1);
		mi.submenu = subMenu;
		this.menu.push(mi);
		this.menuEl.appendChild(li);
	}
	if(level > 1)
	{
		var span = document.createElement('SPAN');
		span.className = 'more';
		span.innerHTML = "&raquo;";
		container.appendChild(span);
	}
	container.appendChild(this.menuEl);
};

// Menu
function Menu()
{

};
Menu.prototype.menu;
Menu.prototype.menuEl;
Menu.prototype.createMenu = function(containerid,separator,menu)
{
	this.menu = [];
	this.menuEl = document.createElement('UL');
	for(var i=0; i<menu.length; i++)
	{
		var mi = menu[i];
		var li = document.createElement('LI');
		li.className = 'level0';
		li.onmouseover = function() { this.menuItem.onMouseOver(this); };
		li.onmouseout = function() { this.menuItem.onMouseOut(this); };
		if(mi.title != '')
		{
			var a = document.createElement('A');
			a.href = mi.url;
			a.innerHTML = mi.title;
			if(mi.iconClass)
			{
				var s = document.createElement('SPAN');
				s.className = mi.iconClass;
				a.appendChild(s);
			}
			li.appendChild(a);
		}
		else
			li.className += ' separator';
		li['menuItem'] = mi;
		var subMenu = new SubMenu();
		subMenu.createMenu(li,mi.submenu,1);
		mi.submenu = subMenu;
		this.menu.push(mi);
		this.menuEl.appendChild(li);
	}

	var container = document.getElementById(containerid);
	container.appendChild(this.menuEl);

	// for the sake of IE6, of course
	var uls = this.menuEl.getElementsByTagName('ul');
	for(var i=0; i<uls.length; i++)
	{
		var ul = uls[i];
		var width = menuGetElWidth(ul);
		var child = ul.firstChild;
		while(child)
		{
			if(child.tagName == 'LI')
				child.style.width = width+'px';
			child = child.nextSibling;
		}
	}
};

// gets an objects position, width & height
// returns array(x,y,width,height)
function menuGetObjRect(el)
{
	var isOpera = (navigator.userAgent.indexOf("Opera") >= 0)? true : false;
	var isIE = (document.all && !isOpera ? true : false);
	var isSafari = navigator.userAgent.indexOf("Safari") >= 0 ? true : false;

	var rect = {'top':0,'right':0,'bottom':0,'left':0};		// x,y,w,h
	var obj = el;
	if(obj.offsetParent)
	{
		while(obj)
		{
			rect.left += obj.offsetLeft;
			obj = obj.offsetParent;
		}
		obj = el;
		while(obj)
		{
			rect.top += obj.offsetTop;
			obj = obj.offsetParent;
		}
	}
	else if(obj.x)
	{
		rect.left = obj.x;
		rect.top = obj.y;
	}
	
	if((isIE && el.style.position != 'absolute'))		// stupid IE
	{
		iebody=(document.compatMode && document.compatMode != "BackCompat")? document.documentElement : document.body;
		rect.left -= iebody.scrollLeft;
		rect.top -= iebody.scrollTop;
	}
	
	if(el.clientWidth)
		rect.width = el.clientWidth;
	else if(el.offsetWidth)
		rect.width = el.offsetWidth;

	if(el.clientHeight)
		rect.height = el.clientHeight;
	else if(el.offsetHeight)
		rect.height = el.offsetHeight;
	
	return rect;
};

// http://www.geekdaily.net/2007/07/04/javascript-cross-browser-window-size-and-centering/
function menuGetScreenSize()
{
	var w = 0;
	var h = 0;

	//IE
	if(!window.innerWidth)
	{
		//strict mode
		if(!(document.documentElement.clientWidth == 0))
		{
			w = document.documentElement.clientWidth;
			h = document.documentElement.clientHeight;
		}
		//quirks mode
		else
		{
			w = document.body.clientWidth;
			h = document.body.clientHeight;
		}
	}
	//w3c
	else
	{
		w = window.innerWidth;
		h = window.innerHeight;
	}
	return {width:w,height:h};
};


function menuGetElWidth(el)
{
	if(el.clientWidth)
		return el.clientWidth;
	else if(el.offsetWidth)
		return el.offsetWidth;
};

var menuEfx = new MenuEfx();
function MenuEfx()
{
	this.queue = [];
	this.interval = 50;
	window.setInterval('menuEfx.execute()',this.interval)
};
MenuEfx.prototype.queue;
MenuEfx.prototype.interval;
// direction = 'show' or 'hide'
MenuEfx.prototype.add = function(menu,direction)
{
	var delay = (direction=='show' ? 0 : 1000);
	var effect = {'menu':menu,'time':delay,'direction':direction};
	
	if(this.removeFromQueue(menu))
	{
		var p = (direction=='show' ? 1 : 0);
		if(menu.effectPos == p)
			return;		// only put it in the queue if the effect isn't already done
		effect.time = 0;
	}
	this.queue.push(effect);
};
MenuEfx.prototype.removeFromQueue = function(menu)
{
	for(var i=0; i<this.queue.length; i++)
	{
		var qItem = this.queue[i];
		if(qItem.menu.id == menu.id)
		{
			this.queue.splice(i,1);
			return true;
		}
	}	
	return false;
};
MenuEfx.prototype.execute = function()
{
	var level = -1;
	for(var i=this.queue.length-1; i>=0; i--)
	{
		var qItem = this.queue[i];
		
		// if another menu is already executing on this level or below, make sure this one executes too
		if(level >= 0 && level <= qItem.menu.level)
			qItem.time = 0;

		if((qItem.time - this.interval) <= 0)
		{
			qItem.time = 0;
			level = (level >= 0 ? Math.min(qItem.menu.level) : qItem.menu.level);
			if(!this.doEffect(qItem))			// returns false when the effect is finished
				this.queue.splice(i,1);
		}
		else
			qItem.time -= this.interval;
	}
};
MenuEfx.prototype.doEffect = function(qItem)
{
	var delta = qItem.direction == 'show' ? .25 : -.25;
	var menu = qItem.menu;
	if(!menu.effectPos)
		menu.effectPos = 0;
	
	menu.effectPos = Math.min(1,Math.max(0,menu.effectPos+delta));
	menu.menuEl.style.opacity = (menu.effectPos < 1 ? menu.effectPos : '');
	menu.menuEl.style.mozOpacity = (menu.effectPos < 1 ? menu.effectPos : '');
	menu.menuEl.style.filter = menu.effectPos < 1 ? 'alpha(opacity='+ Math.round(menu.effectPos*100)+')' : '';
	
	if(menu.effectPos == 0)
		menu.menuEl.style.visibility = 'hidden';
	else
		menu.menuEl.style.visibility = '';
	
	// returns false when done
	return (menu.effectPos < 1 && menu.effectPos > 0);
};