//pre-built strings
var arrow_right='<span title="" class="arrow">&#9658;</span>';
var arrow_down='<span title="" class="arrow">&nbsp;</span>';
var strEvalMenu='';//to be executed in body.onload

var Empty='&nbsp;';
var nextLevel='<table id="nextLevels_0" cellspacing="0" cellpadding="0" border="0" style="display:none;position:absolute;z-index:999;" class="menuTable"></table>';

var expandOnMouseOver=true;//when true, expand occurs without click
if(!expandOnMouseOver)
    {//flyovers displayed only when expand is set to click
    arrow_right=arrow_right.split('title=""').join('title="Click to expand"');
    arrow_down=arrow_down.split('title=""').join('title="Click to expand"');    
    }

var mouseInside=false;//true when mouse is inside a menu;otherwise false
var tOut;//timeout

var Menus;//Array if Menu objects - in case multiple menus are present on the same page

var bodyOnClickSet=false;

    var Ht;//window height
    Ht=document.documentElement.clientHeight;//IE strict mode|FF
    if(Ht==0)Ht=document.body.clientHeight;//IE quirks mode
    //alert(Ht);

//menu object
function Menu(id,src)
{
	this.Nodes=new Array(null);
	this.id=id;//matches with table id
	this.src=src;
	this.XMLdoc;
	this.type='XMLmenu';
	this.addMenuNodes=function(){addMenuNodes(this,true);};
	return(this);
}

//menuNode object
function menuNode(id,text,val,expandable,subNodes,XML,menuId)
{
	this.id=id;
	this.text=text;
	this.val=val;
	this.expandable=expandable;
	this.subNodes=subNodes;
	this.XML=XML;
	this.menuId=menuId;
	this.addMenuNodes=function(){addMenuNodes(this,false,this.id+'_');};
	this.isRoot=null;
	return(this);
}

var oMenu;//current menu

function getMenuById(id)
{
if(Menus)
	{
	for(var i=0;i<Menus.length;i++)
		{
		if(Menus[i].id==id)
			{return(Menus[i]);}
		}
	}
return null;
}

function generateMenu(id,src)
{
//id - id of container table
//src - any valid address of xml or xml-generating source
//alert('generateMenu started');
	clearMenu(-1,id);//clear all including root table

	oMenu=null;
	if(!Menus)
		{
		oMenu=new Menu(id,src);
		Menus=new Array(oMenu)
		}
	else//set oMenu to the current one
		{
		oMenu=getMenuById(id);
		if(!oMenu)
			{
			oMenu=new Menu(id,src);
			Menus[Menus.length]=oMenu;
			}	
		}
    var obj=new oAJAX(src, '',oMenu);
    obj.makeRequest();
	//makeRequest(src,'menu',oMenu);
	if(!Get('nextLevels_0'))
		{
		var div=document.createElement("div");//just a placeholder to insert innerHTML
		document.body.appendChild(div);
		div.innerHTML=nextLevel;
		}
	if(!bodyOnClickSet)
		{
		document.body.onclick=function(){if(!mouseInside)clearMenu(0);};
		bodyOnClickSet=true;
		}
}

function insertMenuItem(Node,tbName)
{
//txt: text to display

if(!tbName){tbName='XMLmenu1'};//default
var tb=Get(tbName);//handle to the table

if(tb.docking=="top") //MS IE
	{//pass execution and exit
	insertMenuItemTop(Node,tbName);return;
	}	
else if(tb.attributes["docking"]&&tb.attributes["docking"].nodeValue=="top")//FF/Mozilla
	{//pass execution and exit
	insertMenuItemTop(Node,tbName);return;
	}	

var iRowNumber=tb.rows.length;//index of next row to insert
var tr=tb.insertRow(iRowNumber);//table row inserted
tr.id=Node.menuId+'|'+Node.id;
tr.className='menuItem';

var td=tr.insertCell(0);//cell inserted for text
td.align='left';td.noWrap=true;
var td1=tr.insertCell(1);//cell inserted for symbol
td1.align='right';
//if(isIE)
//    {
    td.className='menuItem';
    td1.className='menuItem';
//    }

var content='';//thou shalt initialize thy variables!
var symbol=Empty;

content=Empty+Node.text+Empty;
if(Node.expandable)
	{
	symbol=Empty+arrow_right+symbol;
	tr.onclick=function(){menuItemExpand(this,'left');};
	tr.expandable='1';
	}
else
	{
	tr.value=Node.val;
	tr.onclick=function(){item_onClick(this.value);};
	}
if(Node.isRoot)
    {tr.isRoot='1';}
tr.onmouseover=function(){item_onMouseOver(this);};
tr.onmouseout=function(){item_onMouseOut(this);};

td.innerHTML=content;
td1.innerHTML=symbol;
}

