var cnMenu='menu';
var cnMain='main';
var cnOpen='open';
var cnClose='close';
var cnFolder='folder';
var defaultOutDelay=120;
var defaultOverDelay=120;
var defaultIterTime=10;

var switcher=[[cnClose, new RegExp(cnOpen, '')],[cnOpen, new RegExp(cnClose, '')]];
var reFolder=new RegExp(cnFolder,'');
var reMain=new RegExp(cnMain,'');

var refTimeouts;
var refIntervals;
var refRollback;
var scrollers;

function TimeoutHandler(name)
	{
	this.store=[];
	this.name=name;
	this.toDo=function(n)
		{
		this.store[n].fn(this.store[n].ele);
		delete(this.store[n]);
		}
	this.set=function(ele, fn, time)
		{
		var i=this.index++;
		while(this.store[i]) i++;
		this.store[i]={};
		this.store[i].ele=ele;
		this.store[i].fn=fn;
		this.store[i].time=setTimeout(this.name+'.toDo('+i+')',time);
		if(this.index>100) this.index=0;
		return i;
		}
	this.index=0;
	}

function TimeoutManager()
	{
	this.store=[];
	this.clear=function()
		{
		while(this.store.length>0)
			{
			var pos=this.store.pop();
			if(refTimeouts.store[pos])
				{
				clearTimeout(refTimeouts.store[pos].time);
				delete(refTimeouts.store[pos]);
				}
			}
		}
	this.set=function(index)
		{
		this.store.push(index);
		}
	}

function IntervalHandler(name)
	{
	this.store=[];
	this.name=name;
	this.set=function(ele, fn, time)
		{
		var i=0;
		while(this.store[i]) i++;
		this.store[i]={};
		this.store[i].ele=ele;
		this.store[i].fn=fn;
		if(!this.run) this.start();
		return i;
		}
	this.clear=function(index){delete(this.store[index])}
	this.goStep=function()
		{
		var i=0, noFn=true;
		for(i=0; i<this.store.length; i++)
			{
			if(this.store[i])
				{
				this.store[i].fn(this.store[i].ele);
				noFn=false;
				}
			}
		if(noFn) this.stop();
		}
	this.stop=function()
		{
		clearInterval(this.interval);
		this.run=false;
		}
	this.start=function()
		{
		this.interval=setInterval(this.name+'.goStep()', defaultIterTime);
		this.run=true;
		}				
	}

function addClass(ele, name)
	{
	var i;
	for(i=1; i<arguments.length; i++)
		ele.className=(ele.className ? ele.className+' ':'')+arguments[i];
	return ele;
	}

function resetCN(ele, index)
	{
	if(switcher[index][1].test(ele.className)) 
		ele.className=ele.className.replace(switcher[index][1], switcher[index][0]);
	}

function closeMenus(ele, thisNot)
	{
	var lis=ele.getElementsByTagName('li'), li, i;
	for (i=0; li=lis[i]; i++) if(li!=thisNot)  resetCN (li, 0);
	}

function RollbackHandler()
	{
	this.store=[];
	this.prepare=function(ele, thisNot)
		{
		var uls=ele.getElementsByTagName('ul'), i, ul;
		for (i=0; ul=uls[i]; i++) 
			if(ul.parentNode!=thisNot && ul.out) this.set(ul);
		this.check();
		}
	this.set=function(ele)
		{
		var i=0;
		while(this.store[i]) i++;
		this.store[i]=ele;
		}
	this.checkForChildOut=function(ele)
		{
		var uls=ele.getElementsByTagName('ul'), child, run=true, i;
		for(i=0; (child=uls[i]) && run; i++) if(child.out) run=false;
		return run;
		}
	this.atRollEnd=function ()
		{
		resetCN (this.parentNode, 0);
		closeMenus(this,0);
		refRollback.check();
		}
	this.check=function()
		{
		var i;
		for(i=0; i<this.store.length; i++)
			{
			if(this.store[i]) {
				if(this.checkForChildOut(this.store[i]))
					{
					this.store[i].out=false;
					this.store[i].removeAttribute('style');
					if(reMain.test(this.store[i].parentNode.className))
						{
						scroll(this.store[i], 2,'height',this.store[i].to,this.store[i].from,8,'px',0,0,this.atRollEnd);
						}
					else
						{
						scroll(this.store[i], 2,'width',this.store[i].to,this.store[i].from,15,'px',0,0,this.atRollEnd);
						}
					delete(this.store[i]);
					}
				}
			}
		}
	}

function prepareRollOut(ele)
	{		
	if(!ele.run && !ele.out)
		{
		resetCN(ele.parentNode, 1);	
		ele.out=true;
		ele.storeHeight=ele.offsetHeight;
		ele.storeWidth=ele.offsetWidth;
		if(reMain.test(ele.parentNode.className))
			{
			ele.style.height='0px';
			scroll(ele, 1,'height',0,ele.storeHeight,8,'px','overflow','visible');
			}
		else 
			{
			ele.style.width='0px';
			scroll(ele, 1,'width',0,ele.storeWidth,10,'px','overflow','visible');
			}
		}
	}

