// Title: Tigra Menu
// Description: Free JavaScript Menu Navigation
// URL: http://www.javascript-menu.com/
// Version: 2.1 (commented source)
// Date: 06/26/2007
// Tech. Support: http://www.softcomplex.com/forum/forumdisplay_29/
// Notes: This script is free. Visit official site for further details.

// --------------------------------------------------------------------------------
// global collection containing all menus on current page
var A_MENUS = [];

// --------------------------------------------------------------------------------
// menu class
function menu (a_items, a_tpl, target) {

	// browser check
	if (!document.body || !document.body.style)
		return;
	// store items structure
	this.a_config = a_items;

	// store template structure
	this.a_tpl = a_tpl;

	// get menu id
	this.n_id = A_MENUS.length;

	// declare collections
	this.a_index = [];
	this.a_children = [];
	this.resize=function(show){
		var tx=getAbsX(target);
		var ty=getAbsY(target);
		var tw=target.clientWidth;
		this.top=ty;
		this.left=a_tpl[0].block_left=tx  + (tw / 2) - ((a_items.length * a_tpl[0].width)/2);
		if(show){
			for(var i=0;i<this.a_children.length;i++){
				this.a_children[i].show(this);
			}
		}
	};

	// assigh methods and event handlers
	this.expand      = menu_expand;
	this.collapse    = menu_collapse;

	this.onclick     = menu_onclick;
	this.onmouseout  = menu_onmouseout;
	this.onmouseover = menu_onmouseover;
	this.onmousedown = menu_onmousedown;

	// default level scope description structure 
	this.a_tpl_def = {
		'block_top'  : 16,
		'block_left' : 16,
		'top'        : 20,
		'left'       : 4,
		'width'      : 120,
		'height'     : 22,
		'hide_delay' : 0,
		'expd_delay' : 0,
		'css'        : {
			'inner' : '',
			'outer' : ''
		}
	};
	
	// assign methods and properties required to imulate parent item
	this.getprop = function (s_key) {
		return this.a_tpl_def[s_key];
	};

	this.o_root = this;
	this.n_depth = -1;
	this.n_x = 0;
	this.n_y = 0;

	// 	init items recursively
	for (var n_order = 0; n_order < a_items.length; n_order++){
		var mi=new menu_item(this,this, n_order, target);
		this.a_children.push(mi);
	}
	
	// register self in global collection
	A_MENUS[this.n_id] = this;

	// make root level visible
	this.holder=function(){
		return this.a_children[0].e_oelement.parentNode;
	};

	this.show=function(){
		for (var n_order = 0; n_order < this.a_children.length; n_order++){
			if(this.a_children[n_order].show)
			this.a_children[n_order].show(this);//.e_oelement.style.visibility = 'visible';
		}
	};
	this.hide=function(){
		for (var n_order = 0; n_order < this.a_children.length; n_order++)
			this.a_children[n_order].hide();//.e_oelement.style.visibility = 'visible';
	}
}

// --------------------------------------------------------------------------------
function menu_collapse (n_id) {
	// cancel item open delay
	clearTimeout(this.o_showtimer);

	// by default collapse to root level
	var n_tolevel = (n_id ? this.a_index[n_id].n_depth : 0);
	
	// hide all items over the level specified
	for (n_id = 0; n_id < this.a_index.length; n_id++) {
		var o_curritem = this.a_index[n_id];
		if (o_curritem.n_depth > n_tolevel && o_curritem.b_visible) {
			o_curritem.hide();
//			o_curritem.e_oelement.style.visibility = 'hidden';
//			o_curritem.b_visible = false;
		}
	}

	// reset current item if mouse has gone out of items
	if (!n_id)
		this.o_current = null;
}

// --------------------------------------------------------------------------------
function menu_expand (n_id) {

	// expand only when mouse is over some menu item
	if (this.o_hidetimer)
		return;

	// lookup current item
	var o_item = this.a_index[n_id];

	// close previously opened items
	if (this.o_current && this.o_current.n_depth >= o_item.n_depth)
		this.collapse(o_item.n_id);
	this.o_current = o_item;

	// exit if there are no children to open
	if (!o_item.a_children)
		return;

	// show direct child items
	for (var n_order = 0; n_order < o_item.a_children.length; n_order++) {
		var o_curritem = o_item.a_children[n_order];
		o_curritem.show(o_item);
//		o_curritem.e_oelement.style.visibility = 'visible';
//		o_curritem.b_visible = true;
	}
}

// --------------------------------------------------------------------------------
function menu_onclick (n_id) {
	var o_item = this.a_index[n_id];
	var s_link = o_item.a_config[1];
	if (!s_link)
		return true;
	if (String(s_link).toLowerCase().indexOf('javascript:') == 0)
		return eval(s_link);
	if (o_item.a_config[2] && o_item.a_config[2]['tw'])
		window.open(s_link, o_item.a_config[2]['tw']);
	else
		window.location = s_link;
	//menu_onmouseout(n_id);
	return true;
}

