var
$_D									= document,
$_W									= window,

/**
 *	Object detects and store browser information
 *
 * @author MMX <mmx@vitcompany.com>
 * @package VITFramework
 * @version 0.2
 */
$Browser						= new function(){
	var b								= navigator.userAgent;
	this.op							= (/opera/i.test(b));							//	Opera
	this.ff							= (/firefox/i.test(b));						//	Firefox
	this.sf							= (/safari/i.test(b));						//	Safari
	this.ie							= (/msie/i.test(b) && !this.op);	//	IE
	this.v							= parseFloat(											//	Version
		(this.ie)
			? navigator.userAgent.replace(/^.*?MSIE\s([\d\.]+).*?$/, '$1')
			: (this.ff)
					? navigator.userAgent.replace(/^.*?Firefox\/([\d\.]+)$/, '$1')
					: navigator.appVersion);
},

/**
 *	AutoStart object for:
 *	- register & call `onload` function
 *
 * @author MMX <mmx@vitcompany.com>
 * @package VITFramework
 * @version 0.2
 */
$Loader					= new function(){
	var
	/**
	 *	Detect is document load completed
	 *	@var boolean
	 */
	bDocLoaded					= 0,
	/**
	 *	Array of functions, which called on document load complete
	 *	@var array
	 */
	aHandlers						= [],

	/**
	 *	Call functions from array
	 *	@param array aHandlers Array with functions
	 */
	_callHandlers				= function (aHandlers, fHandler)
	{
		while(fHandler = aHandlers.shift())
			fHandler();
	};

	/**
	 *	Register functions, which called on document load complete
	 *	@param function fOnload : called on document load complete
	 */
	this.set						= function(fOnload)
	{
		if ('function' == typeof fOnload)
			(bDocLoaded) ? fOnload() : aHandlers[aHandlers.length] = fOnload;
	};

	/**
	 *	Call functions, registered by `this.set` method, when document load completed
	 */
	$_W.onload					= function()
	{
		bDocLoaded = 1;
		_callHandlers(aHandlers);
	};
};

/**
 *	Добавляем функции работы с DOM елементами
 *
 *	@author MMX <mmx@vitcompany.com>
 *	@package VITFramework
 *	@version 0.3
 */
/**
 *	Check that the argument is a DOM Element
 *	@param mixed m something
 *	@return boolean
 */
function isNode(m)
{
	return ((m) && (('undefined' != typeof m.nodeType) || (m.hasAttribute && m.hasAttribute('nodeType'))));
};

/**
 *	Cover for document.getElementById()
 *	@param string m DOMNode id
 *	@return DOMNode
 */
function byId(m)
{
	return (m && 'string' == typeof m) ? $_D.getElementById(m) : null;
};

/**
 *	Select from specified DOMNode elements By TagName
 *	@param string sTag elements tag name
 *	@param DOMNode [option] dNode startpoint
 *	@param boolean [option] bOne return first element
 *	@return DOMNode collection
 */
function byTag(sName, dNode, bOne)
{
	dNode = isNode(dNode) ? dNode : $_D;
	var aResult = ('*' == sName && $Browser.ie && 6 > $Browser.v)
		? dNode.all : dNode.getElementsByTagName(sName);
	return (aResult.length) ? (bOne) ? aResult[0] : aResult : null;
};

/**
 *	Select from specified DOMNode elements By ClassName
 *	@param string sName elements class name
 *	@param DOMNode [option] dNode startpoint
 *	@param boolean [option] bOne return first element
 *	@return DOMNode collection
 */
function byClass(sName, dNode, bOne)
{
	dNode = byTag('*', dNode);
	sClassName = ' ' + sName + ' ';
	var aResult = [];
	for (var i = 0; i < dNode.length; i ++)
	{
		if ( -1 != (' ' + dNode[i].className + ' ').indexOf(sName) )
		{
			aResult.push(dNode[i]);
		}
	}
	return (aResult.length) ? (bOne) ? aResult[0] : aResult : null;
};

/**
 *	Select from specified DOMNode elements By Name
 *	@param string sName elements name
 *	@param DOMNode [option] dNode startpoint
 *	@param boolean [option] bOne return first element
 *	@return DOMNode collection
 */
function byName(sName, dNode, bOne)
{
	var aResult = [];
	if (dNode)
	{
		dNode = byTag('*', dNode);
		for (var i = 0; i < dNode.length; i ++)
		{
			if (sName == dNode[i].name)
			{
				aResult.push(dNode[i]);
			}
		}
	}
	else
	{
		aResult = $_D.getElementsByName(sName);
	}
	return (aResult.length) ? (bOne) ? aResult[0] : aResult : null;
};