function insertMenuItemTop(Node,tbName)
{
//txt: text to display
//action: action to be performed on click
//top is always root level
if(!tbName){tbName='XMLmenu1'};//default
var tb=Get(tbName);//handle to the table

var tr;
if(!tb.rows[0])tr=tb.insertRow(0);//table row to get cell inserted
else tr=tb.rows[0];

var iCellNumber=0;//index of next cell to insert
if(tb.rows[0].cells)iCellNumber=tb.rows[0].cells.length

var td=tr.insertCell(iCellNumber);//cell inserted for text
td.align='left';td.noWrap=true;
td.id=Node.menuId+'|'+Node.id;
td.isRoot='1';//needed for correct highlight
td.isTop='1';//needed for correct expand on mouseOver

var content='';//thou shalt initialize thy variables!
var symbol=Empty;

content=Node.text;
if(Node.expandable)
	{
	symbol=Empty+arrow_down+symbol;
	td.onclick=function(){menuItemExpand(this,'top');};
	td.expandable='1';
	}
else
	{
	td.value=Node.val;
	td.onclick=function(){item_onClick(this.value);};
	}
td.onmouseover=function(){item_onMouseOver(this);};
td.onmouseout=function(){item_onMouseOut(this);};
td.className='menuItemRoot';

td.innerHTML=Empty+content+symbol+Empty;
}

function item_onClick(val)
{
	clearMenu(0);
	eval(val);
}
function item_onMouseOver(TR)
{
    var root=(TR.isRoot)?'Root':'';
	TR.className='menuItemSelected'+root;
    if(!TR.isRoot)
        {
        TR.cells[0].className='menuItemSelected';
        TR.cells[1].className='menuItemSelected';
        }
	if(expandOnMouseOver)
	    {
	    //clear next level menus if any;expand if expandable
	    var delimited=TR.id.split('|')[1];//part after pipe
	    //alert(delimited);//attn:breaks mouseInside functionality - use only to test mnuItem.id; comment afterwards!!!
	    var arr=delimited.split('_');
	    clearMenu(arr.length-1);//remove previously expanded branches
        if(TR.expandable)
            {
            var pos=(TR.isTop)?'top':'left';
            menuItemExpand(TR,pos);
            }
	    }
	clearTimeout(tOut);
	return true;
}
function item_onMouseOut(TR)
{
    var root=(TR.isRoot)?'Root':'';
	TR.className='menuItem'+root;
    if(!TR.isRoot)
        {
        TR.cells[0].className='menuItem';
        TR.cells[1].className='menuItem';
        }
	tOut=setTimeout('if(!mouseInside)clearMenu(0);',1000);
	//if no activity in 5 sec after mouse left the menu, it clears
	return true;
}


function clearMenu(level,id)
{//removes all rows from menu table
if(level<0)
	{
	clearTable(id);
	level=0;
	}

for(var i=level;true;i++)
	{
	tb=Get('nextLevels_'+i);
	if(tb)
		{
		clearTable(tb.id);
		tb.style.display='none';//Firefox displays empty table as a black pixel
		if(tb.ifr)//IE6 must hide dropdowns
		    {tb.ifr.style.display='none';}
		}
	else return; 
	}
}