// --------------------------------------------------------------------------------
function menu_onmouseout (n_id) {

	// lookup new item's object	
	var o_item = this.a_index[n_id];

	// apply rollout
	o_item.setFocus(0);
	
	// update status line	
	o_item.upstatus(7);

	// run mouseover timer
	this.o_hidetimer = setTimeout('A_MENUS['+ this.n_id +'].collapse();',
		o_item.getprop('hide_delay'));
}

// --------------------------------------------------------------------------------
function menu_onmouseover (n_id) {

	// cancel mouseoute menu close and item open delay
	clearTimeout(this.o_hidetimer);
	this.o_hidetimer = null;
	clearTimeout(this.o_showtimer);

	// lookup new item's object	
	var o_item = this.a_index[n_id];

	// update status line	
	o_item.upstatus();

	// apply rollover
	o_item.setFocus(1);
	
	// if onclick open is set then no more actions required
	if (o_item.getprop('expd_delay') < 0)
		return;

	// run expand timer
	this.o_showtimer = setTimeout('A_MENUS['+ this.n_id +'].expand(' + n_id + ');',
		o_item.getprop('expd_delay'));

}

// --------------------------------------------------------------------------------
// called when mouse button is pressed on menu item
// --------------------------------------------------------------------------------
function menu_onmousedown (n_id) {
	
	// lookup new item's object	
	var o_item = this.a_index[n_id];

	// apply mouse down style
	o_item.e_oelement.className = o_item.getstyle(0, 2);
	o_item.e_ielement.className = o_item.getstyle(1, 2);

	this.expand(n_id);
}

// --------------------------------------------------------------------------------
// menu item Class
function menu_item (o_root,o_parent, n_order, target) {

	// store parameters passed to the constructor
	this.n_depth  = o_parent.n_depth + 1;
	this.a_config = o_parent.a_config[n_order + (this.n_depth ? 3 : 0)];
	this.active_item=(this.a_config[1] == document.location.pathname);
	if(this.active_item && this.n_depth>0){
		o_parent.setActive(true);
	}


	// return if required parameters are missing
	if (!this.a_config) return this;

	// store info from parent item
	this.n_order   = n_order;
	this.toString=function(){
		return "MenuItem:" + this.a_config[0];
	};

	// register in global and parent's collections
	this.n_id = o_root.a_index.length;
	o_root.a_index[this.n_id] = this;
	this.position=function(){
		return getAbsX(this.e_oelement) +',' + getAbsY(this.e_oelement) ;
	};
	this.setActive=function(on){
		if(on){
			this.active_item=true;
			this.e_ielement.className+=' active_item';
		}
	};
	this.show=function(parentNode){
		this.n_x = this.n_order ? parentNode.a_children[this.n_order - 1].n_x + this.getprop('left') : getAbsX(parentNode.e_oelement) + this.getprop('block_left');
		this.n_y = this.n_order ? parentNode.a_children[this.n_order - 1].n_y + this.getprop('top') : getAbsY(parentNode.e_oelement) + this.getprop('block_top');
		if(this.n_order==0){
			var holder=o_root.holder();
			if(this.getprop('orientation')=='horizontal'){
				var rs=(this.n_x + this.e_oelement.offsetWidth ) - (getAbsX(holder) + holder.clientWidth);
				if(rs > 0){
					this.n_x-=rs;
				}
			}
			else{
			}
		}
		this.e_oelement.style.top=this.n_y + 'px';
		this.e_oelement.style.left=this.n_x + 'px';
		this.e_oelement.style.visibility='visible';
		this.b_visible=true;
	};
	this.hide=function(){
		this.e_oelement.style.visibility='hidden';
		this.b_visible=false;
	};
	this.setFocus=function(on){
		this.e_oelement.className = this.getstyle(0, on);
		this.e_ielement.className = this.getstyle(1, on);
		if(this.active_item){
			this.e_ielement.className += ' active_item';
		}

		if(this.n_depth){
			o_parent.setFocus(on);
		}
	};

	// calculate item's coordinates
	this.a_tpl  = o_root.a_tpl;

	// assign methods
	this.getprop  = mitem_getprop;
	this.getstyle = mitem_getstyle;
	this.upstatus = mitem_upstatus;

	this.n_x=0;
	this.n_y=0;
//	this.n_x = n_order ? o_parent.a_children[n_order - 1].n_x + this.getprop('left') : o_parent.n_x + this.getprop('block_left');
//	this.n_y = n_order ? o_parent.a_children[n_order - 1].n_y + this.getprop('top') : o_parent.n_y + this.getprop('block_top');
	// generate item's HMTL
	this.e_oelement=document.createElement('DIV');
	this.e_oelement.id= 'e' + o_root.n_id + '_' + this.n_id + 'o';
	this.e_oelement.className=this.getstyle(0,0);
	if(this.a_config[2] && this.a_config[2]['tt']){
		this.e_oelement.title= this.a_config[2]['tt'];
	}
	if(this.n_depth > 0){
		this.e_oelement.style.position=get_submenustyle();//'fixed';//'absolute';
		this.e_oelement.style.top=this.n_y + 'px';
		this.e_oelement.style.left=this.n_x + 'px';
		if(this.getprop('width') != null){
			this.e_oelement.style.width=this.getprop('width') + 'px';
		}
		this.e_oelement.style.visibility = 'hidden';
	}
//	this.e_oelement.style.height=this.getprop('height') + 'px';
	this.e_oelement.style.zIndex = this.n_depth;
	this.e_oelement.style.cursor= (this.a_config[1] ? 'pointer' : 'default');
	this.e_oelement.onclick=create_onclick(o_root.n_id , this.n_id );
	this.e_oelement.onmouseout=create_onmouseout(o_root.n_id , this.n_id );
	this.e_oelement.onmouseover=create_onmouseover(o_root.n_id ,this.n_id );
	this.e_oelement.onmousedown=create_onmousedown(o_root.n_id, this.n_id );
	if(this.n_depth == 0){
//		var sp1=document.createElement('SPAN');
//		sp1.className='corners-top';
//		var sp2=document.createElement('SPAN');
//		sp1.appendChild(sp2);
//		this.e_oelement.appendChild(sp1);
	}
	if(this.n_depth == 0 && target){
		target.appendChild(this.e_oelement);
/*
		this.n_x= getAbsX(this.e_oelement);
		this.n_y= getAbsY(this.e_oelement);
*/
	}
	else{
		document.body.appendChild(this.e_oelement);
	}
	this.e_ielement = document.createElement('DIV');
	this.e_oelement.appendChild(this.e_ielement);
	this.e_ielement.id='e' + o_root.n_id + '_' + this.n_id + 'i';
	this.e_ielement.className=this.getstyle(1,0);



	//this.e_ielement.innerHTML=this.a_config[0];
	var esp=document.createElement('SPAN');

	this.e_ielement.appendChild(esp);
	if(this.a_config[1]){
		if(this.a_config[1] == document.location.pathname){
			this.e_ielement.className+=' active_item';
			this.a_config[1]=null;
		}
	}
	esp.appendChild(document.createTextNode(this.a_config[0]));
	

	this.b_visible = !this.n_depth;

	// no more initialization if leaf
	if (this.a_config.length < 4)
		return this;

	// node specific methods and properties
	this.a_children = new Array();

	// init downline recursively
	var maxw=0;
	for (var child_order = 0; child_order < this.a_config.length - 3; child_order++){
		this.a_children.push(new menu_item(o_root,this, child_order,target));
		maxw=Math.max(maxw,this.a_children[child_order].e_oelement.clientWidth);
	}
	for (var child_order=0;child_order < this.a_children.length;child_order++){
		this.a_children[child_order].e_oelement.style.width=maxw + 'px';
	}
	return this;
}
function get_submenustyle(){
	if(typeof(IE7)=='undefined'){
		return 'fixed';
	}
	if(parseFloat(IE7.appVersion) >= 7.0){
		return 'fixed';
	}
	return 'absolute';
}
function create_onclick(root_id,n_id){
	function Exec(){
		return A_MENUS[root_id].onclick(n_id);
	}
	return Exec;
}
function create_onmouseout(root_id,n_id){
	function Exec(){
		A_MENUS[root_id].onmouseout(n_id);
	}
	return Exec;
}
function create_onmouseover(root_id,n_id){
	function Exec(){
		A_MENUS[root_id].onmouseover(n_id);
	}
	return Exec;
}
function create_onmousedown(root_id,n_id){
	function Exec(){
		A_MENUS[root_id].onmousedown(n_id);
	}
	return Exec;
}


