var menus = new Array();
// CONSTANTS
// ============================================================================
// menu[] columns
var PID = 0;										// Parent ID
var TITLE = 1;										// Title
var URL = 2;										// URL
var SUB = 3;										// Submenu available
var PARSED = 4;										// Item parsed

// smenu[] columns
var VIS = 0;										// Menu visible
var LEVEL = 1;										// Menu level
var TIMER = 2;										// Menu hide timer ID
var SIZE = 3;

var VERTICAL = 0;
var HORIZONTAL = 1;

function _menu(id,orient) {
	this.MENUID = id;
	this.orient = orient;
	this.menu = new Array();								// Menu items array
	this.smenu = new Array();							// Submenus array
	this.timerId;										// Menu hide timeout timer ID
	this.overitem = -1;
	this.sm_to_hide = -1;
//templates
	this.tpl_evnt = 	'onmouseover="menus[\''+this.MENUID+'\'].mover(this,1)" onmouseout="menus[\''+this.MENUID+'\'].mout(this,1)" onclick="menus[\''+this.MENUID+'\'].mclick(this)"';
	this.tpl_width = 	' width="{WIDTH}"';
	this.tpl_height = 	' height="{HEIGHT}"';
	this.tpl_class = 	' class="{CLASS}"';
	this.tpl_smt_div = 	'<div id="smt'+this.MENUID+'_{MENU_ID}" style="position:absolute;display:none;visibility:hidden;left:{LEFT}px;top:{TOP}px">{CONTENT}</div>';
	this.tpl_smt = 		'<table cellpadding="{CP}" cellspacing="{CS}" border="{BORDER}"{PARAMETERS}>{CONTENT}</table>';
	this.tpl_smi = 		'<tr id="{MENU_ID}" {EVENTS}><td {CLASS}{HEIGHT}>{CONTENT}</td><td {CLASS} align="right">{POINTER}</td></tr>';
	
	this.timeout = 350;									// submenu hide timeout
	this.slide_dir = 'down';							// submenu slide direction: up/down
	this.devider_mid = 1;								// add devider between menu items
	this.devider_start = 0;							// add devider before all menu items
	this.devider_end = 0;								// add devider after all menu items

	this.s_mmt_cp = 0;									// cellpadding
	this.s_mmt_cs = 0;									// cellspacing
	this.s_mmt_border = 0;								// border
	this.s_mmt_class = this.MENUID+'_'+'mmt';							// class
	this.s_mmt_width = 0;								// width
	this.s_mmt_height = 0;								// height
	// Item general settings
	this.s_mmi_height = 0;								// height
	this.s_mmi_width = 0;								// width
	this.s_mmip_class = this.MENUID+'_'+'mmi_passive';					// class
	this.s_mmia_class = this.MENUID+'_'+'mmi_active';					// class
	this.s_mmd_class = this.MENUID+'_'+'mm_devide';						// class
	this.s_smt_cp = 0;									// cellpadding
	this.s_smt_cs = 0;									// cellspacing
	this.s_smt_border = 0;								// border
	this.s_smt_class = this.MENUID+'_'+'smt';							// class
	this.s_smt_width = 0;								// width
	this.s_smt_height = 0;								// height
	this.s_smi_height = 0;								// height
	this.s_smip_class = this.MENUID+'_'+'smi_passive';					// class
	this.s_smia_class = this.MENUID+'_'+'smi_active';					// class
	this.tpl_ptr = '&gt;';								// submenu pointer
	this.tpl_mmdevider = '';	// Main menu devider	
	
	this.v_tpl_mmt = '<table id="mainmenu_'+this.MENUID+'" cellpadding="{CP}" cellspacing="{CS}" border="{BORDER}"{PARAMETERS}>\n{CONTENT}</table>';
	this.v_tpl_mmi = '\t<tr><td id="{MENU_ID}"{PARAMETERS} onmouseover="menus[\''+this.MENUID+'\'].mover(this,0)" onmouseout="menus[\''+this.MENUID+'\'].mout(this,0)" onclick="menus[\''+this.MENUID+'\'].mclick(this)">{CONTENT}</td></tr>\n';
	this.v_tpl_mmd = '\t<tr><td class="'+this.s_mmd_class+'">'+this.tpl_mmdevider+'</td></tr>\n';

	this.h_tpl_mmt = '<table id="mainmenu_'+this.MENUID+'" cellpadding="{CP}" cellspacing="{CS}" border="{BORDER}"{PARAMETERS}>\n{CONTENT}</table>';
	this.h_tpl_mmi = '\t\t<td id="{MENU_ID}"{PARAMETERS} onmouseover="menus[\''+this.MENUID+'\'].mover(this,0)" onmouseout="menus[\''+this.MENUID+'\'].mout(this,0)" onclick="menus[\''+this.MENUID+'\'].mclick(this)">{CONTENT}</td>\n';
	this.h_tpl_mmd = '\t\t<td class="'+this.s_mmd_class+'">'+this.tpl_mmdevider+'</td>\n';

	menus[this.MENUID] = this;
}
_menu.prototype.menu_add = function(pid,title,link) {
	this.menu[this.menu.length] = new Array(pid,title,link,0,0);
}
_menu.prototype.set_devider = function(str) {
	this.v_tpl_mmd = '<tr><td class="'+this.s_mmd_class+'">'+str+'</td></tr>';
	this.h_tpl_mmd = '<td class="'+this.s_mmd_class+'">'+str+'</td>';
}
_menu.prototype.build_menu = function() {
	// Find not terminal nodes
	var pid;
	for (var i=0; i < this.menu.length;i++)
		if (this.menu[i][PID] >= 0)
		{
			pid = this.menu[i][PID];
			this.menu[pid][SUB] = 1;
		}
	document.writeln(this.build_mmenu());
	document.writeln(this.build_smenus());
}
_menu.prototype.build_smenus = function() {
	var out='';
	this.get_mmenu_coord();
	var level = 0;
	var pid = 0;
	for (var i=0;i<this.menu.length;i++)
		if ((this.menu[i][PID] >= 0) && (this.menu[i][PARSED] < 1)) {
			pid = this.menu[i][PID];
			ppid = this.menu[pid][PID];
			if (this.smenu[ppid])
				level = this.smenu[ppid][LEVEL];
			else
				level = 0;
			out += this.build_smenu(pid,level);
		}
	return out;
}
_menu.prototype.build_smenu = function(idx,level) {
	var out='', cnt=0;
	var par='';
	for (var i=0;i < this.menu.length;i++) {
		if (this.menu[i][PID] == idx) {
			out += str_replace(this.tpl_smi,'{CONTENT}',this.menu[i][TITLE]);
			if (this.menu[i][SUB])
				out = str_replace(out,'{POINTER}',this.tpl_ptr);
			else
				out = str_replace(out,'{POINTER}','&nbsp;');
			out = str_replace(out,'{MENU_ID}',this.MENUID+"_"+i);
			out = str_replace(out,'{EVENTS}',this.tpl_evnt);
			// Build row parameters list
			if (this.s_smip_class)
				par = str_replace(this.tpl_class,'{CLASS}',this.s_smip_class);
			else
				par = '';
			out = str_replace(out,'{CLASS}',par);
			
			if (this.s_smi_height)
				par = str_replace(this.tpl_height,'{HEIGHT}',this.s_smi_height);
			else
				par = '';
			out = str_replace(out,'{HEIGHT}',par);
			cnt++;									// Increase row counter
			this.menu[i][PARSED] = 1;					// Mark node as parsed
		}
	}
	if (out != '') {
		// Build menu table parameters
		par = '';
		if (this.s_smt_width)
			par += str_replace(this.tpl_width,'{WIDTH}',this.s_smt_width);
		if (this.s_smt_class)
			par += str_replace(this.tpl_class,'{CLASS}',this.s_smt_class);

		out = str_replace (this.tpl_smt,'{CONTENT}',out);
		out = str_replace (out,'{PARAMETERS}',par);
		out = str_replace (out,'{CP}',this.s_smt_cp);
		out = str_replace (out,'{CS}',this.s_smt_cs);
		out = str_replace (out,'{BORDER}',this.s_smt_border);
		out = str_replace (this.tpl_smt_div,'{CONTENT}',out);
		out = str_replace (out,'{MENU_ID}',idx);
		out = str_replace (out,'{LEFT}',absLeft+50);
		out = str_replace (out,'{TOP}',absTop+200);
		this.smenu[idx] = new Array(0,level+1,0,cnt);
	}
	return out;
}
_menu.prototype.get_mmenu_coord = function() {
	var mm = document.getElementById('mainmenu_'+this.MENUID);
	if (mm) {
		var coord = objectXY(mm);
		absLeft = coord[0];
		absTop = coord[1];
	} else {
		absLeft = 0;
		absTop = 0;
	}
}
_menu.prototype.mover = function (obj,type) {		// Item type: 0-main,1-submenu
	var idx = obj.id.replace(this.MENUID+"_","");								// Get item index
	if (type) {	
		set_style(obj.id,this.s_smia_class);				// Highlight item
		var pid = this.menu[idx][PID];					// Get item's menu index
		this.show_parents(pid);							// Don't hide all item's parent menus
	} else {
		set_style(obj.id,this.s_mmia_class);				// Highlight item
		this.clear_timer(idx);
	}
	if (this.smenu[idx]) {								// If submenu available
		this.hide_level(this.smenu[idx][LEVEL],idx);			// hide all submenus with the same level except IDX
		this.set_visibility(idx,1);						// show submenu
	}
}
_menu.prototype.mout = function (obj,type) {
	var idx = obj.id;								// Get item index
	if (type)
		set_style(idx,this.s_smip_class);				// Unhighlight item
	else
		set_style(idx,this.s_mmip_class);
	this.hide_visibles();
}
_menu.prototype.mclick = function (obj) {
	var idx = obj.id.replace(this.MENUID+"_","");
	var url = this.menu[idx][URL];
	if (url != '')
		document.location = url;
}
set_style = function (idx,style) {
	var obj = document.getElementById(idx);
	if (obj.cells) {
		for (var i=0;i<obj.cells.length;i++)
			obj.cells[i].className = style;
	}
	obj.className = style;
}

