
/****************************************************************************/

defined = function(x) {
	return x === undefined ? false : true;
};

exists = function(x) {
	return (x === undefined || x === null) ? false : true;
};

empty = function(x) {
	return (x === undefined || x === null || x === '') ? true : false;
};

finite = function(x) {
	return isFinite( x ) ? x : 0;
};


finiteInt = function(x, base) {
	return finite(parseInt(x, base));
};


finiteFloat = function(x) {
	return finite(parseFloat(x));
};


max = function() {
	var a = arguments;
	var n = a[0];
	for (var i = 1; i < a.length; i++) if (a[i] > n) n = a[i];
	return n;
};


min = function() {
	var a = arguments;
	var n = a[0];
	for (var i = 1; i < a.length; i++) if (a[i] < n) n = a[i];
	return n;
};

/****************************************************************************/

function l_funccat(f1, f2)
{
	if (empty(f1)) return f2;
	if (empty(f2)) return f1;

	return function()
	{
		f1.call(this, arguments);
		return f2.call(this, arguments);
	};
};

/****************************************************************************/

if (!Object.prototype.hasOwnProperty)
{
	Object.prototype.hasOwnProperty = function(p)
	{
		if (!(p in this)) return false;

		try {
			var pr = this.constructor.prototype;
			while (pr)
			{
				if (pr[p] === this[p]) return false;
				if (pr === pr.constructor.prototype) break;
				pr = pr.constructor.prototype;
			}
		} catch(e) {}
		return true;
	};
}

/****************************************************************************/

Object.prototype.extend = function()
{
	var a = arguments;
	for (var i = 0; i < a.length; i++)
	{
		var o = a[i];
		for (var p in o)
		{
			try {
				if (!this[ p ] && (!o.hasOwnProperty || o.hasOwnProperty(p))) this[p] = o[p];
			} catch(e) {}
		}
	}
	return this;
}

/****************************************************************************/

String.prototype.extend( {
	trim: function() {
		return this.replace( /^\s+|\s+$/g, "" );
	}
} );

/****************************************************************************/

/* Информация о браузере. */
l_browser1 = function()
{
	/* Общая информация об агенте. */
	this.ver   = navigator.appVersion;
	this.agent = navigator.userAgent.toLowerCase();

	/* Поддерживаемые возможности. */
	this.dom   = document.getElementById ? 1:0;
	this.all   = document.all ? 1:0;

	/* Определяем движок агента. */

	this.opera = this.agent.indexOf("opera") > -1;

	this.ie7   = (this.ver.indexOf('MSIE 7') > -1 && this.dom) ? 1:0;
	this.ie6   = (this.ver.indexOf('MSIE 6') > -1 && this.dom) ? 1:0;
	this.ie5   = (this.ver.indexOf('MSIE 5') > -1 && this.dom) ? 1:0;
	this.ie4   = (document.all && !this.dom) ? 1:0;
	this.ie    = this.ie4 || this.ie5 || this.ie6 || this.ie7;

	this.firefox = (this.agent.indexOf('firefox') > -1) ? 1:0;
	this.khtml   = (this.agent.indexOf('khtml'  ) > -1) ? 1:0;

	//this.gecko   = (this.agent.indexOf('gecko'  ) > -1) ? 1:0;

	return this;
};

l_browser = new l_browser1();

/****************************************************************************/

/* Возвращает первый найденный элемент, относящийся к указанному тегу, либо null. */
function l_getElementByTagName(tagname)
{
	var r = document.getElementsByTagName ? document.getElementsByTagName(tagname) : null;
	if (r && r[0]) {r = r[0];}
	else           {r = null;}
	return r;
};

/****************************************************************************/