/**
 *	Add to DOM Element class
 *	@param DOMNode dNode target node
 *	@param string sClass class name
 *	@param boolean bReplace replace current element class
 *	@return DOMNode dNode
 */
function _classSet(dNode, sClass, bReplace)
{
	if ('string' == typeof sClass && isNode(dNode) &&
		(!_classHas(dNode, sClass) || bReplace)
	)
	{
		dNode.className = ((!bReplace && dNode.className) ? dNode.className + ' ' : '') + sClass;
	}
	return dNode;
};
/**
 *	Check that the node has specified className
 *	@param DOMNode dNode target node
 *	@param string sClass class name
 *	@return boolean
 */
function _classHas(dNode, sClass)
{
	return ('string' == typeof sClass && isNode(dNode) && -1 != (' ' + dNode.className + ' ').indexOf(' ' + sClass + ' '));
};
/**
 *	Remove class from DOMNode
 *	@param DOMNode dNode target node
 *	@param string [option] sClass class name
 *	@return DOMNode dNode
 */
function _classUnset(dNode, sClass)
{
	if (isNode(dNode))
	{
		dNode.className = (sClass && 'string' == typeof sClass)
			? dNode.className.replace( new RegExp('^(.*?)\\s?'+sClass+'(.*?)$') ,  '$1$2' )
			: '';
		dNode.className = dNode.className.replace( new RegExp('^\\s+?(.*?)\\s+?$'), '$1');
	}
	return dNode;
};

/**
 *	Add to DOM Element style attributes
 *	@param DOMNode dNode target node
 *	@param array aAttrs attributes (Key=>Attr, Value=>AttrValue)
 *	@return DOMNode dNode
 */
function _styleSet(dNode, aAttrs)
{
	if (isNode(dNode) && 'object' == typeof aAttrs)
	{
		for (var i in aAttrs)
		{
			dNode.style[i] = aAttrs[i];
		}
	}
	return dNode;
};


var $Effects				= new function()
{
	this.aEffect				= {
		/**
		 *	Effect Slide.
		 *	Slide elements Style-Property From-Coord To-Coord
		 *	@param domNode dBody target element
		 *	@param array aData parameters
		 *		- number [option] .step Number of steps from Source position to Final position
		 *		- number [option] .interval Timeout in milisecs beetwen actions
		 *		- array .attrs Style properties to modify, Key: property name,
		 *						Value: array [ 0: Source value, 1: Final value ]
		 *		- function [option] .onstart Handler on effect start
		 *		- function [option] .onfinish Handler on effect finish
		 */
		slide								: function(dBody, aData) {
				var th						= this;
				this.dBody				= dBody;
				this.aStep				= [];
				this.aData				= aData;
				this.aHandlers		= {
					onstart						: aData.onstart,
					onfinish					: aData.onfinish };

				this.start				= function()
				{
					if ('function' == typeof th.aHandlers.onstart)
					{
					  th.aHandlers.onstart(th.dBody);
					}
					th.dBody.style.opacity = 0.4;
					for (i in th.aData.attrs)
					{
						th.dBody.style[i] = th.aData.attrs[i][0] + 'px';
					}
				};

				this.go						= function()
				{
					var q = th.aStep.shift();
					for (var i in q)
					{
						th.dBody.style[i] = q[i];
					}
				};

				this.finish				= function()
				{
					th.dBody.style.opacity = 1;
					for (i in th.aData.attrs)
					{
						th.dBody.style[i] = th.aData.attrs[i][1] + 'px';
					}
					if ('function' == typeof th.aHandlers.onfinish)
					{
					  th.aHandlers.onfinish(th.dBody);
					}
				};

				(function(){
					var iStep = aData.step || 10, iInterval = aData.interval || 10, aAttrsStep = {}, i, j;
					for (i in aData.attrs)
					{
						aAttrsStep[i] = Math.round( (aData.attrs[i][1] - aData.attrs[i][0]) / iStep );
					}

					for (i = 0; i < iStep - 1; i ++)
					{
						th.aStep[i] = {};
						for (j in aAttrsStep)
						{
							th.aStep[i][j] = aAttrsStep[j] * i + 'px';
						}
					}

					setTimeout(th.start, iInterval);
					for (i = 0; i < iStep - 1; i ++)
					{
						setTimeout(th.go, iInterval + 5 * i);
					}
					setTimeout(th.finish, iInterval + 5 * (iStep));
				})();
			}
	};

	this.apply					= function(sName, mBody, aData)
	{
		if (!this.aEffect[sName]) return;
		if ('string' == typeof mBody) mBody = byId(mBody);
		var oEffect = new this.aEffect[sName](mBody, aData);
	};
};


