
/**
 * Common functions
 * -----------------------------------------------
 * @copyright TimeZero <http://www.timezero.ru/>
 * @autor Dmitriy Shkinev <berkel@timezero.ru>
 * @version 2.0 2008-02-20
 */

function $(sId)
{
	if (sId.length > 1)
	{
		var sPrefix = sId.substring(0, 1),
			sName = sId.substring(1);

		if (sPrefix == '#')
		{
			return document.getElementById(sName);
		}
		else if (sPrefix == '.')
		{
			return Common.getElementsByClassName(document, '*', sName);
		}
		else
		{
			return document.getElementById(sId);
		}
	}
	else
	{
		return document.getElementById(sId);
	}
}

function var_dump(oElem)
{
	var sStr = '';

	if (Common.inArray(typeof(oElem), ['string', 'number']))
	{
		sStr = oElem;
	}
	else
	{
		var sValue = '';

		for (var oItem in oElem)
		{
			sValue = oElem[oItem];

			if (Common.inArray(oItem, ['innerHTML', 'outerHTML']))
			{
				sValue = sValue.replace(/</g, '&lt;').replace(/>/g, '&gt;');
			}

			sStr += 'obj.' + oItem + ' = ' + sValue + '\n';
		}
	}

	return sStr;
}

function debug(data)
{
	if (document.body)
	{
		var oItemId = 'js-debug',
			oItem = $(oItemId);

		if (!oItem)
		{
			oItem = document.createElement('DIV');
			oItem.setAttribute('id', oItemId);

			oItem.style.left = '0';
			oItem.style.top = '0';
			oItem.style.backgroundColor = 'yellow';
			oItem.style.color = '#000';
			oItem.style.width = '100%';

			document.body.insertBefore(oItem, document.body.firstChild);
		}

		oItem.innerHTML = '<pre style="margin:0;">' + var_dump(data) + '</pre>';

		oItem = null;
	}
	else
	{
		alert(var_dump(data));
	}
}

function return_false()
{
	return false;
}