/* Ищет элементы, имеющий указанный класс. */
function l_getElementsByClass(searchClass, node, tag)
{
	var classElements = new Array();
	if (node == null) node = document;
	if (tag  == null) tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
    
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	for (i = 0, j = 0; i < elsLen; i++)
	{
		if ( pattern.test(els[i].className) )
		{
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
};

/****************************************************************************/

function l_ElementAddClass(Element, Cls)
{
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	if ( pattern.test(Element.className)) return;

	if (Element.className && Element.className != '') Cls = Element.className.trim() + ' ' + Cls.trim();
	body.className = Cls;
}

/****************************************************************************/

/* Регистратор функций отложенной инициализации по событию onload. */

function l_load()
{
	var next_index = 0;
	var handlers = new Array();
	var ready = 0;

	this.handler = function()
	{
		if (!ready)
		{
			ready = 1;
			for (var i = 0; i < next_index; i++) handlers[i]();
		}
	};

	this.add_handler = function(func)
	{
		handlers[next_index++] = func;
	};

	var objects = window.addEventListener || window.attachEvent ? window : document.addEventListener ? document : null;
	if(objects.addEventListener)
	{
		objects.addEventListener('load', this.handler, false);
	}
	else if (objects.attachEvent)
	{
		objects.attachEvent('onload', this.handler);
	}
};

/****************************************************************************/

/* Обработчик всплывающих подсказок. */

function l_hint()
{
	var th = this;

	this.initialize = function()
	{
		var hint = document.createElement("div");
		hint.setAttribute('id', 'l_hint');
		l_getElementByTagName('body').appendChild(hint);
		hint.style.visibility = 'hidden';

		var tagnames  = ['a','img', 'b', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'div', 'span', 'th', 'td'];

		var hint_text;
		for (var k1 in tagnames)
		{
			var tags = document.getElementsByTagName(tagnames[k1]);

			for (var k2 in tags)
			{
				var tag = tags[k2];

				/* BUG: Следующее условие никогда не проходит в Konqueror 3.3 */

				if (!tag.getAttribute) continue;

				if (!tag.removeAttribute) continue;

				if (hint_text = tag.getAttribute('title'))
				{
					tag.removeAttribute('title');
					th.register_tag(tag, hint_text, hint);
				}
				else if (hint_text = tag.getAttribute('alt'))
				{
					th.register_tag(tag, hint_text, hint);
				}
			}
		}
	};

	this.register_tag = function(tag, hint_text, hint)
	{
		var on_mouse_out = function()
		{
			hint.style.width = '';
			hint.style.visibility = 'hidden';
		};
		tag.onmouseout = l_funccat(tag.onmouseout, on_mouse_out);

		var on_mouse_move = function(advance)
		{
			if (window.l_getElementByTagName === undefined || window.l_getElementByTagName === null)
			{
				return;
			}

			hint.style.width = '';
			hint.innerHTML = hint_text;

			var vc = l_getElementByTagName((document.compatMode && document.compatMode=="CSS1Compat") ? "html":"body");

			var x = window.event ? event.clientX + vc.scrollLeft : advance.pageX;
			var y = window.event ? event.clientY + vc.scrollTop  : advance.pageY;

			var vcwidth  =
				vc.clientWidth ? vc.clientWidth  + vc.scrollLeft : window.innerWidth + window.pageXOffset;
			var vcheight =
				window.innerHeight ? window.innerHeight + window.pageYOffset : vc.clientHeight + vc.scrollTop;

			/*
				BUG USERAGENT:
				В Opera наблюдается ошибка: если показывается длинный элемент,
				которому принудительно уменьшаем ширину, то эта ширина запоминается
				и далее все элементы отображаются с данной шириной.
			*/
			if (hint.offsetWidth > 270)
			{
				hint.style.width = '270px';
			}

			if ((x + hint.offsetWidth + 15) > vcwidth)
			{
				var left = x - hint.offsetWidth - 4;
			}
			else
			{
				var left = x + 15;
			}
			hint.style.left = left.toString() + 'px';

			if((y + hint.offsetHeight + 19) > vcheight)
			{
				var top = y - hint.offsetHeight;
			}
			else
			{
				var top = y + 19;
			}
			hint.style.top = top.toString() + 'px';

			hint.style.opacity = '.91';
			hint.style.filter = "alpha(opacity:91)";
			hint.style.visibility = 'visible';
		};
		tag.onmousemove = on_mouse_move;
	};
};

/****************************************************************************/

window.LOAD = new l_load();

if (!l_browser.ie) {
	var HINT = new l_hint();
	window.LOAD.add_handler(HINT.initialize);
}


