/**
 * JS MENU SYSTEM
 * j0zf 2007.3.8
 * (c) Copyright 2007, All rights reserved. Apogee Design, Inc.
 * apogeeinvent.com  
 *
 */

//INSTANTIATE THE MENU OBJECT
if( typeof j0menu == 'undefined' )
{
	var j0path = document.location.pathname;
	
	if( j0path[ j0path.length - 1 ] != '/' )
	{ 
		//trim the filename off the path
		var j0arr = j0path.split("/");
		j0arr.pop();
		j0path = j0arr.join("/") + "/";		 
	}
	
	var j0menu = new C_j0menu_system( j0path, "en", {} );
}

/**
 * Class j0 Menu System
 * THE MAIN MENU SYSTEM OBJECT
 *
 * x_base_url : url to location of menu definitions - include trailing slash
 * x_lang : the language code to be used
 *
 */
function C_j0menu_system( x_base_url, x_lang, x_args )
{
	//CONFIG ///////////////////////////////////////////////////////////////
	this.debug = false;
	this.max_load_attempts = 300;
	this.load_attempt_freq_ms = 200;
	this.off_timer_ms = 500;
	
	//PROPERTIES ///////////////////////////////////////////////////////////
	this.base_url = x_base_url;
	this.lang = x_lang;
	this.args = x_args;
	
	this.menus = Array();
	this.paths_2_menus = Array(); //associative array
	this.visible_stack = Array(); //stack of the paths of visible menu indicies
	this.load_timer = new C_j0menu_timer();
	this.off_timer = new C_j0menu_timer();
	this.page_shadow = {};
	
	//PUBLIC METHODS ///////////////////////////////////////////////////////
	this.on = function( x_path, x_args )
	{
		//CHECK IF THE MENU IS LOADED YET
		if( !this._is_loaded( x_path ) )
		{
			this._load_menu( this, x_path, x_args, 0 );
		}
		else
		{
			//OK THE MENU HAS BEEN LOADED SO DRAW IT!
			this.off_timer.clear();
			this.get_menu(x_path).set_args(x_args);
		
			//HIDE MENUS IN VISIBLE STACK
			var path_str = '';
			var menu_index = -1;
			while( this.visible_stack.length > 0 && this.visible_stack[ this.visible_stack.length - 1 ] != x_path )
			{
				this.get_menu( this.visible_stack.pop() ).hide();
			}
			
			//SHOW MENUS AND ADD TO VISIBLE STACK
			var path_parts = x_path.split("/");
			path_str = '';
			for( var pp_i=0; pp_i < path_parts.length; pp_i++ )
			{
				path_str += path_parts[pp_i];
				if( pp_i >= this.visible_stack.length )
				{
					this.visible_stack.push( path_str );
					this.get_menu(path_str).show();
				}
				path_str += "/";
			}
		}
	}
	
	this.off = function()
	{
		this.off_timer.set( this._off_now, this.off_timer_ms, this );
	}
	
	this.hold = function()
	{
		this.off_timer.clear();
	}
	
	this.add_menu = function( x_path, x_args, x_event_handler )
	{
		var menu_index = this.menus.length;
		this.menus[menu_index] = new C_j0menu_menu( this, x_path, x_args, x_event_handler );
		this.paths_2_menus[ x_path ] = menu_index;
	}
	
	this.add_item = function( x_path, x_args, x_event_handler )
	{
		this.get_menu(x_path).add_item( x_path, x_args, x_event_handler );
	}
	
	this.set_args = function( x_args ){ if( typeof x_args != "undefined" )for( var arg in x_args )this.args[arg] = x_args[arg]; }
	
	this.get_menu_index = function( x_path )
	{
		return ( typeof this.paths_2_menus[x_path] == "undefined" ? -1 : this.paths_2_menus[x_path] );
	}
	
	this.get_menu = function( x_path )
	{
		var menu_index = this.get_menu_index( x_path );
		return ( menu_index < 0 ? null : this.menus[menu_index] );
	}
		
	this.set_page_shadow = function( shadow_url, shadow_logo_url, logo_x, logo_y )
	{
    	if( document.body && ( document.body.scrollWidth || document.body.scrollHeight ) ) 
			{
				var pageWidth = document.body.scrollWidth;
				var pageHeight = document.body.scrollHeight;
			} 
			else if( document.body.offsetWidth ) 
			{
				var pageWidth = document.body.offsetWidth;
				var pageHeight = document.body.offsetHeight;
			} 
			
			if( typeof this.page_shadow.img == "undefined" )
			{
				this.page_shadow.img_logo = document.createElement("IMG");
	
				this.page_shadow.img_logo.style.position = "absolute";
				this.page_shadow.img_logo.style.top = logo_x + "px";
				this.page_shadow.img_logo.style.left = logo_y + "px";
				this.page_shadow.img_logo.style.zIndex = "60000";
				
				this.page_shadow.img = document.createElement("IMG");
	
				this.page_shadow.img.style.position = "absolute";
				this.page_shadow.img.style.top = "0px";
				this.page_shadow.img.style.left = "0px";
				this.page_shadow.img.style.width = ( pageWidth < 800 ? 800 : pageWidth ) + "px";
				this.page_shadow.img.style.height = ( pageHeight < 650 ? 650 : pageHeight ) + "px";
				this.page_shadow.img.style.zIndex = "60001";
				this.page_shadow.img.style.opacity = ".7";
				this.page_shadow.img.style.filter = "alpha(opacity=70)";
			
				document.getElementsByTagName('body').item(0).appendChild( this.page_shadow.img_logo );	
				document.getElementsByTagName('body').item(0).appendChild( this.page_shadow.img );
			}
			
			this.page_shadow.img_logo.src = shadow_logo_url;
			this.page_shadow.img_logo.style.display = "block";
			
			this.page_shadow.img.src = shadow_url;
			this.page_shadow.img.style.display = "block";
    	
	}
	
	this.clear_page_shadow = function()
	{
			if( typeof this.page_shadow.img != "undefined" )
			{
				this.page_shadow.img.style.display = "none";
				this.page_shadow.img_logo.style.display = "none";
			}
	}
	
	this.get_left_of = function(o) 
	{
		if( !o )return 0;
		
		// Get an object left position from the upper left viewport corner
		var o_left = o.offsetLeft; // Get left position from the parent object
		while( o.offsetParent != null ) 
		{   
			// Parse the parent hierarchy up to the document element
			var o_parent = o.offsetParent;    // Get parent object reference
			o_left += o_parent.offsetLeft; // Add parent left position
			o = o_parent;
		}
		// Return left postion
		return o_left;
	}
	
	this.get_top_of = function(o) 
	{
		if( !o )return 0;
		
		// Get an object top position from the upper left viewport corner
		var o_top = o.offsetTop; // Get top position from the parent object
		while( o.offsetParent != null ) 
		{ 
			// Parse the parent hierarchy up to the document element
			var o_parent = o.offsetParent;  // Get parent object reference
			o_top += o_parent.offsetTop; // Add parent top position
			o = o_parent;
		}
		// Return top position
		return o_top;
	}
	
	//PRIVATE METHODS //////////////////////////////////////////////////////
	this._load_menu = function( x_this, x_path, x_args, x_attempt_counter )
	{ 
		if( x_attempt_counter > x_this.max_load_attempts )
		{
			if(x_this.debug)alert("Max Load Attempts (" + x_this.max_load_attempts + ") reached for (" + x_path + ")");
			return; //give up...
		}
		
		if( !x_this._is_loaded( x_path ) )
		{
			if( x_attempt_counter < 1 )
			{
				//FIRST TIME SO START THE LOADING...
				//x_this._call_js( x_this.base_url + x_path + "." + x_this.lang + "/menu.js" );
				x_this._call_js( "menus.php?menu_system=j0menu&path=" + escape( x_path ) + "&lang=" + escape( x_this.lang ) );
			}
			
			//KEEP CHECKING TO SEE IF IT'S LOADED
			x_attempt_counter++;
			x_this.load_timer.set( x_this._load_menu, x_this.load_attempt_freq_ms, x_this, x_path, x_args, x_attempt_counter );
		}
		else
		{
			//OK IT'S FINALLY LOADED SO SWITCH THE MENU ON
			x_this.on( x_path, x_args );
		}
	}
	
	this._off_now = function( x_this )
	{
		if( typeof x_this.paths_2_menus != "undefined" )
		{
			var path_str = '';
			var menu_index = -1;
			while( x_this.visible_stack.length > 0 )
			{
				path_str = x_this.visible_stack.pop();
				menu_index = x_this.paths_2_menus[path_str];
				x_this.menus[menu_index].hide();
			}
		}
	}
	
	this._is_loaded = function( x_path )
	{
		if( typeof this.paths_2_menus[x_path] != "undefined" )return true;
		else return false;
	}
	
	this._get_basepath = function( x_path )
	{
		var arr = x_path.split("/");
		arr.pop();
		var str = arr.join("/");
		return str;
	}
	
	this._get_rootpath = function( x_path )
	{
		var arr = x_path.split("/");
		return arr[0];
	}
	
	this._call_js = function( src_url )
	{
		var head = document.getElementsByTagName('head').item(0);
		var script = document.createElement('script');
		script.src = src_url;
		script.type = 'text/javascript';
		script.language = 'javascript1.2';
		head.appendChild(script);
	}
	
}//~function C_j0menu_system()