_menu.prototype.set_visibility = function (idx,state) {

	var obj = document.getElementById('smt'+this.MENUID+"_"+idx);
	if (obj) {
		if (state) {
			var pmi = document.getElementById(this.MENUID+"_"+idx);	// get parent item object
			if (pmi) {
				var pcoord = objectXY(pmi);			// get parent's coords
				// set submenu coords
				if (this.menu[idx][PID] < 0) {	// show 1st level submenu
					obj.style.left = pcoord[0] + (this.orient ? 0 : (pmi.offsetWidth + 2)) + 'px';
					if (this.slide_dir == 'up')
						obj.style.top = pcoord[1] - (this.s_smi_height*this.smenu[idx][SIZE] + 2) + 'px';
					else
						obj.style.top = pcoord[1] + (this.orient ? pmi.offsetHeight + 2 : 0) + 'px';
				} else {	// show 2nd and more level submenu
					obj.style.left = pcoord[0] + pmi.offsetWidth + 'px';
					
					if ((obj.offsetLeft+obj.offsetWidth) > document.body.clientWidth)
						obj.style.left = pcoord[0] - obj.offsetWidth + 'px';
						
					if (this.slide_dir == 'up')
						obj.style.top = pcoord[1] + pmi.offsetHeight - (this.s_smi_height*this.smenu[idx][SIZE]) + 'px';
					else
						obj.style.top = pcoord[1] + 'px';
				}
			}
			
			obj.style.visibility = 'visible';
			obj.style.display = 'block';
			this.smenu[idx][VIS] = 1;
		} else {
			obj.style.visibility = 'hidden';
			obj.style.display = 'none';
			this.smenu[idx][VIS] = 0;
		}
	}
}
_menu.prototype.hide = function (idx) {
	if (this.smenu[idx] && (this.smenu[idx][VIS])) {
		clearTimeout(this.smenu[idx][TIMER]);
		this.smenu[idx][TIMER] = eval("setTimeout('menus[\""+this.MENUID+"\"].set_visibility("+idx+",0)',this.timeout)");
	}
}
_menu.prototype.clear_timer = function (idx) {
	if (this.smenu[idx] && this.smenu[idx][TIMER])
		clearTimeout(this.smenu[idx][TIMER]);
}
_menu.prototype.show_parents = function(idx) {
	while (idx >= 0) {
		this.clear_timer(idx);
		idx = this.menu[idx][PID];						// get submenu PID
	}
}
_menu.prototype.hide_visibles = function() {
	for (var i=0;i<this.smenu.length;i++)
		if (this.smenu[i]) this.hide(i);						// set hide timeout
}
_menu.prototype.hide_level = function (level,expt) {
	for (var i=0;i<this.smenu.length;i++)
		if (this.smenu[i] && (this.smenu[i][LEVEL] == level) && (i != expt))
			this.set_visibility(i,0);					// hide submenu
}
_menu.prototype.build_mmenu = function() {
	var out='';
	var par='';
	// Count main menu items
	var size=0, cnt=0;
	for (var i=0;i<this.menu.length;i++)
		if (this.menu[i][PID] < 0) size++;

	for (var i=0;i<this.menu.length;i++) {
		if (this.menu[i][PID] < 0) {
			// Build cell parameters list
			par = '';
			if (this.s_mmi_width)
				par += str_replace(this.tpl_width,'{WIDTH}',this.s_mmi_width);
			if (this.s_mmi_height)
				par += str_replace(this.tpl_height,'{HEIGHT}',this.s_mmi_height);
			if (this.s_mmip_class)
				par += str_replace(this.tpl_class,'{CLASS}',this.s_mmip_class);
			out += str_replace(this.orient ? this.h_tpl_mmi : this.v_tpl_mmi,'{CONTENT}',this.menu[i][TITLE]);
			out = str_replace(out,'{MENU_ID}',this.MENUID+"_"+i);
			out = str_replace(out,'{PARAMETERS}',par);
			if ((++cnt < size) && (this.devider_mid)) 
				out += (this.orient ? this.h_tpl_mmd : this.v_tpl_mmd);
			this.menu[i][PARSED] = 1;
		}
	}
	// Add start|end deviders
	if (this.devider_start) out = (this.orient ? this.h_tpl_mmd : this.v_tpl_mmd) + out;
	if (this.devider_end) out += (this.orient ? this.h_tpl_mmd : this.v_tpl_mmd);

	// Insert items into the table body
	out = str_replace(this.orient ? this.h_tpl_mmt : this.v_tpl_mmt,"{CONTENT}",out);

	// Build menu table parameters
	par = '';
	if (this.s_mmt_width)
		par += str_replace(this.tpl_width,'{WIDTH}',this.s_mmt_width);
	if (this.s_mmt_height)
		par += str_replace(this.tpl_height,'{HEIGHT}',this.s_mmt_height);
	if (this.s_mmt_class)
		par += str_replace(this.tpl_class,'{CLASS}',this.s_mmt_class);

	out = str_replace(out,'{PARAMETERS}',par);
	out = str_replace(out,'{CP}',this.s_mmt_cp);
	out = str_replace(out,'{CS}',this.s_mmt_cs);
	out = str_replace(out,'{BORDER}',this.s_mmt_border);

	return out;
}
function objectXY(obj)
{
	var x = 0, y = 0;
	do
	{
		x += obj.offsetLeft;
		y += obj.offsetTop
	}
	while (typeof(obj = obj.offsetParent) != 'undefined' && obj != null);
	return [x,y];
}

function str_replace(s1,s2,s3) {
	var i=0;
	
	if (s2 == "") s2 = " ";
	var s = "";
	while(i = s1.indexOf(s2)) {
		if (i >= 0) {
			s = s1.substr(0,i) + s3;
			s1 = s + s1.substr(i+s2.length);			
		}
		else
			break;
	}
	return s1;
}

