/*
 ** SUPERCEDED BY system.navigation.js **
 * 
 * system.interface.menu.js 
 * version 1.0.0
 * Copyright (C) Jason Mingl, ratheous@ratheous.net
 *
 * Requires: system.tools.js
 *           system.events.js
 *
 * Optional: system.debug.js
*/

var POS_BOTTOM = 0;
var POS_RIGHT = 1;
var POS_RELATIVE = 2;
var POS_ABSOLUTE = 3;

var DEFAULT_OFFSET_X = 1;
var DEFAULT_OFFSET_Y = 1;

var DEFAULT_STYLE_ON = "";
var DEFAULT_STYLE_OFF = "";

if(typeof system != "object")
	var system = new Object;
if(typeof system.interface != "object")
	system.interface = new Object;

system.interface.menu = new Object;
system.interface.menu.menu_path = new Array;
system.interface.menu.event_queue = new Array;

system.interface.menu.timer_id = null;
system.interface.menu.timer_on = false;
system.interface.menu.timer_delay = 250;

/*
 * system.interface.menu.item constructor arguments:
 * any argument that is not required and is left undefined will use default values
 *
 *  element   : REQUIRED - id or node object of menu item. this element will trigger menu events
 *
 *  one or both of the following two  arguments must be defined
 *  parent    : system.interface.menu.item object. leave undefined for root menu items
 *  child     : id or node object of the container element for sub items. this element should be hidden initially
 *
 *  target    : id or node object of the element to recieve activate/deactivate style changes. leave undefined to default to the main element
 *  style_on  : activated state class name
 *  style_off : deactivated state class name
 *  position  : active state positioning mode for the child frame element. valid values: POS_BOTTOM, POS_RIGHT, POS_RELATIVE, POS_ABSOLUTE
 *  x         : x or left offset. behaves differently based on the above position setting. positive or negative integer
 *  y         : y or top offset. behaves differently based on the above position setting. positive or negative integer
 *
 * Example:
 *
 *  DEFAULT_POSITION = POS_BOTTOM;
 *  DEFAULT_STYLE_ON = 'ItemOn';
 *  DEFAULT_STYLE_OFF = 'ItemOff';
 *  var item1 = new menu_item({element:"item_root", child:"submenu1", x:0, y:1});
 *  new menu_item({element:'sub_item', parent:item1, target:'sub_item_target', style_on:'altItemOn', style_off:'altItemOff'});
 */

system.interface.menu.item = function(obj) 
{
	try
	{
		if (obj == undefined) return 'undefined';
    	if (obj == null) return 'null';
		this.parent = (obj.parent == undefined ? null : (typeof(obj.parent) == "object" ? obj.parent : null));
		this.child_frame = system.tools.get_var_object(obj.child);
		this.position = obj.position != undefined ? obj.position : DEFAULT_POSITION;
		this.offset_x = obj.x != undefined ? obj.x : DEFAULT_OFFSET_X;
		this.offset_y = obj.y != undefined ? obj.y : DEFAULT_OFFSET_Y;
		this.style_on = obj.style_on != undefined ? obj.style_on : DEFAULT_STYLE_ON;
		this.style_off = obj.style_off != undefined ? obj.style_off : DEFAULT_STYLE_OFF;
		this.elem = system.tools.get_var_object(obj.element);
		this.style_target = obj.target != undefined ? system.tools.get_var_object(obj.target) : this.elem;
		this.name = this.elem.id;
		system.events.add(this.elem, "mouseover", system.interface.menu.activator(this));
		system.events.add(this.elem, "mouseout", system.interface.menu.deactivator(this));
	}
	catch(e) { system.debug.trace("Error initializing menu item for id: '" + obj.element + "'", "error", e); }
}; var menu_item = system.interface.menu.item;

// Internal utility functions - not intended to be called directly ------------------------------------------------------------------------------

system.interface.menu.activator = function(obj)
{
	return function()
	{
		if(system.interface.menu.timer_on)
		{
			clearTimeout(system.interface.menu.timer_id);
			system.interface.menu.timer_id = null;
			system.interface.menu.timer_on = false;
		}

		var pos = obj;
		do { system.interface.menu.menu_path.unshift(pos); pos = pos.parent; } while(pos != null);
		system.interface.menu.deactivate();
		
		var path = "";
		for(i = 0; i < system.interface.menu.menu_path.length; i++)
		{
			path += system.interface.menu.menu_path[i].name;
			if(i < system.interface.menu.menu_path.length-1)
				path += " &raquo; ";
		}
		system.debug.status(path);
		
		obj.style_target.className = obj.style_on;
		if(obj.child_frame != null)
		{
			var offset = system.tools.get_elem_offset(obj.elem);
			if (obj.position == POS_BOTTOM) 
			{
				obj.child_frame.style.top = (offset.top + obj.elem.offsetHeight + obj.offset_y) + "px";
				obj.child_frame.style.left = (offset.left + obj.offset_x) + "px";
			}
			else if (obj.position == POS_RIGHT) 
			{
				obj.child_frame.style.top = (offset.top + obj.offset_y) + "px";
				obj.child_frame.style.left = (offset.left + obj.elem.offsetWidth + obj.offset_x) + "px";
			}
			else if (obj.position == POS_RELATIVE) 
			{
				obj.child_frame.style.top = (offset.top + obj.offset_y) + "px";
				obj.child_frame.style.left = (offset.left + obj.offset_x) + "px";
			}
			else if (obj.position == POS_ABSOLUTE) 
			{
				obj.child_frame.style.top = obj.offset_y + "px";
				obj.child_frame.style.left = obj.offset_x + "px";
			}
			obj.child_frame.style.visibility = "visible";			
		}
	};
};

system.interface.menu.deactivator = function(obj)
{
	return function()
	{
		var operation = function()
		{
			obj.style_target.className = obj.style_off;
			if(obj.child_frame != null)
				obj.child_frame.style.visibility = "hidden";
		};
		
		var deactivate_event = new Object;
		deactivate_event.name = obj.name;
		deactivate_event.deactivate = operation;
		system.interface.menu.event_queue.push(deactivate_event);
		system.interface.menu.menu_path = new Array();
		
		if(system.interface.menu.timer_on == false)
		{
			system.interface.menu.timer_id = setTimeout(system.interface.menu.deactivate, system.interface.menu.timer_delay);
			system.interface.menu.timer_on = true;
		}
	};
};

system.interface.menu.deactivate = function()
{
	var new_queue = new Array;
	while(itm = system.interface.menu.event_queue.pop())
	{
		found = false;
		for(i = 0; i < system.interface.menu.menu_path.length; i++)
			if(system.interface.menu.menu_path[i].name == itm.name)
				found = true;
		if(found == false) itm.deactivate();
		else new_queue.push(itm);
	}
	system.interface.menu.event_queue = new_queue;
	system.debug.status("Menu closed");
}
