/*
*	Packages Menu, Analyzing
*	menu.complete.js		2001.04.12
*	Victor A.Spirin,	victor_aspirin@mail.ru
*/



var AnalyzeManager = new analyzeManager();

AnalyzeManager.addAnalyzer( new link_analyzer(null, linkMenuActivator, 'bottom') );

window.onload = function ()
	{
	AnalyzeManager.analyzeAll();
	}

function menu( Element, ActivatorContext )
	{
	var DELAY_FOR_MOUSE_OUT_MENU = 300;

	Element = new baseElement( Element );
	var ParentMenu;
	var IsTopLevelMenu;

	var HideThread;

		if( document.layers != null )
		{
		window.getSize = function ()
			{
			return {Width: window.innerWidth, Height: window.innerHeight};
			}

		function cancel()
			{
			return false;
			}
		}
		else if( document.all != null )
		{
		window.getSize = function ()
			{
			return {Width: document.body.scrollWidth, Height: document.body.offsetHeight};
			}

		function cancel()
			{
			event.cancelBubble = true;
			return false;
			}

		Element.onmousedown = cancel;
		Element.onmouseup = cancel;
		}
		else return null;

	Element.getParentMenu = function ()
		{
			if( IsTopLevelMenu == null )
			{
				if( ActivatorContext != null && ActivatorContext.getParentMenu != null )
				{
				ParentMenu = ActivatorContext;
				IsTopLevelMenu = false;
				}
				else IsTopLevelMenu = true;
			}
		return ParentMenu;
		}

	function getContext()
		{
		var M = Element;
			while( M.getParentMenu() != null )
			{
			M = M.getParentMenu();
			}
		return M.parentLayer != null && M.parentLayer != window ? new baseElement( M.parentLayer ) : window;
		}

	function selectByPlacing( Size, AreaBegin, AreaSize, HoleBegin, HoleSize )
		{
		return HoleBegin + HoleSize + Size < AreaBegin + AreaSize ? HoleBegin + HoleSize : HoleBegin - Size;
		}

	function selectByAligning( Size, AreaBegin, AreaSize, HoleBegin, HoleSize )
		{
		return HoleBegin + Size < AreaBegin + AreaSize ? HoleBegin : HoleBegin + HoleSize - Size;
		}

	function selectByRestricting( Size, AreaBegin, AreaSize, HoleBegin, HoleSize )
		{
		return HoleBegin + Size < AreaBegin + AreaSize ? HoleBegin : AreaBegin + AreaSize - Size;
		}

	Element.place = function ( ActivatorPosition, ActivatorSize, Layout )
		{
		var Context = getContext();
		var Origin = Context.getAbsolutePosition != null ? Context.getAbsolutePosition() : {X: 0, Y: 0};
		var Area = Context.getSize();

		var Size = Element.getSize();

		var X;
		var Y;
			if( IsTopLevelMenu )
			{
				if( Layout == 'top' || Layout == 'bottom'  )
				{
				X = selectByRestricting( Size.Width, Origin.X, Area.Width, ActivatorPosition.X, ActivatorSize.Width );
				Y = selectByPlacing( Size.Height, Origin.Y, Area.Height, ActivatorPosition.Y, ActivatorSize.Height );
				}
				else if( Layout == 'left' || Layout == 'right' )
				{
				X = selectByPlacing( Size.Width, Origin.X, Area.Width, ActivatorPosition.X, ActivatorSize.Width );
				Y = selectByAligning( Size.Height, Origin.Y, ActivatorPosition.Y, ActivatorSize.Height );
				}
			}
			else
			{
			X = selectByPlacing( Size.Width, Origin.X, Area.Width, ParentMenu.getAbsolutePosition().X, ParentMenu.getSize().Width );
			Y = selectByAligning( Size.Height, Origin.Y, Area.Height, ActivatorPosition.Y, ActivatorSize.Height );
			}
		Element.moveToAbsolute( X, Y );
		}

	Element.hideAfter = function ( Waiting )
		{
		HideThread = setTimeout( Element.hide, Waiting )
		}

	Element.clearHide = function ()
		{
			if( HideThread != null ) clearTimeout( HideThread );
		HideThread = null;
		}

	var IsMicrosoft = document.all != null;//////////////////////////////////////////////////////

	Element.onmouseover = function onMouseOver( Evt )
		{
			if( !IsMicrosoft || !Element.contains(event.fromElement) )
			{
			var M = Element;
				while( M != null )
				{
				M.clearHide();
				M.show();
				M = M.getParentMenu();
				}
			}
		return cancel();
		}

	Element.onmouseout = function onMouseOut( Evt )
		{
			if( !IsMicrosoft || !Element.contains(event.toElement) )
			{
			Element.hide();
			var M = Element.getParentMenu();
				while( M != null )
				{
				M.hideAfter( DELAY_FOR_MOUSE_OUT_MENU );
				M = M.getParentMenu();
				}
			}
		return cancel();
		}

	return Element;
	}

