/*
* Victor A.Spirin, victor_as@mail.ru
* 2003.03.01 - 2003.06.25
*/

/*
			document.setElementPosition( element, x, y );
	was changed to 
			document.setElementPosition( element, x - 11, y + 5 );
*/



function buildMenus()
	{
	var es = document.links;
	var at = 'menu-id';
		for( var i = 0 ; i < es.length ; i++ )
		{
		var id = es[i].getAttribute(at);
			if( id != null && es[i].getMenuControl == null && document.getElementById(id) != null )
			var mc = new MenuControl( es[i] );
		}
	}



// public class
function MenuControl( htmlElement )
	{
	var HIDE_DELAY = 180;
	
	var menu;
	var element;
	
	var styles;
	
	var This = this;
	
	function init( e )
		{
 		element = e;
		styles = {init: {}};
		var s = getComputedStyle(e, null);
			if( s.length != null )
			{
				for( var i = 0 ; i < s.length ; i++ )
				{
				var n = s.item(i);
				styles.init[n] = s.getPropertyValue(n);
				}
			}
			else
			{
				for( var n in s )
				{
				styles.init[n] = s[n];
				}
			}
		e.getMenuControl = get_mc;
			if( e.addEventListener != null )
			{
			e.addEventListener('mouseover', handle_m_over, false);
			e.addEventListener('mouseout', handle_m_out, false);
			}
			else
			{
			e.attachEvent('onmouseover', handle_m_over);
			e.attachEvent('onmouseout', handle_m_out);
			}
		}
	
	this.getElement = function ()
		{
		return element;
		}
	
	function get_mc()
		{
		return This;
		}
	
	function handle_m_over( evt )
		{
			if( menu == null ) find();
		menu.layuot( This, element.getAttribute("menu-layout"), element.getAttribute("menu-align") );
		menu.show();
		}
	
	function handle_m_out( evt )
		{
			if( styles.over == null ) calc();
		menu.hideAfter( HIDE_DELAY );
		}
	
	function find()
		{
		var id = element.getAttribute("menu-id");
		var m = document.getElementById(id);
			if( m != null ) menu = m.getMenu != null ? m.getMenu() : new Menu(m);
			else alert('Illegal attribute menu-id: ' + id);
		}
	
	function calc()
		{
		var s = getComputedStyle(element, null);
		var init = styles.init;
		styles.init = null;
		styles.out = {};
		styles.over = {};
			if( s.length != null )
			{
				for( var i = 0 ; i < s.length ; i++ )
				{
				var n = s.item(i);
				var v = s.getPropertyValue(n);
					if( v != init[n] )
					{
					styles.out[n] = init[n];
					styles.over[n] = v;
					}
				}
			}
			else
			{
				for( var n in s )
				{
					if( s[n] != init[n] )
					{
					styles.out[n] = init[n];
					styles.over[n] = s[n];
					}
				}
			}
		}
	
	this.switchOn = function ()
		{
		switch_state('over');
		}
	
	this.switchOff = function ()
		{
		switch_state('out');
		}
	
	function switch_state( state )
		{
			if( styles.over == null ) return;
		var s = document.getOverrideStyle(element);
			if( s.length != null )
				for( var n in styles[state] )
				s.setProperty(n, styles[state][n], '');
			else
				for( var n in styles[state] )
				s[n] = styles[state][n];
		}
	
	init( htmlElement );
	}
	


// public class
function Menu( htmlElement )
	{
	var element;
	var menuControl;
	
	var thread;
	
	var This = this;
	
	function init( e )
		{
		element = e;
		e.getMenu = get_m;
			if( e.addEventListener != null )
			{
			e.addEventListener('mouseover', handle_m_over, false);
			e.addEventListener('mouseout', handle_m_out, false);
			}
			else
			{
			e.attachEvent('onmouseover', handle_m_over);
			e.attachEvent('onmouseout', handle_m_out);
			}
		}
	
	this.getElement = function ()
		{
		return element;
		}
	
	this.getMenuControl = function ()
		{
		return menuControl;
		}
	
	function get_m()
		{
		return This;
		}
	
	function handle_m_over( evt )
		{
			if( document.isMSIE && element.contains(evt.fromElement) ) return;
		This.show();
		}
	
	function handle_m_out( evt )
		{
			if( document.isMSIE && element.contains(evt.toElement) ) return;
		This.hide();
		}
	
	this.layuot = function ( control, layout, align )
		{
		menuControl = control;
		var ce = control.getElement();
		var ds = document.getElementSize( document.body );
		var ms = document.getElementSize( element );
		var p = document.getElementPosition( ce );
		var x, y;
			if( layout == 'top' )
			{
			x = (align == 'right' || ds.width < p.x + ms.width) ? p.x + document.getElementSize(ce).width - ms.width : p.x;
			y = p.y - ms.height;
			}
			else if( layout == 'left' )
			{
			x = p.x - ms.width;
			y = (align == 'bottom' || ds.height < p.y + ms.height) ? p.y - ms.height + document.getElementSize(ce).height : p.y;
			}
			else if( layout == 'right' )
			{
			var cs = document.getElementSize( ce );
			x = p.x + cs.width;
			y = (align == 'bottom' || ds.height < p.y + ms.height) ? p.y - ms.height + cs.height : p.y;
			}
			else
			{
			var cs = document.getElementSize( ce );
			x = (align == 'right' || ds.width < p.x + ms.width) ? p.x + cs.width - ms.width : p.x;
			y = p.y + cs.height;
			}
		document.setElementPosition( element, x - 11, y + 5 );
		}
	
	this.show = function ()
		{
		This.clearHide();
			if( element.onshow != null && getComputedStyle(element, null).visibility != 'visible' ) element.onshow();
		menuControl.switchOn();
		document.getOverrideStyle(element).visibility = 'visible';
		}
	
	this.hide = function ()
		{
		This.clearHide();
			if( element.onhide != null && getComputedStyle(element, null).visibility != 'hidden' ) element.onhide();
		document.getOverrideStyle(element).visibility = 'hidden';
		menuControl.switchOff();
		}
	
	this.hideAfter = function ( delay )
		{
		This.clearHide();
		thread = setTimeout( This.hide, delay );
		}
	
	this.clearHide = function ()
		{
			if( thread != null )
			{
			clearTimeout( thread );
			thread = null;
			}
		}
	
	init( htmlElement );
	}