/**
 * Class j0 Menu Menu
 * SUPPORTING OBJECT
 */
function C_j0menu_menu( x_menu_system, x_path, x_args, x_event_handler )
{
	//PROPERTIES ///////////////////////////////////////////////////////////
	this.menu_system = x_menu_system;
	this.path = x_path;
	this.event_handler = x_event_handler;
	this.args = x_args;
	this.level = x_path.split("/").length;
	
	this.items = Array(); //a container for each "menu item"
	this.events = {}; //a container for C_j0menu_handler_linkage objects
	this.hidden_elements = new Array(); //a container for objecst like (flash & selects) that get hidden
	this.e = {}; //a container object for elements
	
	//METHODS //////////////////////////////////////////////////////////////
	this.add_item = function( x_path, x_args, x_event_handler )
	{
		var item_index = this.items.length;
		this.items[item_index] = new C_j0menu_item( this, item_index, x_path, x_args, x_event_handler );
	}
	this.show = function(){ if( typeof this.events.show != "undefined") this.events.show.invoke(); }
	this.hide = function(){ if( typeof this.events.hide != "undefined") this.events.hide.invoke(); }
	this.set_args = function( x_args ){ if( typeof x_args != "undefined" )for( var arg in x_args )this.args[arg] = x_args[arg]; }
	
	this.get_x = function()
	{
		var x = 0;
		if( typeof this.args.attach_id != "undefined" )this.args.x = this.menu_system.get_left_of( document.getElementById( this.args.attach_id ) );		
		if( typeof this.args.x != "undefined" ) x = this.args.x;
		if( typeof this.args.offset_x != "undefined" ) x += this.args.offset_x;
		return x;
	}
	
	this.get_y = function()
	{
		var y = 0;
		if( typeof this.args.attach_id != "undefined" )this.args.y = this.menu_system.get_top_of( document.getElementById( this.args.attach_id ) );		
		if( typeof this.args.y != "undefined" ) y = this.args.y;
		if( typeof this.args.offset_y != "undefined" ) y += this.args.offset_y;
		return y;
	}
		 
	this.invoke_out_callback = function()
	{
		if( typeof this.args.out != "undefined" )this.args.out.call(this);
	}
	
	this.invoke_over_callback = function()
	{
		if( typeof this.args.over != "undefined" )this.args.over.call(this);
	}
	
	//CONSTRUCTOR //////////////////////////////////////////////////////////
	//setup and invoke the init event
	this.events.init = new C_j0menu_handler_linkage(this,"init");
	this.events.init.invoke();
	this.hide();
}
 
