﻿/*************************************************
*     Модуль манипуляции свойствами объекта     *
*                                               *   
*     Автор:                     Агроник А.Ю.   *
*     Дата создания:             08.06.2007     *
*     Дата изменения:            21.07.2008     * 
*                                               *
*                                               *
*		Внимание! данный файл является           *
*		частью программного продукта SCSC        *
*      и не поставляется отдельно. Права        *
*      на программный продукт SCSC              *
*      принадлежат компании A2 www.a2soft.ru    *
*											   	 *
*************************************************/

var $global = {
    Mouse: {
        X: "0",
        Y: "0"
    },
    GetConst: {
        Up: "up",
        First: "first",
        Last: "last",
        Next: "next",
        Previous: "prev",
        All: "all"
    },
    MakeFlash: function(src, id, width, height, wmode, scale, quality, flashvars)
    {
        /// <summary>Сделать строку с объектом флеша</summary>
        /// <returns type="String" />
        var flashvars = $G.IsString(flashvars) ? flashvars.replace(/\=/gi, '%3D').replace(/\&/gi, '%26') : $server.GetPostString(flashvars);
        var result = "<object classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0\" width=\"" + width + "\" height=\"" + height + "\" id=\"" + id + "\" align=\"top\"><param name=\"flashvars\" value=\"" + flashvars + "\"><param name=\"allowScriptAccess\" value=\"always\" /><param name=\"movie\" value=\"" + src + "\" /><param name=\"menu\" value=\"true\" /><param name=\"quality\" value=\"" + quality + "\" /><param name=\"scale\" value=\"" + scale + "\" /><param name=\"salign\" value=\"lt\" /><param name=\"wmode\" value=\"" + wmode + "\" /><param name=\"devicefont\" value=\"true\" /><embed src=\"" + src + "\" menu=\"true\" quality=\"" + quality + "\" scale=\"" + scale + "\" salign=\"lt\" wmode=\"" + wmode + "\" devicefont=\"true\" bgcolor=\"#ffffff\" width=\"" + width + "\" height=\"" + height + "\" name=\"" + id + "\" align=\"top\" allowScriptAccess=\"always\" type=\"application/x-shockwave-flash\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" flashvars=\"" + flashvars + "\" /></object>";
        return result;
    },
    Extend: function(obj, eobj, prefix)
    {
        /// <summary>Расширяет объект 'obj' свойствами объекта 'eobj'</summary>
        /// <returns type="Object" />
        for (var _prop in eobj)
        {
            if (_prop != "style")
                obj[(prefix || "") + _prop] = eobj[_prop];
        }
        return obj;
    },
    ExtendPrivate: function(obj, eobj)
    {
        return $G.Extend(obj, eobj, "_");
    },
    Match: function(obj1, obj2)
    {
        var result = true;
        for (var i in obj2)
        { result = result && (obj1[i] == obj2[i]); }
        return result;
    },
    Clone: function(obj, nofuncs) // Попробовать
    {
        var a = new Object();
        for (var i in obj)
            if (!nofuncs || !$global.IsFunction(obj))
            a[i] = obj[i];
        return a;
    },
    Date:
    {
        ShortMonth: ["", "янв", "фев", "мар", "апр", "мая", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"],
        Month: ["", "января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
        MonthEntity: ["", "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"],
        DaysOfWeek: ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"],
        DaysOfWeekShort: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"],
        StringFormat: function(str, date)
        {
            if (!str || !date)
                return "";
            return str.replace(/dddd/gi, $G.Date.DaysOfWeek[date.getDay()])
                      .replace(/ddd/gi, $G.Date.DaysOfWeekShort[date.getDay()])
                      .replace(/dd/gi, $G.Number.Norm(date.getDate(), 2))
                      .replace(/d/gi, $G.Number.Norm(date.getDate(), 1))
                      .replace(/^MMMM/g, $G.Date.MonthEntity[date.getMonth() + 1])
                      .replace(/MMMM/g, $G.Date.Month[date.getMonth() + 1])
                      .replace(/MMM/g, $G.Date.ShortMonth[date.getMonth() + 1])
                      .replace(/MM/g, $G.Number.Norm(date.getMonth() + 1, 2))
                      .replace(/M/g, $G.Number.Norm(date.getMonth() + 1, 1))
                      .replace(/yyyy/gi, date.getFullYear().toString())
                      .replace(/yy/gi, date.getFullYear().toString().substring(2, 4))
                      .replace(/mm/g, $G.Number.Norm(date.getMinutes(), 2))
                      .replace(/m/g, date.getMinutes().toString())
                      .replace(/HH/g, $G.Number.Norm(date.getHours(), 2))
                      .replace(/H/g, $G.Number.Norm(date.getHours(), 1))
                      .replace(/hh/g, $G.Number.Norm($G.Date.ShortHours(date), 2))
                      .replace(/h/g, $G.Number.Norm($G.Date.ShortHours(date), 1))
                      .replace(/ss/g, $G.Number.Norm(date.getSeconds(), 2))
                      .replace(/s/g, $G.Number.Norm(date.getSeconds(), 1));
        },
        ShortHours: function(date)
        {
            return date.getHours() > 12 ? date.getHours() - 12 : date.getHours();
        },
        Decade: function(date)
        {
            return Number(date.getFullYear().toString().substr(0, 3) + "0");
        },
        TryGetDate: function(str)
        {
            var res = new Date();
            var datetime = str.split(" ");
            if (datetime.length == 1)
                datetime.push("00:00");
            var date = datetime[0].split(".");
            if (date.length != 3)
                new Date();
            else
                res.setFullYear(Number(date[2]), Number(date[1]) - 1, Number(date[0]));
            return res;
        },
        Clone: function(date)
        {
            var _wd = new Date();
            _wd.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
            return _wd;
        },
        Compare: function(date1, date2)
        {
            return ((date1.getFullYear() == date2.getFullYear()) &
                    (date1.getMonth() == date2.getMonth()) &
                    (date1.getDate() == date2.getDate()));
        },
        Format: function(str)
        {
            return $global.FormatDate(str);
        },
        ShortDate: function(date)
        {
            return $G.Number.Norm(date.getDate()) + "." + $G.Number.Norm((date.getMonth() + 1)) + "." + date.getFullYear();
        },
        FormString: function(date)
        {
            return date.getDate() + " " + $global.Date.Month[date.getMonth() + 1] + " " + date.getFullYear();
        }
    },
    FormatDate: function(str)
    {
        var sep = str.indexOf(".") != -1 ? "." : "/";
        var m = sep == "." ? 1 : 0;
        var d = m == 1 ? 0 : 1;
        var date = str.split(sep);
        if ($global.Date.Month[Number(date[m])] != null)
            date[m] = $global.Date.Month[Number(date[m])];
        var res = date[d] + " " + date[m] + " " + date[2];
        if (res.indexOf(":") != -1)
            res = res.substring(0, res.lastIndexOf(":"));
        return res;
    },
    CurrentMenu: null, // Что Это ??!!
    SwapClasses: function(class1, class2, obj) // Переключить классы у объекта (1 -> 2, 2 -> 1)
    {
        if (obj)
        {
            obj.className = obj.className == class1 ? class2 : class1;
        }
    },
    SwapAttributeValues: function(value1, value2, obj, attr) // Переключить значения атрибутов ???
    {
        if (obj)
        {
            var attribute = obj.getAttributeNode(attr);
            if (attribute)
                attribute.value = attribute.value == value1 ? value2 : value1;
        }
    },
    SetAttr: function(obj, attr, value)
    {
        var _attr = obj.getAttributeNode(attr);
        if (_attr == null)
            _attr = document.createAttribute(attr);
        _attr.value = value;
        obj.setAttributeNode(_attr);
    },
    SwapText: function(obj, Text1, Text2) // Переключить текст
    {
        if (obj)
        {
            var tmp = this.GetText(obj);
            this.SetText(obj, (tmp == Text1 ? Text2 : Text1));
        }
    },
    SwapVisibility: function(obj) // Переключить выдимость элемента
    {
        this.Display.Swap(obj, "none", "block");
    },
    Cookie:
    {
        Set: function(name, value, days, path, domain, secure) // установить заничение Cookie 
        {
            var expire = new Date();
            if (days)
                expire.setTime(expire.getTime() + (days * 24 * 60 * 60 * 1000));
            document.cookie = name + "=" + escape(value) +
					((days) ? "; expires=" + expire.toGMTString() : "") +
					((path) ? "; path=" + path : "") +
					((domain) ? "; domain=" + domain : "") +
					((secure) ? "; secure" : "");
        },
        Get: function(name) // получить значение Cookie по имени
        {
            var cookie = " " + document.cookie;
            var search = " " + name + "=";
            var setStr = null;
            var offset = 0;
            var end = 0;
            if (cookie.length > 0)
            {
                offset = cookie.indexOf(search);
                if (offset != -1)
                {
                    offset += search.length;
                    end = cookie.indexOf(";", offset)
                    if (end == -1)
                    {
                        end = cookie.length;
                    }
                    setStr = unescape(cookie.substring(offset, end));
                }
            }
            return (setStr);
        }
    },
    Display: {
        Swap: function(obj, value1, value2) // Переключить значение стиля display
        {
            if (obj)
            {
                obj.style.display = obj.style.display == value1 ? value2 : value1;
            }
        },
        Clear: function(obj)	// очистить значение стиля display
        {
            if (obj)
            {
                var _obj = obj;

                if (window["A2"])
                    if (A2.UI.Control.prototype.isPrototypeOf(obj))
                    _obj = obj.Holder;
                _obj.style.display = "";
            }
        },
        Block: function(obj)	// установить значение display в block
        {
            if (obj)
            {
                var _obj = obj;

                if (window["A2"])
                    if (A2.UI.Control.prototype.isPrototypeOf(obj))
                    _obj = obj.Holder;
                _obj.style.display = "block";
            }
        },
        Inline: function(obj) // установить значение display в inline
        {
            if (obj)
            {
                var _obj = obj;

                if (window["A2"])
                    if (A2.UI.Control.prototype.isPrototypeOf(obj))
                    _obj = obj.Holder;
                _obj.style.display = "inline";
            }
        },
        Hide: function(obj)	// установить значение display в none
        {
            if (obj)
            {
                var _obj = obj;

                if (window["A2"])
                    if (A2.UI.Control.prototype.isPrototypeOf(obj))
                    _obj = obj.Holder;
                _obj.style.display = "none";
            }
        },
        Visible: function(obj)
        {
            return $G.GetStyle(obj, "display") != "none";
        },
        Blink: function(obj, values)
        {
            for (var i = 0; i < values.length; i++)
            {
                obj.style.display = values[i];
            }
        }
    },
    GetParent: function(obj, depth) // получит родительский нод вверх на depth элементов
    {
        var res = null;
        if (obj)
        {
            res = obj;
            var i = 1;
            while (depth >= i)
            {
                res = res.parentNode != null ? res.parentNode : res;
                i++;
            }
        }
        return res;
    },
    GetIframeDocument: function(iframe)
    {
        return iframe ? iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow.document : null;
    },
    GetText: function(obj)
    {
        var result = "";
        if (obj)
            result = (obj.innerText) ? obj.innerText : ((obj.textContent) ? obj.textContent : "");
        return result;
    },
    SetError: function(obj)
    {
        if (obj)
            $G.ClassName.Replace(obj, "", "ErrorCtrl");
    },
    isError: function(obj)
    {
        if (obj)
        {
            return $G.ClassName.Has(obj, "ErrorCtrl");
        }
        return false;
    },
    ClearError: function(obj)
    {
        if (obj)
            $G.ClassName.Replace(obj, "ErrorCtrl", "");
    },
    StepToNumber: function(str) // преобразует строку вида xkym к виду x000y000000
    {
        return str.replace(/k/gi, "000").replace(/m/gi, "000000");
    },
    FindPosition: function(obj)
    {
        var curleft = curtop = 0;
        if (obj.offsetParent)
        {
            curleft = obj.offsetLeft
            curtop = obj.offsetTop
            while (obj = obj.offsetParent)
            {
                curleft += obj.offsetLeft
                curtop += obj.offsetTop
            }
        }
        return [curleft, curtop];
    },
    GetTopLeft: function(obj)
    {
        var b = this.FindPosition(obj);
        return { x: b[0], y: b[1] };
    },
    /* Следующий блок заменить на что-нибудь типа:
    Align.AtCursor(), Align.ScreenCenter(), Align.Under(), Align.On(), Align.LeftOf(), Align.RightOf() */
    ShowAtPosition: function(obj, noshow, ox, oy)
    {
        if (obj)
        {
            obj.style.position = "absolute";
            if (!noshow)
                obj.style.display = "block";
            obj.style.top = "0px";
            obj.style.left = "0px";
            var pos = $global.FindPosition(obj);
            obj.style.top = Number($global.Mouse.Y - pos[1] + (oy ? oy : 0)) + "px";
            obj.style.left = Number($global.Mouse.X - pos[0] + (ox ? ox : 0)) + "px";

        }
    },
    ShowInPageCenterByBounds: function(obj, w, h)
    {
        if (obj)
        {
            obj.style.position = "absolute";
            var _deltaX = (w / 2);
            var _deltaY = (h / 2);
            var _centerW = ($global.Window.Width() / 2) + $global.Window.Scroll.Left();
            var _centerH = ($global.Window.Height() / 2) + $global.Window.Scroll.Top();
            obj.style.top = ((_centerH - _deltaY) > 0) ? (Math.floor(_centerH - _deltaY) + "px") : "0px";
            obj.style.left = ((_centerW - _deltaX) > 0) ? (Math.floor(_centerW - _deltaX) + "px") : "0px";
            $global.Display.Block(obj);
        }
    },
    ShowInPageCenter: function(obj)
    {
        if (obj)
        {
            var w = obj.offsetWidth;
            var h = obj.offsetHeight;
            w = w == 0 ? $global.GetStyle(obj, "width", true) : w;
            h = h == 0 ? $global.GetStyle(obj, "height", true) : h;
            w += $global.GetStyle(obj, "borderLeftWidth", true) + $global.GetStyle(obj, "borderRightWidth", true);
            h += $global.GetStyle(obj, "borderTopWidth", true) + $global.GetStyle(obj, "borderBottomWidth", true);
            $global.ShowInPageCenterByBounds(obj, w, h);
        }
    },
    ShowUnderObject: function(obj, target, noabs)
    {
        if (obj && target)
        {
            obj.style.top = "0px";
            obj.style.left = "0px";
            var oldPos = ($global.Browser.Detect.ie) ? [0, 0] : $global.FindPosition(obj);
            var h = target.offsetHeight;
            var position = $global.FindPosition(target);
            if (!noabs) { obj.style.position = "absolute"; };
            obj.style.top = Number(position[1] + h + oldPos[1]) + "px";
            obj.style.left = Number(position[0] + oldPos[0]) + "px";
            if ($global.Browser.Detect.opera)
            {
                obj.style.left = Number(position[0] + oldPos[0] - 1) + "px";
            }
            obj.style.display = "block";
        }
    },
    ShowRightToObject: function(obj, target, noabs)
    {
        if (obj && target)
        {
            obj.style.top = "0px";
            obj.style.left = "0px";
            var oldPos = ($global.Browser.Detect.ie && !$global.Browser.Detect.ie7) ? [0, 0] : $global.FindPosition(obj);
            var w = target.offsetWidth;
            var position = $global.FindPosition(target);
            if (!noabs) { obj.style.position = "absolute"; };
            obj.style.top = Number(position[1] + oldPos[1]) + "px";
            obj.style.left = Number(position[0] + w + oldPos[0]) + "px";
            obj.style.display = "block";
        }
    },
    ShowLeftToObject: function(obj, target, noabs)
    {
        if (obj && target)
        {
            obj.style.top = "0px";
            obj.style.left = "0px";
            var oldPos = ($global.Browser.Detect.ie && !$global.Browser.Detect.ie7) ? [0, 0] : $global.FindPosition(obj);
            var w = target.offsetWidth;
            var position = $global.FindPosition(target);
            if (!noabs) { obj.style.position = "absolute"; };
            obj.style.top = Number(position[1] + oldPos[1]) + "px";
            obj.style.left = Number(position[0] - w + oldPos[0]) + "px";
            obj.style.display = "block";
        }
    },
    /* --- конец блока --- */
    TrackMousePosition: function(e)
    {
        var posx = 0;
        var posy = 0;
        if (!e) var e = window.event;
        if (e.pageX || e.pageY)
        {
            posx = e.pageX;
            posy = e.pageY;
        }
        else if (e.clientX || e.clientY)
        {
            posx = e.clientX + document.body.scrollLeft
			    + document.documentElement.scrollLeft;
            posy = e.clientY + document.body.scrollTop
			    + document.documentElement.scrollTop;
        }
        $global.Mouse.X = posx;
        $global.Mouse.Y = posy;
    },
    InitEvents: function(e)
    {
        var _o = document.onmousemove;
        document.onmousemove = function(ev)
        {
            if (_o)
                _o(ev);
            $global.TrackMousePosition(ev);
        };
        this.CssFix.Init();
    },
    GetKeyCode: function(e)
    {
        var e = e ? e : window.event;
        var code = e.keyCode ? e.keyCode : e.which;
        return code;
    },
    Event:
	{
	    Add: function(obj, type, fn, key)
	    {
	        if (window["A2"])
	        {
	            if (UIControl.prototype.isPrototypeOf(obj))
	                return obj.AddEvent.bind(obj)(type, fn);
	        }
	        if (type != "rclick")
	        {
	            if (obj.attachEvent)
	            {
	                if (key)
	                {
	                    obj['e' + type + key] = fn;
	                    obj[type + key] = function() { obj['e' + type + key](window.event); }
	                    obj.attachEvent('on' + type, obj[type + key]);
	                }
	                else
	                {
	                    obj["on" + type] = fn;
	                }
	            }
	            else
	                obj.addEventListener(type, fn, false);
	        }
	        else
	        {
	            var fnc = fn;
	            $G.Event.Add(obj, "mouseup", function(e)
	            {
	                var btn = $G.Event.Button(e);
	                if (btn == 2 || btn == 3)
	                {
	                    this.fnc(e);
	                }
	                btn = null;
	            } .bind({ fnc: fnc }));
	        }
	        return obj;
	    },
	    Remove: function(obj, type, fn, key)
	    {
	        var _obj = window["A2"] ? UIControl.prototype.isPrototypeOf(obj) ? obj.Holder : obj : obj;
	        if (_obj.detachEvent)
	        {
	            _obj.detachEvent('on' + type, _obj[type + (key || fn)]);
	            _obj[type + (key || fn)] = null;
	        }
	        else
	            _obj.removeEventListener(type, fn, false);
	        return _obj;
	    },
	    KeyCode: function(e)
	    {
	        return $global.GetKeyCode(e);
	    },
	    KeyIsNotSystem: function(e)
	    {
	        var code = $G.Event.KeyCode(e);
	        return (code >= 48 && code <= 57) || (code >= 65 && code <= 90) || (code >= 186 && code <= 192) || (code >= 219 && code <= 222) || code == 226; //печатные символы
	    },
	    KeyIsTextEdit: function(e)
	    {
	        var code = $G.Event.KeyCode(e);
	        return (code == 37) || (code == 39) || (code == 32) || (code == 8) || (code == 46) || $G.Event.KeyIsNotSystem(e); // вперед, назад, вверх, вниз, пробел, делит, бэкспейс, + печатные символы
	    },
	    Target: function(e)
	    {
	        var e = e ? e : event;
	        return e.target ? e.target : e.srcElement;
	    },
	    Button: function(e)
	    {
	        var e = e ? e : event;
	        return e.button ? e.button : e.which;
	    }
	},
    /*
    Merge: function(func, func2)
    {
    return function()
    {
    if (func)
    func.apply(this, arguments);
    if (func2)
    func2.apply(this, arguments);
    }
    },
    SwitchToggleGroupByClass: function(obj, class1, class2, formal) // Частная задача для Tezey - ?
    {
    if (obj)
    {
    var objs = obj.parentNode.getElementsByTagName("div");
    for (var i = 0; i < objs.length; i++)
    if (objs[i] != obj)
    if (objs[i].className.indexOf(formal) != -1)
    objs[i].className = class1[i];
    obj.className = class2;
    }
    },
    SwitchDivGroupClass: function(obj, toggleClass) // Частная задача для Tezey - ?
    {
    if (obj)
    {
    var divGroup = obj.parentNode.getElementsByTagName("div");
    for (var i = 0; i < divGroup.length; i++)
    if (divGroup[i] != obj)
    if (divGroup[i].getAttribute('defaultClass') != null)
    divGroup[i].className = divGroup[i].getAttribute('defaultClass');
    obj.className = toggleClass;
    }
    },
    */
    Next: function(obj, num)
    {
        var result = null;
        if (obj)
        {
            if (num == null)
            {
                result = obj.nextSibling;
                if (result != null)
                    if (result.nodeType == 3)
                    result = this.Next(result);
            }
            else
            {
                result = this.Next(obj);
                for (var i = 1; i < num; i++)
                    result = this.Next(result);
            }
        }
        return result;
    },
    Previous: function(obj, num)
    {
        var result = null;
        if (obj)
        {
            if (num == null)
            {
                result = obj.previousSibling;
                if (result != null)
                    if (result.nodeType == 3)
                    result = this.Previous(result);
            }
            else
            {
                result = this.Previous(obj);
                for (var i = 1; i < num; i++)
                    result = this.Previous(result);
            }
        }
        return result;
    },
    XML:
	{
	    Parse: function(xml)
	    {
	        if (window.ActiveXObject)
	        {
	            var doc = new ActiveXObject("Microsoft.XMLDOM");
	            doc.async = "false";
	            doc.loadXML(xml);
	        }
	        else
	        {
	            var parser = new DOMParser();
	            var doc = parser.parseFromString(xml, "text/xml");
	        }
	        return doc.documentElement;
	    }
	},
    GetAttribute: function(obj, attr)
    {
        var result = "";
        if (obj)
        {
            var a = (obj.getAttribute(attr) || obj[attr]);
            result = this.isString(a) ? a : "";
        }
        return result;
    },
    ValueInArray: function(array, value)
    {
        var result = false;
        if (array)
        {
            if (value)
            {
                for (var i = 0; i < array.length; i++)
                {
                    result = result || (array[i] == value);
                }
            }
        }
        return result;
    },
    HasKey: function(array, key)
    {
        return array[key] != null;
    },
    NormCssStr: function(cssPropStr) // Приводит строку к виду для JS, например  margin-left > marginLeft
    {
        var i, c, a = cssPropStr.split('-');
        var s = a[0];
        for (i = 1; i < a.length; ++i)
        {
            c = a[i].charAt(0);
            s += a[i].replace(c, c.toUpperCase());
        }
        return s;
    },
    ShrinkStr: function(str, chars, last, empty)
    {
        return str.length > chars ? str.substring(0, chars) + last : str.length == 0 ? empty : str;
    },
    SmartShrinkStr: function(str, chars, last, empty)
    {
        var i = chars;
        while (str.length > i && (str.substring(i, i + 1) != " ")) { i++; };
        return str.length > i ? str.substring(0, i) + last : str.length == 0 ? empty : str;
    },
    ClassName:
    {
        Replace: function(obj, cname1, cname2)
        {
            var cname1 = $global.IsString(cname1) ? [cname1] : cname1;
            var cname2 = $global.IsString(cname2) ? [cname2] : cname2;

            var obj = (window["A2"] && A2.UI.Control.prototype.isPrototypeOf(obj) ? obj.Holder : obj);
            var classes = (obj.className ? obj.className.toString().despace().split(" ") : []);
            for (var i = 0; i < classes.length; i++)
                if (cname1.contains(classes[i]))
                classes[i] = "";
            classes = classes.concat(cname2);
            obj.className = classes.join(" ").despace();
        },
        Has: function(obj, cname)
        {
            var cname = $global.IsString(cname) ? [cname] : cname;
            var obj = (window["A2"] && A2.UI.Control.prototype.isPrototypeOf(obj) ? obj.Holder : obj);
            var classes = (obj.className ? obj.className.toString().despace().split(" ") : []);
            var result = classes.length > 0;
            for (var i = 0; i < cname.length; i++)
            {
                result = result && classes.contains(cname[i]);
            }
            return result;
        }
    },
    GetStyle: function(obj, css, i) // Получает значение стиля, если если i == true возвращает int
    {
        if (!obj)
            return null;
        var s, v = 'undefined', dv = document.defaultView;
        if (dv && dv.getComputedStyle)
        {
            s = dv.getComputedStyle(obj, '');
            if (s) v = s.getPropertyValue(css);
        }
        else if (obj.currentStyle)
            v = obj.currentStyle[this.NormCssStr(css)];
        else return null;
        return i ? (parseInt(v) || 0) : v;
    },
    SetStyle: function(sProp, sVal) // Устанавливает значение стиля для нескольких объектов (через запятую после sVal)
    {
        var i, e;

        if (sProp.indexOf("-") != -1)
            sProp = $G.NormCssStr(sProp);

        for (i = 2; i < arguments.length; ++i)
        {
            e = arguments[i];
            if (e)
            {
                if (window["A2"])
                    e = e.Holder ? e.Holder : e;
                if (e.style)
                {
                    try { e.style[sProp] = sVal; }
                    catch (err) { e.style[sProp] = ''; } // ???
                }
            }
        }
    },
    IsString: function(value)
    {
        return typeof (value) == 'string';
    },
    IsNumber: function(value)
    {
        return typeof (value) == 'number';
    },
    IsFunction: function(value)
    {
        return Function.prototype.isPrototypeOf(value);
    },
    IsDate: function(value)
    {
        return Date.prototype.isPrototypeOf(value);
    },
    isDate: function(value) { return $global.IsDate(value); },
    isString: function(value) { return this.IsString(value); },
    Is: function(obj, type)
    {
        return obj && type && type.prototype.isPrototypeOf(obj);
    },
    FilterByValue: function(array, attr, value)
    {
        var res = new Array();
        if (Array.prototype.isPrototypeOf(array))
            for (var i = 0; i < array.length; i++)
            if (array[i][attr] == value)
            res.push(array[i]);
        return res;
    },
    HTML:
    {
        SendEncode: function(inner)
        {
            var encoded = "";
            for (var i = 0; i < inner.length; i++)
            {
                var code = inner.charCodeAt(i);
                if ((code < 32) || (code >= 128 && code <= 191) || (code > 1110) || code == 43)
                {
                    encoded += "&#" + code.toString() + ";";
                }
                else
                {
                    encoded += inner.charAt(i);
                }
            }
            encoded = encoded.replace(/\&/gi, "%26");

            return encoded;
        },
        EnAmp: function(str)
        {
            return str.replace(/\%26/gi, "&").replace(/\&/gi, "&amp;");
        },
        DeAmp: function(str)
        {
            return str.replace(/\&amp\;/gi, "&");
        },
        Encode: function(str)
        {
            return str.replace(/\</gi, "&lt;").replace(/\>/gi, "&gt;");
        },
        DeQuote: function(str)
        {
            return str.replace(/\&quot\;/gi, "\"");
        },
        EnQuote: function(str)
        {
            return str.replace(/\"/gi, "&quot;");
        },
        URLEncode: function(str)
        {
            var res = $global.HTML.Encode(str);
            return res.replace(/\&/gi, "[#amp]");
        },
        GETVars: function(id)
        {
            var url = document.location.toString();
            var vars = { __count: 0 };
            if (url.indexOf("#") != -1)
                url = url.substring(0, url.indexOf("#"));
            if (url.indexOf("?") != -1)
            {
                url = url.substring(url.indexOf("?") + 1, url.length);
                var _vars = url.split("&");
                for (var i = 0; i < _vars.length; i++)
                {
                    var _cv = _vars[i].split("=");
                    if (_cv.length > 1)
                    {
                        vars[_cv[0].toLowerCase()] = _cv[1];
                        vars.__count++;
                    }
                }
            }
            if (id)
                return (vars[id] || vars[id.toLowerCase()]);
            return vars;
        },
        Decode: function(str)
        {
            return str.replace(/\&lt\;/gi, "<").replace(/\&gt\;/gi, ">");
        },
        URLDecode: function(str)
        {
            var res = str.replace(/\[\#amp\]/gi, "&");
            return $global.HTML.Decode(res);
        },
        Trims: function(str)
        {
            return str.replace(/\r/gi, "").replace(/\n/gi, "<br />");
        },
        GetDomain: function(str)
        {
            var domain = str ? str.replace("http://", "") : "";
            domain = domain.replace("www.", "");
            return domain.indexOf("/") != -1 ? domain.substring(0, domain.indexOf("/")) : domain;
        },
        Unicode: function(lit)
        {
            var el = $global.Tag("div", null, null, lit);
            return el.innerHTML;
        },
        NumForm: function(str, male, num)
        {
            var res = str;
            var a = num - Math.floor(num / 10);
            res += male ? (a >= 5 || a == 0) ? "ов" : a == 1 ? "" : "а" : (a >= 5 || a == 0) ? "" : a == 1 ? "a" : "ы";
            return res;
        },
        Typo: function(str) // Пока тест
        {
            var r = str;
            var patt1 = /\"[^\"]+\"/gi;

            var a = patt1.exec(r);
            while (a != null)
            {
                var s = "";
                for (var i = 0; i < a.length; i++)
                {
                    s = s + a[i];
                }
                var g = s.replace(/\"/gi, "");
                r = r.replace(s, "\&laquo\;" + g + "\&raquo\;");
                a = patt1.exec(r);
            }
            r = r.replace(/\s\-\s/gi, " &mdash; ");
            r = r.replace(/\.\.\.\s/gi, "&hellip;" + " ");
            return r;
        }
    },
    SetOpacity: function(obj, val) // Устанавливает значение непрозрачности для разных браузеров
    {
        this.Opacity.Set(obj, val);
    },
    ClearOpacity: function(obj)
    {
        this.Opacity.Clear(obj);
    },
    Opacity:
    {
        Set: function(obj, val)
        {
            if (obj)
            {
                //Внимание! zoom используется для применения hasLayout в IE. без него не работает
                if (!$G.GetStyle(obj, "zoom"))
                    $G.SetStyle("zoom", "1", obj);
                if ($global.isString(obj.style.opacity))
                    obj.style.opacity = val + '';
                else if ($global.isString(obj.style.filter))
                    obj.style.filter = 'alpha(opacity=' + (100 * val) + ')';
                else if ($global.isString(obj.style.MozOpacity))
                    obj.style.MozOpacity = val + '';
                else if ($global.isString(obj.style.KhtmlOpacity))
                    obj.style.KhtmlOpacity = val + '';
            }
        },
        Clear: function(obj)
        {
            if (obj)
            {
                if ($global.isString(obj.style.opacity))
                    obj.style.opacity = '';
                else if ($global.isString(obj.style.filter))
                    obj.style.filter = '';
                else if ($global.isString(obj.style.MozOpacity))
                    obj.style.MozOpacity = '';
                else if ($global.isString(obj.style.KhtmlOpacity))
                    obj.style.KhtmlOpacity = '';
            }
        },
        Get: function(obj)
        {
            if (obj)
            {
                if ($global.isString(obj.style.opacity))
                    return Number(obj.style.opacity) * 100;
                else if ($global.isString(obj.style.filter))
                    return Number(obj.style.filter.replace("alpha(opacity=", "").replace(")", ""));
                else if ($global.isString(obj.style.MozOpacity))
                    return Number(obj.style.MozOpacity) * 100;
                else if ($global.isString(obj.style.KhtmlOpacity))
                    return Number(obj.style.KhtmlOpacity) * 100;
            }
        }
    },
    GetCharPosition: function(str, chr, pos, up)
    {
        if (!up)
        {
            for (var i = pos; i >= chr.length; i--)
                if (str.substring(i - chr.length, i) == chr)
                return Number(i - chr.length);
            return -1;
        }
        else
        {
            for (var i = pos; i < str.length; i++)
                if (str.substring(i, i + chr.length) == chr)
                return i;
            return str.length;
        }
    },
    Selection:
    {
        Disable: function(target)
        {
            if (typeof target.onselectstart != "undefined") //IE
                target.onselectstart = function() { return false };
            else if (typeof target.style.MozUserSelect != "undefined") //Firefox
                target.style.MozUserSelect = "none";
            else //Другие
                target.onmousedown = function() { return false };
            target.style.cursor = "default";
        },
        Enable: function(target)
        {
            if (typeof target.onselectstart != "undefined") //IE
                target.onselectstart = function() { };
            else if (typeof target.style.MozUserSelect != "undefined") //Firefox
                target.style.MozUserSelect = "";
            else //Другие
                target.onmousedown = function() { };
            target.style.cursor = "";
        },
        LookUpType: { Forward: 0, Back: 1, BackForward: 2 },
        Look: function(o, sep, type)
        {
            var sel = $global.Selection.Start(o);
            var result = { value: "", back: "", forward: "", start: -1, end: -1 };
            if (sel > 0)
            {
                var value = o.GetText ? o.GetText : o.value;
                if (value)
                {
                    var _backSub = value.substring(0, sel);
                    var _back = "";
                    if (_backSub && (type == 1 || type == 2))
                    {
                        var i = _backSub.lastIndexOf(sep) >= 0 ? _backSub.lastIndexOf(sep) : 0;
                        _back = _backSub.substring(i, _backSub.length);
                        _back = _back.replace(sep, "");
                    }
                    var _forwardSub = value.substring(sel, value.length);
                    var _forward = "";
                    if (_forwardSub && (type == 0 || type == 2))
                    {
                        var i = (_forwardSub.indexOf(sep) >= 0 && _forwardSub.indexOf(sep) < _forwardSub.length) ? _forwardSub.indexOf(sep) : _forwardSub.length;
                        _forward = _forwardSub.substring(0, i);
                    }

                    result.value = _back + _forward;
                    result.back = _back;
                    result.forward = _forward;
                    result.start = sel - _back.length;
                    result.end = sel + _forward.length;
                }
            }
            return result;
        },
        Start: function(o)
        {
            if (o.createTextRange)
            {

                o.focus();
                var r = document.selection.createRange();
                r.moveStart('character', -o.value.length);
                return r.text.length;

            }
            else
                return o.selectionStart
        },
        End: function(o)
        {
            if (o.createTextRange)
            {
                o.focus();
                var r = document.selection.createRange();
                r.moveStart('character', -o.value.length);
                return r.text.length;
            }
            else
                return o.selectionEnd;
        },
        Set: function(o, start, end)
        {
            if (o.createTextRange)
            {
                var r = o.createTextRange();
                r.select();
                r.moveStart('character', start);
                r.moveEnd('character', -(r.text.length - end + start));
                r.select();
            }
            else
            {
                o.setSelectionRange(start, end);
            }
        }
    },
    GetClear: function()
    {
        var clear = document.createElement("div");
        clear.className = "clear";
        return clear;
    },
    Window:
	{
	    _defaultWindowTitle: "",
	    _titleSpliter: " - ",
	    SetTitle: function(texts, splitter)
	    {
	        if (splitter)
	            $global.Window._titleSpliter = splitter;

	        document.title = this._defaultWindowTitle;
	        if ($G.isString(texts))
	        {
	            if (texts)
	                document.title += texts;
	        }
	        else
	            document.title = texts.join(this._titleSpliter);
	    },
	    Size: function(axis)
	    {
	        var x, y;
	        if (self.innerHeight)
	        {
	            x = self.innerWidth;
	            y = self.innerHeight;
	        }
	        else if (document.documentElement && document.documentElement.clientHeight)
	        {
	            x = document.documentElement.clientWidth;
	            y = document.documentElement.clientHeight;
	        }
	        else if (document.body)
	        {
	            x = document.body.clientWidth;
	            y = document.body.clientHeight;
	        }
	        return (axis == "x") ? x : (axis == "y") ? y : 0;
	    },
	    Width: function()
	    {
	        return Number(this.Size("x"));
	    },
	    Height: function()
	    {
	        return Number(this.Size("y"));
	    },
	    Scroll:
	    {
	        Left: function()
	        {
	            var res = 0;
	            if (document.documentElement)
	                res = document.documentElement.scrollLeft;
	            else
	                res = document.body.scrollLeft;
	            if (res == 0)
	                return document.body.scrollLeft || 0;
	            else
	                return res;
	        },
	        Top: function()
	        {
	            var res = 0;
	            if (document.documentElement)
	                res = document.documentElement.scrollTop;
	            else
	                res = document.body.scrollTop;
	            if (res == 0)
	                return document.body.scrollTop || 0;
	            else
	                return res;
	        }
	    }
	},
    IsChildOf: function(par, child, depth)
    {
        if (child)
        {
            //alert(child);
            var o = child.parentNode;
            for (var i = 0; i < depth; i++)
            {
                if (o == null)
                    return false;
                if (o == par)
                    return true;
                o = o.parentNode;
            }
        }
        return false;
    },
    Number:
	{
	    is2N: function(value)
	    {
	        return value % 2 == 0;
	    },
	    Decade: function(value, o)
	    {
	        o = o || 10;
	        return Math.floor(value / o) * o;
	    },
	    toHex: function(value)
	    {
	        return value.toString(16);
	    },
	    toDec: function(value)
	    {
	        return parseInt(value, 16);
	    },
	    hexToColor: function(hex)
	    {
	        return "#" + this.Norm(hex, 6);
	    },
	    decToColor: function(dec)
	    {
	        return $global.Number.hexToColor($global.Number.toHex(dec));
	    },
	    colorToHex: function(color)
	    {
	        return color.replace("#", "");
	    },
	    colorToDec: function(color)
	    {
	        return $global.Number.toDec($global.Number.colorToHex(color));
	    },
	    toHexRGB: function(color)
	    {
	        //alert(color.substr(1,2)+":"+color.substr(3,2)+":"+color.substr(5,2));
	        return { r: color.substr(1, 2), g: color.substr(3, 2), b: color.substr(5, 2) };
	    },
	    toDecRGB: function(color)
	    {
	        var _rbg = $global.Number.toHexRGB(color);
	        _rbg.r = $global.Number.toDec(_rbg.r);
	        _rbg.g = $global.Number.toDec(_rbg.g);
	        _rbg.b = $global.Number.toDec(_rbg.b);
	        return _rbg;
	    },
	    Norm: function(num, c)
	    {
	        var a = num.toString();
	        var _c = c == null ? 2 : c;
	        while (a.length < _c)
	            a = "0" + a;
	        return a;
	    }
	},
    Color:
	{
	    Plus: function(c1, c0)
	    {
	        var _c = { r: c1.r + c0.r, g: c1.g + c0.g, b: c1.b + c0.b };
	        return _c;
	    },
	    Minus: function(c1, c0)
	    {
	        var _c = { r: c1.r - c0.r, g: c1.g - c0.g, b: c1.b - c0.b };
	        return _c;
	    },
	    Mult: function(c1, c0)
	    {
	        var _c1 = c1;
	        if ($global.IsNumber(c1))
	            _c1 = { r: _c1, g: _c1, b: _c1 };
	        var _c0 = c0;
	        if ($global.IsNumber(c0))
	            _c0 = { r: _c0, g: _c0, b: _c0 };
	        return { r: Math.round(_c0.r * _c1.r), g: Math.round(_c0.g * _c1.g), b: Math.round(_c0.b * _c1.b) };
	    },
	    fromRGB: function(rgb)
	    {
	        return "#" + $global.Number.Norm($global.Number.toHex(rgb.r)) + $global.Number.Norm($global.Number.toHex(rgb.g)) + $global.Number.Norm($global.Number.toHex(rgb.b));
	    }
	},
    Tag: function(tag, css, id, inner, other)
    {
        var element = document.createElement(tag);
        if (element)
        {
            if ($global.IsString(css))
                element.className = css;
            if ($global.IsString(id))
                element.id = id;
            if ($global.IsString(inner))
                element.innerHTML = inner;

            var _other = other ? other
                               : ($global.IsString(css) == false && css != null) ? css
                               : ($global.IsString(id) == false && id != null) ? id
                               : ($global.IsString(inner) == false && inner != null) ? inner
                               : null;
            if (_other)
            {
                if (_other.style)
                    for (var selector in _other.style)
                    if (!Function.prototype.isPrototypeOf(_other.style[selector]))
                    $global.SetStyle(selector, _other.style[selector], element);
                $global.Extend(element, _other, "");
            }
        }
        return element;
    },
    CutLastSeperator: function(str, sep)
    {
        if (str.lastIndexOf(sep) == str.length - sep.length)
            return str.substr(0, str.length - sep.length);
        return str;
    },
    TagToString: function(tag)
    {
        return $G.Append($G.Tag("div"), tag.cloneNode(true)).parentNode.innerHTML;
    },
    AddText: function(to, text)
    {
        var _t = document.createTextNode(text);
        to.appendChild(_t);
        return to;
    },
    Append: function(to, what, anchor, before)
    {
        var _to = to;
        var _what = what;
        var _anchor = anchor;
        if (window["A2"])
        {
            _to = A2.UI.Control.prototype.isPrototypeOf(to) ? to.Content : to;
            _what = A2.UI.Control.prototype.isPrototypeOf(what) ? what.Holder : what;
            _anchor = A2.UI.Control.prototype.isPrototypeOf(anchor) ? anchor.Holder : anchor;
        }
        if (anchor)
        {
            if (before)
                _to.insertBefore(_what, _anchor);
            else
                if (_anchor.nextSibling)
                _to.insertBefore(_what, _anchor.nextSibling)
            else
                _to.appendChild(_what);
        }
        else
            _to.appendChild(_what);
        return what;
    },
    Get:
	{
	    ById: function(id)
	    {
	        return document.getElementById(id);
	    },
	    ByTag: function(obj, tag, global)
	    {
	        return $global.GetElementsByTagName(obj, tag, global);
	    },
	    ByClass: function(obj, css, index)
	    {
	        var elements = $global.GetElementsByClass(obj, css);
	        if (index == null)
	            return elements;
	        else
	        {
	            if (elements && elements.length > index)
	                return elements[index];
	        }
	    },
	    ByAttribute: function(obj, attr, value, index)
	    {
	        var elements = $global.RemoveEmptyNodes(obj.childNodes);
	        var result = [];
	        for (var i = 0; i < elements.length; i++)
	            if (elements[i].getAttribute(attr) == value)
	            result.push(elements[i]);
	        if (index == null)
	            return result;
	        else
	        {
	            if (result && result.length > index)
	                return result[index];
	        }
	        return null;
	    }
	},
    GetElementsByTagName: function(obj, tag, global)
    {
        var result = new Array();
        if (obj != null)
        {
            if (tag != null)
            {
                if (window["A2"] && A2.UI.Control.prototype.isPrototypeOf(obj))
                    obj = obj.Holder;
                for (var i = 0; i < obj.childNodes.length; i++)
                {
                    var _elem = obj.childNodes[i];
                    if (_elem.tagName)
                    {
                        if (_elem.tagName.toLowerCase() == tag.toLowerCase())
                        {
                            result.push(_elem);
                        }
                        if (global)
                        {
                            var _tmp = $global.Get.ByTag(_elem, tag, true);
                            result = result.concat(_tmp);
                        }
                    }
                }
            }
        }
        return result;
    },
    RemoveEmptyNodes: function(array)
    {
        var tmp = new Array();
        for (var i = 0; i < array.length; i++)
            if (array[i].nodeType != 3)
            tmp.push(array[i]);
        return tmp;
    },
    GetElementByTagName: function(obj, tag, index)
    {
        var result = null;
        var array = $global.GetElementsByTagName(obj, tag);
        if (array.length > 0)
        {
            var tmp = this.RemoveEmptyNodes(array);
            if (index != null)
            {
                var ind = index == $global.GetConst.First ? 0 : index == $global.GetConst.Last ? (tmp.length - 1) : Number(index);
                if (ind < tmp.length)
                {
                    result = tmp[ind];
                } else { result = tmp[0]; }
            } else { result = tmp[0]; }
        }
        return result;
    },
    GetElementsByClass: function(obj, className)
    {
        var result = new Array();
        if (obj)
        {
            if (obj.childNodes != null)
            {
                for (var i = 0; i < obj.childNodes.length; i++)
                {
                    if (obj.childNodes[i] != null && obj.childNodes[i].nodeType != 3)
                    {
                        if (obj.childNodes[i].className != null)
                            if (obj.childNodes[i].className == className)
                            result.push(obj.childNodes[i]);
                        if (obj.childNodes[i].childNodes)
                            result = result.concat($global.GetElementsByClass(obj.childNodes[i], className));
                    }
                }
            }
        }
        return result;
    },
    GET: function(obj, path) // Получает элемент по строке вида "<param>:<value>,<param>:<value>" например "up:3,div:0"
    {
        path = $global.isString(obj) ? obj : path;
        obj = $global.isString(obj) ? document.body : obj;
        var result = obj;
        var str = path = path || "";
        if (obj)
        {
            var strArray = $G.Is(str, Array) ? str : str.split(',');
            for (var i = 0; i < strArray.length; i++)
            {
                var pair = $G.Is(str, Array) ? strArray[i] : strArray[i].split(':');
                if (pair.length == 3)
                {
                    if (pair[0].indexOf("@") == 0)
                        result = $global.Get.ByAttribute(result, pair[0].substring(1, pair[0].length), pair[1], Number(pair[2]));
                }
                else if (pair.length == 2)
                {
                    if (pair[0] == $global.GetConst.Up)
                        result = $global.GetParent(result, Number(pair[1]));
                    else if (pair[0] == $global.GetConst.Next)
                        result = $global.Next(result, Number(pair[1]));
                    else if (pair[0] == $global.GetConst.Previous)
                        result = $global.Previous(result, Number(pair[1]));
                    else if (pair[0].indexOf(".") == 0)
                        result = $global.Get.ByClass(result, pair[0].substring(1, pair[0].length), Number(pair[1]));
                    else if (pair[0].indexOf("@") == 0)
                        result = $global.Get.ByAttribute(result, pair[0].substring(1, pair[0].length), pair[1], 0);
                    else
                    {
                        var _tag = pair[0];
                        if (_tag.substr(_tag.length - 1, 1) == "s")
                        {
                            result = $global.GetElementsByTagName(result, _tag.substr(0, _tag.length - 1));
                        }
                        else
                        {
                            result = $global.GetElementByTagName(result, pair[0], pair[1]);
                        }
                        _tag = null;
                    }
                }
                else if (pair.length == 1)
                {
                    if (pair[0] == $global.GetConst.Up)
                        result = $global.GetParent(result, 1);
                    else if (pair[0] == $global.GetConst.Next)
                        result = $global.Next(result, 1);
                    else if (pair[0] == $global.GetConst.Previous)
                        result = $global.Previous(result, 1);
                    else if (pair[0].indexOf("#") == 0)
                        result = $global.Get.ById(pair[0].substring(1, pair[0].length));
                    else if (pair[0].indexOf(".") == 0)
                        result = $global.Get.ByClass(result, pair[0].substring(1, pair[0].length), 0);
                    else
                    {
                        var _tag = pair[0];
                        if (Number(_tag).toString() == _tag || _tag == "last")
                        {
                            var _num = Number(_tag);
                            if (result.childNodes)
                            {
                                var _nodes = $global.RemoveEmptyNodes(result.childNodes);
                                if (_tag == "last")
                                    _num = _nodes.length - 1;
                                _num = _num > 0 ? _num : 0;
                                if (_nodes.length > _num)
                                    result = _nodes[_num];
                                _nodes = null;
                            }
                            _num = null;
                        }
                        else if (_tag.substr(_tag.length - 1, 1) == "s")
                        {
                            result = $global.GetElementsByTagName(result, _tag.substr(0, _tag.length - 1));
                        }
                        else
                        {
                            result = $global.GetElementByTagName(result, pair[0], pair[1]);
                        }
                        _tag = null;
                    }
                }
                pair = null;
            }
            strArray = null;
        }
        return result;
    },
    CssFix:
    {
        //Взято с хабра
        GetBrowser: function()
        {
            return document.getElementsByTagName('html')[0].className;
        },
        Init: function()
        {
            var u = navigator.userAgent.toLowerCase();
            var is = function(t) { return (u.indexOf(t) != -1); };
            var env = [
                (/msie (\d)/.test(u) && navigator.userAgent.indexOf("Opera") == -1)
                    ? ('ie ie' + RegExp.$1)
                    : is('firefox/2')
                        ? 'gecko ff2'
                        : is('firefox/3')
                            ? 'gecko ff3'
                            : is('gecko/')
                                ? 'gecko'
                                : is('opera/9')
                                    ? 'opera opera9'
                                    : /opera (\d)/.test(u)
                                        ? 'opera opera' + RegExp.$1
                                        : is('konqueror')
                                            ? 'konqueror'
                                            : is('applewebkit/')
                                                ? 'webkit safari'
                                                : is('mozilla/')
                                                    ? 'gecko'
                                                    : '',
                (is('x11') || is('linux'))
                    ? ' linux'
                    : is('mac')
                        ? ' mac'
                        : is('win')
                        ? ' win'
                        : ''
          ].join(" ");
            $global.ClassName.Replace(document.getElementsByTagName('html')[0], env, env);
            env = env.split(" ");
            for (var i = 0; i < env.length; i++)
            {
                $global.Browser.Detect[env[i]] = true;
            }
        }
    },
    _browser: null,
    Browser:
	{
	    Detect: {}
	},
    Array:
	{
	    SortNumbersASC: function(a, b) { return a - b; },
	    SortNumbersDESC: function(a, b) { return b - a; },
	    Shuffle: function(a, b) { return (0.5 - Math.random()); }
	}
}

var $G = $global; //Алиас для $global
$G._old = window.onload;
window.onload = function()
{
    if ($G._old)
        $G._old();
    $global.InitEvents();
};
// Date extension methods by Sergey.ro
// Возвращают новый объект с датой :)
Date.isLeapYear = function(year)
{
    if (isNaN(year) || year < 1 || year > 9999)
        throw new Error("year");

    return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
};
Date.daysInMonth = function(year, month)
{
    var daysNonLeap = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    var daysLeap = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    if (isNaN(year) || year < 1 || year > 9999)
        throw new Error("year");
    if (isNaN(month) || month < 0 || month > 11)
        throw new Error("month");

    return (Date.isLeapYear(year) ? daysLeap[month] : daysNonLeap[month]);
};
Date.prototype.addMilliseconds = function(value)
{
    if (isNaN(value))
        throw new Error("value must be a Number");

    return new Date(this.getTime() + value);
};
Date.prototype.addSeconds = function(value)
{
    return this.addMilliseconds(value * 1000);
};
Date.prototype.addMinutes = function(value)
{
    return this.addSeconds(value * 60);
};
Date.prototype.addHours = function(value)
{
    return this.addMinutes(value * 60);
};
Date.prototype.addDays = function(value)
{
    return this.addHours(value * 24);
};
Date.prototype.addMonths = function(value)
{
    if (isNaN(value))
        throw new Error("value must be a Number");

    var date = new Date();
    var day = this.getDate();
    var month = this.getMonth() + parseInt(value % 12, 10);
    var year = this.getFullYear() + parseInt(value / 12, 10);

    if (month < 0)
    {
        month = 12 + month;
        year--;
    }
    else if (month > 11)
    {
        month = month - 12;
        year++;
    }

    var maxday = Date.daysInMonth(year, month);

    if (day > maxday)
        day = maxday;

    date.setTime(this.getTime());
    date.setFullYear(year);
    date.setMonth(month);
    date.setDate(day);

    return date;
};
Date.prototype.addYears = function(value)
{
    return this.addMonths(value * 12);
};
Date.prototype.date = function()
{
    var d = new Date();

    d.setFullYear(this.getFullYear());
    d.setMonth(this.getMonth());
    d.setDate(this.getDate());

    d.setHours(0);
    d.setMinutes(0);
    d.setSeconds(0);
    d.setMilliseconds(0);

    return d;
};
// закончили упражнение
Function.prototype.bind = function(obj)
{
    var method = this,
	temp = function()
	{
	    return method.apply(obj, arguments);
	};
    return temp;
}
Function.prototype.toNamespace = function(scope, name)
{
    scope[name] = this;
}
Array.prototype.contains = function(value)
{
    return $G.ValueInArray(this, value);
};
Array.prototype.remove = function(value)
{
    for (var i = 0; i < this.length; i++)
        if (this[i] == value)
        this.splice(i, 1);
}
Array.prototype.xjoin = function(sep, prop)
{
    var str = "";
    for (var i = 0; i < this.length; i++)
    {
        var props = prop.split(".");
        var v = null;
        for (var j = 0; j < props.length; j++)
        {
            if (v == null)
                v = this[i][props[j]];
            else
                v = v[props[j]];
            if (Function.prototype.isPrototypeOf(v))
                v = v();
            if (v == null)
                break;
        }
        if (v != null)
            str += v + ((i == this.length - 1) ? "" : sep);
    }
    return str;
}
Array.prototype.foreach = function(func)
{
    if (func)
    {
        for (var i = 0; i < this.length; i++)
        {
            func(this[i], i);
        }
    }
}
Array.prototype.without = function(arr)
{
    var ret = new Array();
    var _arr = Array.prototype.isPrototypeOf(arr) ? arr : [arr];
    for (var i = 0; i < this.length; i++)
        if (!_arr.contains(this[i]))
        ret.push(this[i]);
    return ret;
}
Array.prototype.indexOf = function(item)
{
    for (var i = 0; i < this.length; ++i)
        if (this[i] == item)
        return i;

    return -1;
};
String.prototype.trim = function()
{
    return this.replace(/^\s+|\s+$/gi, "");
}
String.prototype.despace = function()
{
    return this.replace(/\s+/gi, " ").trim();
}
String.prototype.xmlEncode = function()
{
    return $G.HTML.Encode($G.HTML.EnQuote($G.HTML.EnAmp(this)));
}
String.prototype.xmlDecode = function()
{
    return $G.HTML.DeAmp($G.HTML.DeQuote($G.HTML.Decode(this)));
}
function rgb(r, g, b)
{
    return $G.Color.fromRGB({ r: r, g: g, b: b });
}