function baseElement( Element )
	{
		if( document.layers != null )
		{
		Element.show = function show( Strongly )
			{
			Element.visibility = Strongly ? 'show' : 'inherit';
			}

		Element.hide = function hide()
			{
			Element.visibility = 'hide';
			}

		Element.getAbsolutePosition = function ()
			{
			return {X: Element.pageX, Y: Element.pageY};
			}

		Element.getSize = function ()
			{
			return {Width: Element.clip.width, Height: Element.clip.height};
			}
		}
		else if( document.all != null )
		{
		Element.show = function show( Strongly )
			{
			Element.style.visibility = Strongly ? 'visible' : 'inherit';
			}

		Element.hide = function hide()
			{
			Element.style.visibility = 'hidden';
			}

		Element.getAbsolutePosition = function ()
			{
			var PageX = 0;
			var PageY = 0;
			var E = Element;
				while( E != null )
				{
				PageX += E.offsetLeft;
				PageY += E.offsetTop;
				E = E.offsetParent;
				}
			return {X: PageX, Y: PageY};
			}

		Element.getSize = function ()
			{
			return {Width: (Element.style.posWidth != 0 ? Element.style.pixelWidth : Element.offsetWidth), Height: (Element.style.posHeight != 0 ? Element.style.pixelHeight : Element.offsetHeight)};
			}

		Element.moveToAbsolute = function ( X, Y )
			{
			var X0 = 0;
			var Y0 = 0;
			var P = Element.offsetParent;
				while( P != null )
				{
				X0 += P.offsetLeft;
				Y0 += P.offsetTop;
				P = P.offsetParent;
				}
			Element.style.pixelLeft = X - X0;
			Element.style.pixelTop = Y - Y0;
			}
		}
		else return null;

	return Element;
	}

function linkMenuActivator( Link, Container, Name, Layout )
	{
	var DELAY_FOR_MOUSE_OUT_ACTIVATOR = 120;

	var Menu = findLayer( Name, Container.window.document );
		if( Menu == null ) return null;

		if( document.layers != null )
		{
		Link.getAbsolutePosition = function ()
			{
				if( Container == Container.window ) return {X: Link.x, Y: Link.y};
				else return {X: Link.x + Container.pageX, Y: Link.y + Container.pageY};
			}

		function getValueOf( SizeString )
			{
			var M = SizeString.match( /([0-9]+\.?[0-9]*)([a-zA-Z]*)/ );
				switch( M[2] )
				{
				case 'px': return parseInt( M[1] );
				case 'pt': return parseInt( M[1] )*96/72;
				case 'mm': return parseInt( M[1] )*96/25.4;
				case 'cm': return parseInt( M[1] )*96/2.54;
				}
			}

		Link.getSize = function ()
			{
			var DEFAULT_FONT_SIZE = 16;
			var DEFAULT_TEXT_LENGTH = 8;
			var FontSize;
				if( document.tags['a'].fontSize != null ) FontSize = getValueOf( document.tags['a'].fontSize );
				else if( document.tags['body'].fontSize != null ) FontSize = getValueOf( document.tags['body'].fontSize );
				else FontSize = DEFAULT_FONT_SIZE;
			var W = FontSize*(0.5*(Link.text != null ? Link.text.length : DEFAULT_TEXT_LENGTH) + 0.2);
			var H = FontSize*1.5;
			return {Width: Math.round(W), Height: Math.round(H)};
			}

		Link.getContext = function ()
			{
			return Container;
			}

		function cancel()
			{
			return false;
			}
		}
		else if( document.all != null )
		{
		Link.getAbsolutePosition = function ()
			{
			var X = 0;
			var Y = 0;
			var E = Link;
				while( E != null )
				{
				X += E.offsetLeft;
				Y += E.offsetTop;
				E = E.offsetParent;
				}
			return {X: X, Y: Y};
			}

		Link.getSize = function ()
			{
			return {Width: Link.offsetWidth, Height: Link.offsetHeight};
			}

		Link.getContext = function ()
			{
				for( var P = Link.offsetParent ; P.tagName != 'BODY' ; P = P.offsetParent )
					if( P.tagName != 'TABLE' && P.tagName != 'TR' && P.tagName != 'TD' ) return P;
			return Container.window;
			}

		function cancel()
			{
			event.cancelBubble = true;
			return false;
			}
		}
		else return null;

	function findLayer( ID, Document )
		{
		var Ls = Document.layers;
			if( Ls == null ) return Document.all[ID];
			if( Ls[ID] != null ) return Ls[ID];
		var L;
			for( var i = 0 ; i < Ls.length ; i++ )
			{
			L = findLayer( ID, Ls[i].document );
				if( L != null ) return L;
			}
		return null;
		}

	Link.onmouseover = function onMouseOver( Evt )
		{
		Menu.clearHide();
		Menu.place( Link.getAbsolutePosition(), Link.getSize(), Layout );
		Menu.show();
		return cancel();
		}

	Link.onmouseout = function onMouseOut( Evt )
		{
		Menu.hideAfter( DELAY_FOR_MOUSE_OUT_ACTIVATOR );
		return cancel();
		}

	Link.href = Container.window.document.location.href;
//	Link.onclick = cancel;

	Menu = new menu( Menu, Link.getContext() );

	return Link;
	}