/**
 * Class j0 Menu Item
 * SUPPORTING OBJECT
 */
function C_j0menu_item( x_menu, x_item_index, x_path, x_args, x_event_handler )
{
	this.menu = x_menu;
	this.item_index = x_item_index;
	this.path = x_path;
	this.event_handler = x_event_handler;
	this.args = x_args;
	
	this.events = {}; //a container for C_j0menu_handler_linkage objects
	this.e = {}; //a container object for elements
	
	//METHODS //////////////////////////////////////////////////////////////
	this.set_args = function( x_args ){ if( typeof x_args != "undefined" )for( var arg in x_args )this.args[arg] = x_args[arg]; }
	
	this.invoke_out_callback = function()
	{
		if( typeof this.args.out != "undefined" )this.args.out.call(this);
	}
	
	this.invoke_over_callback = function()
	{
		if( typeof this.args.over != "undefined" )this.args.over.call(this);
	}
	
	//CONSTRUCTOR //////////////////////////////////////////////////////////
	//setup and invoke the init event
	this.events.init = new C_j0menu_handler_linkage(this,"init");
	this.events.init.invoke();
}

function C_j0menu_handler_linkage( x_this, x_event )
{
	this.x_this = x_this;
	this.x_event = x_event;
	this.invoke = function(){ x_this.event_handler.call(x_this,x_event); }
}
	