function menuItemExpand(mnuItem, pos)
{
	var delimited=mnuItem.id.split('|')[1];//part after pipe
	//alert(delimited);//attn:breaks mouseInside functionality - use only to test mnuItem.id; comment afterwards!!!
	var arr=delimited.split('_');
	clearMenu(arr.length-1);//remove previously expanded branches
	
	var newX=GetOffset(mnuItem,'offsetLeft');
	var newY=GetOffset(mnuItem,'offsetTop');
	//TODO:Opera bug:GetOffset returns 0 for newly generated elements
				
	if(pos=='left')
		{newX+=mnuItem.clientWidth;}
	else
		{newY+=mnuItem.clientHeight;}//TODO:  what if the height too big so the menu doesn't fit?
	//alert(newX);	
	if(!isIE)newX++;//FireFox needs an extra pixel
	if(isOpera)
	    {
	    var tb=mnuItem.offsetParent;
	    if(tb.X&&tb.X>0)newX=tb.X;
	    }

	var mnu=getMenuById(mnuItem.id.split('|')[0]);//handle to the menu object
	var sn;//menu subnode
	sn=mnu.Nodes[arr[0]];	
	
	//getting to the right menu node
	for(var i=1;i<arr.length;i++)
	{
	sn=sn.subNodes[arr[i]];
	}
		
	var tb=Get('nextLevels_'+(arr.length-1));
	if(tb.parentItem==mnuItem.id)return;//already done once
	tb.className='menuTable';
	tb.style.display='block';//Firefox displays empty table as a black pixel


	for(var i=0;i<sn.subNodes.length;i++)
	{
		insertMenuItem(sn.subNodes[i],tb.id)
	}

	tb.style.left=newX+'px';
	tb.style.top=newY+'px';
	
	tb.X=newX+parseInt(tb.offsetWidth);//need for Opera
	
	tb.style.display='block';
	tb.parentItem=mnuItem.id;//setting this property to avoid multiple expands
	tb.onmouseover=function(){mouseInside=true;};
	tb.onmouseout=function(){mouseInside=false;};

	if(!Get('nextLevels_'+arr.length))
		{
		var div=document.createElement('div');
		document.body.appendChild(div);
		div.innerHTML=nextLevel.replace('nextLevels_0','nextLevels_'+arr.length);//adding table for next level
		}
    document.body.onclick=function(){if(!mouseInside)clearMenu(0);};//changing it to the new body extents

    var mnuHt=tb.clientHeight;//alert(mnuHt);//submenu height
    if((newY+mnuHt)>Ht)//submenu extends below screen limit
        {
        var dif=Ht-mnuHt;//difference bet. menu height and page height
        if(dif>=0)
            {
            tb.style.top=dif+'px';//move menu up to display it entirely within the page
            }
        else
            {
            tb.style.top='0px';//TODO:for now - replace with scrolling
            }
        }
        
    if(isIE)//hiding IE6- dropdowns
        {
        var ifr;
        if(tb.ifr)
            {ifr=tb.ifr;}
        else
            {
            ifr=document.createElement('iframe');
            document.body.appendChild(ifr);
            tb.ifr=ifr;//linking table and iframe        
            }

        //ifr.src='blank.htm';
        ifr.style.zIndex='990';
        ifr.style.position='absolute';
        ifr.style.top=tb.style.top;
        ifr.style.left=tb.style.left;
        ifr.style.height=tb.clientHeight;
        ifr.style.width=tb.clientWidth;
        ifr.style.display='block';    
        }
}


function addMenuNodes(parentObject, isRoot, suffix)
{ 
	var txt;
	var val;
	var exp;//indicates the node being expandable
	var subMenuSrc=null;//added for separate submenu source
	var sub;
	var XMLnode;//xml node for this Node element
	var XML;//xml node for subnodes, if any
	var menuId;//node needs to carry menu id

	var len;
	var Nodes;//array of node objects

	if(isRoot)
	{
		Nodes=parentObject.Nodes;
		menuId=parentObject.id;
	}//to work with current menu
	else
	{
		Nodes=parentObject.subNodes;
		menuId=parentObject.menuId;
	}

	if(isRoot)
		{len=parentObject.XMLdoc.childNodes.length;}
	else{len=parentObject.XML.length;}
	var i=0;
	for(var j=0;j<len;j++)
	    {
		if(isRoot){XMLnode=parentObject.XMLdoc.childNodes[j];}
		else{XMLnode=parentObject.XML[j];}
		if((!XMLnode.tagName)||(XMLnode.tagName!='item'))
		    {continue;}//process only 'item' nodes - necessary for Moz!
		    
		try//IE
		    {
		    txt=XMLnode.getAttribute('Text');
		    val=XMLnode.getAttribute('Value');
		    }
		catch(err)//Moz
		    {
		    txt=XMLnode.attributes['Text'].nodeValue;
		    val=XMLnode.attributes['Value'].nodeValue;
		    }    

		try//IE
		    {
		    exp=XMLnode.getAttribute('subMenu');
		    }
		catch(err)//Moz
		    {
		    if(XMLnode.attributes['subMenu'])
		        {exp=XMLnode.attributes['subMenu'].nodeValue;}
		    else exp=null;
		    }
		
		if(exp)
			{
			sub=new Array(null);
			XML=XMLnode.childNodes;
			}
		else
			{
			exp=false;
			sub=null;
			XML=null;
			}
		if(isRoot)
		    {
		    Nodes[i]=new menuNode(i,txt,val,exp,sub,XML,menuId);
		    if(exp)
		        {
		        Nodes[i].addMenuNodes(Nodes[i]);
		        }
		    insertMenuItem(Nodes[i],parentObject.id);
		    }
		else
		    {
		    parentObject.subNodes[i]=new menuNode(parentObject.id+'_'+i,txt,val,exp,sub,XML,menuId);
			
		    if(exp){parentObject.subNodes[i].addMenuNodes();}			
		    }
		i++;
	    }
}