var Common = {

	/*********Стандартные вспомогательные функции***********/

	aImgs : [],

	preloadImages : function()
	{ 
		for (var i=0, length=arguments.length, iImgLength=0; i<length; i++)
		{
			iImgLength = Common.aImgs.length;

			Common.aImgs[iImgLength] = new Image();
			Common.aImgs[iImgLength].src = arguments[i];
		}
	},

	informationObject : null,

	information : function()
	{
		var sUserAgent = navigator.userAgent.toLowerCase();

		if (window.opera)
		{
			this.bOpera = true;
		}

		if (sUserAgent.indexOf('safari') != -1)
		{
			this.bSafari = true;
		}
		else if (!this.bOpera && sUserAgent.indexOf('msie') != -1)
		{
			this.bIE = true;
		}
		else if (navigator.product == 'Gecko')
		{
			this.bGecko = true;
			this.bMozilla = true;
		}

		if (sUserAgent.indexOf('mac') != -1)
		{
			this.bMAC = true;
		}

		return this;
	},

	cloneObject : function(oObject)
	{
		var oNewObject = {};

		for (var sProperty in oObject)
		{
			oNewObject[sProperty] = oObject[sProperty];
		}

		return oNewObject;
	},

	inArray : function(sNeedle, aHaystack, bStrict)
	{
		if (bStrict)
		{
			var equals = function(a, b)
			{
				return (a === b);
			};
		}
		else
		{
			var equals = function(a, b)
			{
				return (a == b);
			};
		}

		for (var oItem in aHaystack)
		{
			if (equals(aHaystack[oItem], sNeedle))
			{
				return true;
			}
		}

		return false;
	},

	recursiveInArray : function(sNeedle, aHaystack, bStrict)
	{
		for (var i=0, length=aHaystack.length; i<length; i++)
		{
			var oItem = aHaystack[i];

			if (Common.inArray(typeof(oItem), ['array', 'object']))
			{
				if (Common.recursiveInArray(sNeedle, oItem, bStrict))
				{
					return true;
				}
			}
			else
			{
				if (Common.inArray(sNeedle, aHaystack, bStrict))
				{
					return true;
				}
			}
		}

		return false;
	},

	getSelectedText : function()
	{
		var sText = '';

		if (window.getSelection)
		{
			sText = window.getSelection();
		}
		else if (document.getSelection)
		{
			sText = document.getSelection();
		}
		else if (document.selection)
		{
			sText = document.selection.createRange().text;
		}

		return sText;
	},

	location : function(sUrl)
	{
		window.location.href = sUrl;
	},

	getRandom : function(iMin, iMax)
	{
		return (Math.round(Math.random() * (iMax - iMin)) + iMin);
	},

	between : function(iNum, iMin, iMax, bInclusive)
	{
		if (bInclusive)
		{
			return (iNum >= iMin && iNum <= iMax);
		}
		else
		{
			return (iNum > iMin && iNum < iMax);
		}
	},

	getScrollXY : function()
	{
		var iX = document.documentElement.scrollLeft || document.body.scrollLeft,
			iY = document.documentElement.scrollTop || document.body.scrollTop;

		return {x: iX, y: iY};
	},

	getElementsByClassName : function(oElem, sTagName, sClassName)
	{
		var aElements = (sTagName == '*' && oElem.all) ? oElem.all : oElem.getElementsByTagName(sTagName);

		sClassName = sClassName.replace(/\-/g, '\\-');

		var oRegExp = new RegExp('(^|\\s)' + sClassName + '(\\s|$)');

		for (var i=0, oElement=null, aReturnElements=[], length=aElements.length; i<length; i++)
		{
			oElement = aElements[i];

			if (oRegExp.test(oElement.className))
			{
				if (aReturnElements.push)
				{
					aReturnElements.push(oElement);
				}
			}
		}

		return aReturnElements;
	},

	getAbsolutePos : function(oElem)
	{
		var iX=0, iY=0;

		if (oElem)
		{
			do
			{
				iX += oElem.offsetLeft;
				iY += oElem.offsetTop;
			}
			while (oElem = oElem.offsetParent);
		}

		return {x: iX, y: iY};
	},

	pairsStringGetValue : function(sText, sName, sFrom, sBefore)
	{
		var sValue = '';

		if (sText)
		{
			if (!sFrom)
			{
				sFrom = '=';
			}

			if (!sBefore)
			{
				sBefore = ';';
			}

			sText = sText.replace(new RegExp('(' + sBefore + ')\\s+', 'g'), '$1');

			var iStart = sText.indexOf(sBefore + sName + sFrom);

			if (iStart >= 0)
			{
				iStart += (sBefore.length + sName.length + sFrom.length);
			}
			else
			{
				iStart = sText.indexOf(sName + sFrom);

				if (iStart == 0)
				{
					iStart += (sName.length + sFrom.length);
				}
				else
				{
					iStart = -1;
				}
			}

			if (iStart >= 0)
			{
				var iEnd = sText.indexOf(sBefore, iStart);

				if (iEnd < 0)
				{
					iEnd = sText.length;
				}

				sValue = sText.substring(iStart, iEnd);
			}
		}

		return sValue;
	},

	/*******************************************************/

	//Класс для работы с Cookie
	Cookie : {

		set : function(name, value, expires, path, domain, secure)
		{
			var cookieStr = name + '=' + escape(value) +
		        ((expires) ? '; expires=' + expires.toGMTString() : '') +
		        ((path) ? '; path=' + path : '') +
		        ((domain) ? '; domain=' + domain : '') +
		        ((secure) ? '; secure' : '');

		     document.cookie = cookieStr;
		},

		get : function(sName)
		{
			return Common.pairsStringGetValue(document.cookie, sName);
		}
	},

	/*******************************************************/

	//Класс для работы с Event
	Event : {

		add : function(eOn, sEvent_type, ptrFunction)
		{
			if (eOn.addEventListener)
			{
				eOn.addEventListener(sEvent_type, ptrFunction, false);
			}
			else if (eOn.attachEvent && sEvent_type != 'selectstart')
			{
				if (!eOn[sEvent_type + ptrFunction])
				{
					eOn['e' + sEvent_type + ptrFunction] = ptrFunction;

					eOn[sEvent_type + ptrFunction] = function()
					{
						eOn['e' + sEvent_type + ptrFunction](window.event);
					};

					eOn.attachEvent('on' + sEvent_type, eOn[sEvent_type + ptrFunction]);
				}
			}
			else
			{
				eOn['on' + sEvent_type] = ptrFunction;
			}
		},

		remove : function(eOn, sEvent_type, ptrFunction)
		{
			if (eOn.removeEventListener)
			{
				eOn.removeEventListener(sEvent_type, ptrFunction, false);
			}
			else if (eOn.detachEvent && sEvent_type != 'selectstart')
			{
				if (eOn[sEvent_type + ptrFunction])
				{
					eOn.detachEvent('on' + sEvent_type, eOn[sEvent_type + ptrFunction]);

					eOn[sEvent_type + ptrFunction] = null;

					eOn['e' + sEvent_type + ptrFunction] = null;
				}
			}
			else
			{
				eOn['on' + sEvent_type] = null;
			}
		},
		
		stopEvent : function(e) {
			if (e.preventDefault) {
		    	e.stopPropagation();
		    	e.preventDefault();
		    } else {
		    	e.returnValue = false;
		    	e.cancelBubble = true;
		    }
		},
		
		getTarget : function(e) {
			var event = e || window.event;
			var target = event.target || event.srcElement;
			return target;
		}
	},

	/*******************************************************/

	//Класс для работы с AJAX
	AJAX : {

		error : 0,

		isLoading : false,

		createRequest : function()
		{
			var request = null;

			if (window.XMLHttpRequest)
			{
				request = new XMLHttpRequest();

				if (request.overrideMimeType)
				{
					request.overrideMimeType('text/xml');
				}
			}
			else if (window.ActiveXObject)
			{
				var XMLHTTP_IDS = ['MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'];

				for (var i=0, length=XMLHTTP_IDS.length; i<length; i++)
				{
					try
					{
						request = new ActiveXObject(XMLHTTP_IDS[i]);

						if (request)
						{
							break;
						}
					}
					catch (e)
					{
					}
				}
			}

			return request;
		},

		readyStateChange : function(request, handler)
		{
			if (!(request || hander))
			{
				return false;
			}

			handler(request);

			if (request.readyState == 4)
			{
				this.isLoading = false;

				if (request.status == 200)
				{
					this.error = 0;
				}
				else
				{
					this.error = request.status;
				}
			}
			else
			{
				this.isLoading = true;
			}
		},

		sendRequest : function(method, url, args, handler, asynchronous)
		{
			var request = this.createRequest();

			if (!(request || handler))
			{
				return false;
			}

			var oThis = this;

			var readystatechange = function()
			{
				oThis.readyStateChange(request, handler);
			};

			request.onreadystatechange = readystatechange;
			request.open(method, url, asynchronous || false);

			if (method.toLowerCase() == 'post')
			{
				request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
				request.setRequestHeader('Content-length', args.length);
				request.setRequestHeader('Connection', 'close');
				request.send(args);
				
			}
			else
			{
				request.send(null);
			}

			try
			{
				if (request.onreadystatechange == null)
				{
					readystatechange();
				}
			}
			catch (e)
			{
				readystatechange();
			}
		},

		getContent : function(method, url, args)
		{
			var content = '';

			this.sendRequest(method, url, args,

				function(request)
				{
					if (request.readyState == 4 && request.status == 200 && request.responseText)
					{
						content = request.responseText;
					}
				}
			);

			return content;
		}
	},

	/*******************************************************/

	//Функции для работы с классами
	CSSClass : {

		switchClass : function(eOn, sClass_name, sInstead)
		{
			if (this.match(eOn, sClass_name))
			{
				this.set(eOn, sInstead, sClass_name);
			}
			else
			{
				this.set(eOn, sClass_name, sInstead);
			}
		},

		remove : function(eOn, sClass_name)
		{
			this.set(eOn, '', sClass_name);
		},

		change : function(eOn, sClass_name)
		{
			if (eOn)
			{
				sClass_name = (sClass_name.length) ? sClass_name.replace(/(^\s+|\s+$)/, '') : '';

				eOn.className = sClass_name;
			}
		},

		set : function(eOn, sClass_name, sInstead)
		{
			if (eOn)
			{
				sClass_name = (sClass_name.length) ? sClass_name.replace(/(^\s+|\s+$)/, '') : '';

				if (eOn.className.length)
				{
					var sOld = sClass_name;

					if (sInstead && sInstead.length)
					{
						sInstead = sInstead.replace(/\s+(\S)/g, '|$1');

						if (sOld)
						{
							sOld += '|';
						}

						sOld += sInstead;
					}

					eOn.className = eOn.className.replace(new RegExp('(^|\\s+)(' + sOld + ')($|\\s+)', 'g'), '$1');
				}

				eOn.className += (eOn.className.length && sClass_name ? ' ' : '') + sClass_name;
			}
		},

		match : function(eOn, sClass_name)
		{
			return (sClass_name && eOn.className && eOn.className.length && eOn.className.match(new RegExp('(^|\\s+)(' + sClass_name + ')($|\\s+)')));
		}
	},
	
	JSON : new (function(){
	    var useHasOwn = !!{}.hasOwnProperty;

	    var pad = function(n) {
	        return n < 10 ? "0" + n : n;
	    };

	    var m = {
	        "\b": '\\b',
	        "\t": '\\t',
	        "\n": '\\n',
	        "\f": '\\f',
	        "\r": '\\r',
	        '"' : '\\"',
	        "\\": '\\\\'
	    };

	    var encodeString = function(s){
	        if (/["\\\x00-\x1f]/.test(s)) {
	            return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
	                var c = m[b];
	                if(c){
	                    return c;
	                }
	                c = b.charCodeAt();
	                return "\\u00" +
	                    Math.floor(c / 16).toString(16) +
	                    (c % 16).toString(16);
	            }) + '"';
	        }
	        return '"' + s + '"';
	    };

	    var encodeArray = function(o){
	        var a = ["["], b, i, l = o.length, v;
	            for (i = 0; i < l; i += 1) {
	                v = o[i];
	                switch (typeof v) {
	                    case "undefined":
	                    case "function":
	                    case "unknown":
	                        break;
	                    default:
	                        if (b) {
	                            a.push(',');
	                        }
	                        a.push(v === null ? "null" : Common.JSON.encode(v));
	                        b = true;
	                }
	            }
	            a.push("]");
	            return a.join("");
	    };

	    this.encodeDate = function(o){
	        return '"' + o.getFullYear() + "-" +
	                pad(o.getMonth() + 1) + "-" +
	                pad(o.getDate()) + "T" +
	                pad(o.getHours()) + ":" +
	                pad(o.getMinutes()) + ":" +
	                pad(o.getSeconds()) + '"';
	    };

	    this.encode = function(o){
	        if(typeof o == "undefined" || o === null){
	            return "null";
	        }else if(o && typeof o.length == 'number' && typeof o.splice == 'function'){
	            return encodeArray(o);
	        }else if(o && typeof o.getFullYear == 'function'){
	            return this.encodeDate(o);
	        }else if(typeof o == "string"){
	            return encodeString(o);
	        }else if(typeof o == "number"){
	            return isFinite(o) ? String(o) : "null";
	        }else if(typeof o == "boolean"){
	            return String(o);
	        }else {
	            var a = ["{"], b, i, v;
	            for (i in o) {
	                if(!useHasOwn || o.hasOwnProperty(i)) {
	                    v = o[i];
	                    switch (typeof v) {
	                    case "undefined":
	                    case "function":
	                    case "unknown":
	                        break;
	                    default:
	                        if(b){
	                            a.push(',');
	                        }
	                        a.push(this.encode(i), ":",
	                                v === null ? "null" : this.encode(v));
	                        b = true;
	                    }
	                }
	            }
	            a.push("}");
	            return a.join("");
	        }
	    };

	    this.decode = function(json){
	        return eval("(" + json + ')');
	    };
	})(),

	Serializer : {

		serialize : function(object)
		{
			return this.recursiveSerialize(object, [], '').join('&');
		},

		recursiveSerialize : function(object, values, prefix)
		{
			for (key in object)
			{
				if (Common.inArray(typeof(object[key]), ['array', 'object']))
				{
					if (prefix.length > 0)
					{
						prefix += '[' + key + ']';
					}
					else
					{
						prefix += key;
					}

					values = this.recursiveSerialize(object[key], values, prefix);

					prefixes = prefix.split('[');

					prefix = prefixes.slice(0, prefixes.length - 1).join('[');
				}
				else
				{
					value = encodeURIComponent(object[key]);

					if (prefix.length > 0)
					{
						prefixed_key = prefix + '[' + key + ']';
					}
					else
					{
						prefixed_key = key
					}

					prefixed_key = encodeURIComponent(prefixed_key);

					if (value)
					{
						values.push(prefixed_key + '=' + value);
					}
				}
			}

			return values;
		}
	},

	Timer : {

		start : function()
		{
			var date = new Date();

			this.time = 0;
			this.timer = date.getTime();
		},

		stop : function()
		{
			var date = new Date();

			this.time = date.getTime() - this.timer;
			this.timer = 0;

			return this.getTime();
		},

		getTime : function()
		{
			return this.time / 1000;
		}
	}
};

Common.informationObject = new Common.information();