// --------------------------------------------------------------------------------
// reads property from template file, inherits from parent level if not found
// ------------------------------------------------------------------------------------------
function mitem_getprop (s_key) {

	// check if value is defined for current level
	var retval=null;
	for(var i=this.n_depth;i>=0;i--){
		try{
			retval=this.a_tpl[i][s_key];
			if(retval != null){
				return retval;
			}
		}
		catch(x){}
	}
	return retval;
}
// --------------------------------------------------------------------------------
// reads property from template file, inherits from parent level if not found
// ------------------------------------------------------------------------------------------
function mitem_getstyle (n_pos, n_state) {

	var a_css = this.getprop('css');
	var a_oclass = a_css[n_pos ? 'inner' : 'outer'];

	// same class for all states	
	if (typeof(a_oclass) == 'string')
		return a_oclass;

	// inherit class from previous state if not explicitly defined
	for (var n_currst = n_state; n_currst >= 0; n_currst--)
		if (a_oclass[n_currst])
			return a_oclass[n_currst];
}

// ------------------------------------------------------------------------------------------
// updates status bar message of the browser
// ------------------------------------------------------------------------------------------
function mitem_upstatus (b_clear) {
	window.setTimeout("window.status=unescape('" + (b_clear
		? ''
		: (this.a_config[2] && this.a_config[2]['sb']
			? escape(this.a_config[2]['sb'])
			: escape(this.a_config[0]) + (this.a_config[1]
				? ' ('+ escape(this.a_config[1]) + ')'
				: ''))) + "')", 10);
}

// --------------------------------------------------------------------------------
// that's all folks