/**
 *	Provide displaying sub-menues
 *		on mouseOver/ mouseOut with timeout
 *
 * @author MMX <mmx@vitcompany.com>
 * @package VITFramework
 * @version 0.2
 */
var $MenuOver				= new function()
{
	var th							= this;
	this.tHover					= null;
	this.dActive				= null;
	this.dOpen					= null;
	this.sCandidate			= null;
	this.aMenues				= {};


	this.init						= function(sMenuId)
	{
		var aNodes = byTag('a', byId(sMenuId));
		if (!aNodes) return;
		var dNode, iLeft;
		for (var i = 0; i < aNodes.length; i ++)
		{
			if (aNodes[i].name && (dNode = byId('s'+aNodes[i].name)))
			{
				aNodes[i].onmouseover	= this.eHover;
				aNodes[i].onmouseout	= this.eOut;
				iLeft = aNodes[i].parentNode.offsetLeft;
				if ($Browser.op && 9 > $Browser.v)	iLeft -= 330;
				_styleSet(dNode, {left: iLeft + 'px'});
				this.aMenues[aNodes[i].name] = dNode;
				dNode.onmouseover			= this.eHover;
				dNode.onmouseout			= this.eOut;
				if (_classHas(dNode, 'menu_on'))		this.dOpen = dNode;
			}
		}
	};


	this.eHover					= function()
	{
		th._stopTimeout();
		if (th.aMenues[this.name])		th.sCandidate = this.name;
		else							return;
		if (th.dActive)		return th.slowHover();
		th.tHover = setTimeout(th.slowHover, 250);
	};
	this.slowHover			= function()
	{
		th._stopTimeout();
		if (th.dActive)			_classUnset(th.dActive, 'menu_on');
		else if (th.dOpen)	_classUnset(th.dOpen, 'menu_on');
		if (th.sCandidate)
		{
			th.dActive = th.aMenues[th.sCandidate];
			var iHeight = th.dActive.firstChild.offsetHeight;
			if ($Browser.ie && 7 > $Browser.v) iHeight += 5;
			$Effects.apply(
				'slide',
				th.dActive,
				{	step		: 15,
					attrs		: {
						height	: [0, iHeight] },
					onstart	: th._fShow });
			th.dActive.style.height = 0;
		}
	};

	this.eOut						= function()
	{
		th._stopTimeout();
		if (th.dActive)			th.tHover = setTimeout(th.slowOut, 250);
	};
	this.slowOut				= function()
	{
		th._stopTimeout();
		if (th.dActive && th.dOpen && th.dActive.id == th.dOpen.id) return ;
		if (th.dActive)
		{
			_classUnset(th.dActive, 'menu_on');
			th.dActive = null;
		}
		if (th.dOpen)
		{
			var iHeight = th.dOpen.firstChild.offsetHeight;
			if ($Browser.ie && 7 > $Browser.v) iHeight += 5;
			$Effects.apply(
				'slide',
				th.dOpen,
				{	step		: 15,
					attrs		: {
						height	: [0, iHeight] },
					onstart	: th._fShow });
			th.dOpen.style.height = 0;
		}
	};
	this._fShow					= function(dNode)
	{
		_classSet(dNode, 'menu_on');
	};

	this._stopTimeout		= function()
	{
		if (this.tHover)
		{
			clearTimeout(this.tHover);
			this.tHover = null;
		}
	};
};

$Loader.set(function(){
	$MenuOver.init('menu_main');
	if ('undefined' != typeof SWFObject)
	{
		var src = byTag('span', byId('page_image'), 1);
		if (src && src.innerHTML)
		{
			// src="{$P.swf}" quality="high" bgcolor="#ffffff" width="330" height="440" name="swf_page_image"
			// new SWFObject(swf, id, width, height, version, background-color [, quality, xiRedirectUrl, redirectUrl, detectKey]);
			var so = new SWFObject(src.innerHTML, 'swf_page_image', '330', '440', '8', '#ffffff', 'high');
			so.write("page_image");
		}
	}
});