function C_j0menu_timer()
{
	 this.timer_ref = null;
	 
	 this.set = function( x_function, x_timeout )
	 {
		 var parent_args = arguments;
		 
		 function child_function()
		 {
			 var args = new Array();
			 for( var i=2; i < parent_args.length; i++ ){ args[i-2] = parent_args[i]; }
			 x_function.apply( this, args );
			 this.timer_ref = null;
		 }
		 
		 this.clear();
		 this.timer_ref = setTimeout( child_function, x_timeout );
		 return this.timer_ref;
	 }
	 
	 this.clear = function()
	 {
		 if( this.timer_ref != null )
		 {
			 clearTimeout( this.timer_ref );
			 this.timer_ref = null;
		 }
	 }
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

function j0menu_menu_handler( x_event )
{
	switch( x_event )
	{
		case "init":
		{
			//DEFAULT ORIENTATION TO VERTICAL
			if( typeof this.args.orientation == "undefined" )
			{
				this.args.orientation = "vertical";
			}
		
			//BUILD HTML
			this.e.table = document.createElement("TABLE");
			this.e.tbody = document.createElement("TBODY");
			
			this.e.table.appendChild( this.e.tbody );
			document.getElementsByTagName('body').item(0).appendChild( this.e.table );		
			
			//STYLES
			this.e.table.setAttribute("border","0");
			this.e.table.setAttribute("cellspacing","0");
			this.e.table.setAttribute("cellpadding","0");
			this.e.table.border = "0";
			this.e.table.cellSpacing = "0";
			this.e.table.cellPadding = "0";
			
			this.e.table.style.zIndex = '65565';
			
			this.e.table.style.position = 'absolute';
			this.e.table.style.top = this.get_x() + "px";
			this.e.table.style.left = this.get_y() + "px";
			
			if( this.args.orientation == "vertical" )this.e.table.style.width = this.args.w + "px";
								
			this.invoke_out_callback();
			
			//SETUP EVENTS
			this.events.show = new C_j0menu_handler_linkage(this,"show");
			this.events.hide = new C_j0menu_handler_linkage(this,"hide");
			this.events.mouseover = new C_j0menu_handler_linkage(this,"mouseover");
			this.events.mouseout = new C_j0menu_handler_linkage(this,"mouseout");
			
			this.e.table.onmouseover = this.events.mouseover.invoke;
			this.e.table.onmouseout = this.events.mouseout.invoke;
		}break;
		
		case "show": 
		{
			var objs = null;
			this.e.table.style.left = this.get_x() + "px";
			this.e.table.style.top = this.get_y() + "px";
			this.e.table.style.display = "block"; 
			
			//HIDE WINDOWED OBJECTS (e.g. flash / select)
			if( typeof this.args.dont_hide == "undefined" || this.args.dont_hide == false )//don't hide objects if this menu doesn't hide
			{
				if( typeof this.args.hide_objects != "undefined" && this.args.hide_objects == true )//defaults to false
				{
					//hide the flash
					objs = document.getElementsByTagName('OBJECT');
					if(objs)
					{
						for( var i=0; i<objs.length; i++ )
						{
							if( objs[i].style.visibility != "hidden" )
							{
								objs[i].style.visibility = "hidden";
								this.hidden_elements.push( objs[i] );
							}
						}
					}
				}
				
				if( typeof this.args.hide_selects == "undefined" || this.args.hide_selects == true )//defaults to true
				{
					//now hide the select boxes...
					objs = document.getElementsByTagName('SELECT');
					if(objs)
					{
						for( var i=0; i<objs.length; i++ )
						{
							if( objs[i].style.visibility != "hidden" )
							{
								objs[i].style.visibility = "hidden";
								this.hidden_elements.push( objs[i] );
							}
						}
					}
				}
				
			}//~if()
			
		}break;
		
		case "hide":
		{ 
			if( typeof this.args.dont_hide == 'undefined' || this.args.dont_hide != true )
			{ 
				this.e.table.style.display = "none";
			} 
			
			//SHOW SAVED HIDDEN WINDOWED OBJECTS (e.g. flash / select-boxes / etc )
			if( this.hidden_elements.length > 0 )
			{
				for( var i=0; i<this.hidden_elements.length; i++ )
				{
					this.hidden_elements[i].style.visibility = "visible";
				}
				this.hidden_elements = new Array(); //clear out the list
			}		
			
		}break;
		
		case "mouseover": this.menu_system.hold(); this.invoke_over_callback(); break;
		case "mouseout": this.menu_system.off(); this.invoke_out_callback(); break;
		
		default: if( this.menu_system.debug )alert( "path: " + this.path + ", x_event: " + x_event ); break;
	}
}

function j0menu_item_handler( x_event )
{
	switch( x_event )
	{
		case "init":
		{
			//BUILD HTML
			this.e.td = document.createElement("TD");
			this.e.td_arrow = document.createElement("TD");
			
			if( this.menu.args.orientation == "horizontal" )
			{
				if( typeof this.menu.e.tr == "undefined" )
				{
					this.menu.e.tr = document.createElement("TR");
					this.menu.e.tbody.appendChild( this.menu.e.tr );
				}
				
				this.menu.e.tr.appendChild( this.e.td );
				this.menu.e.tr.appendChild( this.e.td_arrow );
			}
			else
			{
				this.e.tr = document.createElement("TR");					
				this.menu.e.tbody.appendChild( this.e.tr );
				this.e.tr.appendChild( this.e.td );
				this.e.tr.appendChild( this.e.td_arrow );
			}
			
			//STYLES
			this.e.td.innerHTML = this.args.label;
			
			//width
			if( typeof this.args.w != "undefined" )
			{
				this.e.td.style.width = this.args.w + "px";
			}
			else
			{
				this.e.td.style.width = this.menu.args.w + "px";
			}
			
			//mouse cursor			
			if( typeof this.args.url != "undefined" )
			{
				this.e.td.style.cursor = "pointer";
			}
			else
			{
				this.e.td.style.cursor = "default";
			}
			
			//arrow
			if( typeof this.menu.args.arrow != "undefined" && typeof this.args.submenu != "undefined" )
			{
				this.e.td_arrow.innerHTML = "<img border='0' src='" + this.menu.menu_system.base_url + "images/" + this.menu.args.arrow + "'>";
			}
			else if( typeof this.args.submenu != "undefined" )
			{ 
				this.e.td_arrow.innerHTML = "<img border='0' src='" + this.menu.menu_system.base_url + "images/arrow_white_" + ( (typeof this.menu.args.direction != "undefined" && this.menu.args.direction == "left") ? 'left':'right' ) + ".gif'>";
			}
			else
			{
					this.e.td_arrow.innerHTML = "&nbsp;";
			}
			
			this.invoke_out_callback();
			
			//SETUP EVENTS
			this.events.click = new C_j0menu_handler_linkage(this,"click");
			this.events.mouseover = new C_j0menu_handler_linkage(this,"mouseover");
			this.events.mouseout = new C_j0menu_handler_linkage(this,"mouseout");
			this.events.submenu = new C_j0menu_handler_linkage(this,"submenu");
			
			this.e.td.onclick = this.events.click.invoke;
			this.e.td.onmouseover = this.events.mouseover.invoke;
			this.e.td.onmouseout = this.events.mouseout.invoke;
			
			this.e.td_arrow.onclick = this.events.click.invoke;
			this.e.td_arrow.onmouseover = this.events.mouseover.invoke;
			this.e.td_arrow.onmouseout = this.events.mouseout.invoke;
		}break;
		
		case "mouseover": 
		{
			this.invoke_over_callback();
			if( typeof this.args.submenu != "undefined")this.events.submenu.invoke();
		}break;
		
		case "mouseout": this.invoke_out_callback(); break;
			
		case "click": if( typeof this.args.url != "undefined" )document.location.href=this.args.url; break;
		
		case "submenu":
		{
			if( this.menu.args.orientation == "horizontal" ) 
			{
				//first find the position of the submenu
				var w = 0, i = 0, td_w = 0, td_arrow_w = 0;
				for( i=0; i < this.menu.items.length && i < this.item_index; i++ )
				{
					td_w = this.menu.items[i].e.td.style.width.replace( /[^0-9]/g, "" ) - 0;
					td_arrow_w = this.menu.items[i].e.td_arrow.style.width.replace( /[^0-9]/g, "" ) - 0;
					w += td_w + td_arrow_w;
					if( typeof this.menu.args.extra_w != "undefined" ) w += this.menu.args.extra_w; 
				}
				
				//display BELOW (horizontal menu)
				this.menu.menu_system.on(this.args.submenu, { x:( this.menu.get_x() + w + 2 ), y:( this.menu.get_y() + this.menu.args.h + 5 ) } );								
			}
			else if( typeof this.menu.args.direction != "undefined" && this.menu.args.direction == "left" )
			{
				//display to the LEFT
				this.menu.menu_system.on(this.args.submenu, { x:( this.menu.get_x() - this.menu.menu_system.get_menu(this.args.submenu).args.w - 2 ), y:( this.menu.get_y() + ( this.item_index * this.menu.args.h ) + 2 ) } );
			}
			else
			{
				//display to the RIGHT
				this.menu.menu_system.on(this.args.submenu, { x:( this.menu.get_x() + this.menu.args.w + 2 ), y:( this.menu.get_y() + ( this.item_index * this.menu.args.h ) + 2 ) } );
			}
						
		}break;
		
		default: if( this.menu_system.debug )alert( "path: " + this.path + ", x_event: " + x_event ); break;
	}
}