function link_analyzer( Marker, objectConstructor, ObjectData )
	{
	var Type = Marker != null ? Marker.toLowerCase() : null;

	this.getType = function ()
		{
		return Type;
		}

	this.findArray = function findArray( Container )
		{
			if( window.document.layers != null ) return Container.document.links;
			else if( document.all != null ) return (Container != window ? Container : document).all.tags( 'a' );
			else return null;
		}

	function getPath( Link )
		{
		var Ret = unescape( Link.href );
		var i = Ret.indexOf( '#' );
			if( 0 < i ) Ret = Ret.substring(0, i);
			if( Link.pathname == '/' && Ret.charAt(Ret.length - 1) != '/' ) Ret += '/';
		return Ret; 
		}

	function getHash( Link )
		{
		var i = Link.href.indexOf( '#' );
		return (0 < i && i + 1 < Link.href.length) ? Link.href.substring(i + 1) : null; 
		}

	this.accept = function accept( Element, Container )
		{
		var Hash = getHash( Element );
			if( Hash == null || getPath(Element) != getPath(Container.window.document.location) ) return false;

		var Anchors = Container.window.document.anchors;
			for( var i = 0 ; i < Anchors.length ; i++ )
				if( Anchors[i].name == Hash ) return false;

		return (Type == null || Hash.toLowerCase().search(Type) != -1);
		}

	this.createObject = function createObject( Element, Container )
		{
		var Object = new objectConstructor( Element, Container, getHash(Element), ObjectData );
		}
	}

function analyzeManager()
	{
	var Analyzers;
	var This = this;

	this.addAnalyzer = function addAnalyzer( New )
		{
			if( New.getType != null
			&&	New.findArray != null
			&&	New.accept != null
			&&	New.createObject != null )
			{
				if( Analyzers == null ) Analyzers = {};
			Type = New.getType();
				if( Type == null ) Type = 'type_' + Math.random();
			Analyzers[Type] = New;
			}
		}

	this.analyze = function ( Type, Container )
		{
		var Cont = Container != null ? Container : window;
		var An = Analyzers[Type];

		var Elements = An.findArray( Cont );
			for( var j = 0 ; j < Elements.length ; j++ )
			{
				if( An.accept(Elements[j], Cont) ) An.createObject( Elements[j], Cont );
			}

			if( Cont.document != null && Cont.document.layers != null )
			{
				for( var k = 0 ; k < Cont.document.layers.length ; k++ )
				This.analyze( Type, Cont.document.layers[k] );
			}
		}

	this.analyzeAll = function ( Container )
		{
			for( var each in Analyzers )
			This.analyze( each, Container );
		}
	}