function newEle(type, content, toNode, attrs)
	{
	var ele=document.createElement(type), i;
	if(attrs) for(var i=0; i<attrs.length; i+=2) ele[attrs[i]]=attrs[i+1];
	if(content) ele.appendChild(document.createTextNode(content));
	if(toNode) toNode.appendChild(ele);
	return ele;
	}

function createNewMenu(ele, arr)
	{
	var i, newEntry, k;
	for(i=0; i<arr.length; i++)
		{
		newEntry=newEle('li', '', ele, (arr[i][2]?arr[i][2]:''));
		if(typeof arr[i][1]=='string' ) 
			newEle('a', arr[i][0], newEntry, ['href', arr[i][1]]);
		else
			{
			newEntry.className=(newEntry.className ? newEntry.className + ' ' : '') + 
				(newEntry.parentNode.className==cnMenu ? cnMain + ' ':'') + cnFolder + ' ' + cnClose;
			newEle('h2', arr[i][0], newEntry);
			newEntry=newEle('ul', '', newEntry);
			createNewMenu(newEntry, arr[i][1]);
			}
		}
	}
		
function setMenue(thisEle)
	{
	thisEle.outDelays=new TimeoutManager();
	thisEle.overDelays=new TimeoutManager();
	while(thisEle.firstChild) thisEle.removeChild(thisEle.firstChild);
	createNewMenu(thisEle, menuContent);
	thisEle.outDelay=defaultOutDelay;
	thisEle.overDelay=defaultOverDelay;
	thisEle.onmouseover=function (e)
		{
		var ele=(( e && e.target ) || ( event && event.srcElement )), rollout;
		thisEle.outDelays.clear();
		while( ele.parentNode && !/li/i.test(ele.nodeName) ) ele=ele.parentNode;				
		if(switcher[1][1].test(ele.className))
			{
			rollout=ele.getElementsByTagName('ul')[0];
			thisEle.overDelays.clear();
			refRollback.prepare(ele.parentNode, ele);
			if(!rollout.run && !rollout.out)
				{
				thisEle.overDelays.set(refTimeouts.set(rollout, function(ele){prepareRollOut(ele);}, thisEle.overDelay));
				}
			}
		}
	thisEle.onmouseout=function ()
		{
		thisEle.outDelays.set(refTimeouts.set(thisEle, function(ele){refRollback.prepare(ele, 0);}, thisEle.outDelay));
		}
	
	thisEle.onclick=function (e)
		{
		if(/a/i.test((( e && e.target ) || ( event && event.srcElement )).nodeName)) closeMenus(thisEle, 0);
		}
	}

function scroll(thisEle, start, property, from, to, iter, iterType, endProperty, valueEndProperty, fn)
	{	
	if(start)
		{	
		if(start==2) thisEle.clear=1;
		else thisEle.clear=0;
		thisEle.from=from;
		thisEle.to=to;		
		thisEle.property=property;
		thisEle.iter=iter;
		thisEle.iterType=iterType;
		if(endProperty) 
			{
			thisEle.endProperty=endProperty;
			thisEle.valueEndProperty=valueEndProperty;
			}
		else thisEle.endProperty=false;
		if(fn) thisEle.fn=fn;
		else thisEle.fn=null;
		thisEle.curr=thisEle.from;
		if(thisEle.from<thisEle.to) thisEle.how=1;
		else thisEle.how=-1;
		if(thisEle.run) return;
		thisEle.interval=refIntervals.set( thisEle, function(ele){scroll(ele)});
		thisEle.run=true;
		}
	thisEle.curr+=thisEle.how*thisEle.iter;
	if(thisEle.curr*thisEle.how<=thisEle.to*thisEle.how)
		{
		thisEle.style[thisEle.property]=thisEle.curr+thisEle.iterType;
		}
	else
		{
		thisEle.style[thisEle.property]=thisEle.to+thisEle.iterType;
		if(thisEle.endProperty) 
			thisEle.style[thisEle.endProperty]=thisEle.valueEndProperty;
		if(thisEle.fn) thisEle.fn();
		if(thisEle.clear) thisEle.removeAttribute('style');
		refIntervals.clear(thisEle.interval);
		thisEle.run=false;
		}
	}
window.onload=function (e)
	{
	if( document.getElementById && document.getElementsByTagName &&
			((e && e.target) || (event && typeof event.srcElement=='object')) )
		{
		refTimeouts=new TimeoutHandler('refTimeouts');
		refIntervals=new IntervalHandler('refIntervals');
		refRollback=new RollbackHandler();
		var uls=document.getElementsByTagName('ul'), ul, i;
		for(i=0; ul=uls[i]; i++) if(/menu/i.test(ul.className)) setMenue(ul);
		}
	}


