﻿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) {
        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;
    },
    Sprite: function (obj, sprite, x, y, w, h) {
        if (obj) {
            if ($G.Is(obj, $ctrl)) return $global.Sprite(obj.Holder, sprite, x, y, w, h);
            if (obj.tagName.toString().toLowerCase() == "img") { obj.src = A2.UI.Url + $ResourceManager.PxGif; }
            obj.style.background = "url(" + sprite + ") no-repeat -" + (x || "0") + "px -" + (y || "0") + "px";
            if (w) obj.style.width = w + "px";
            if (h) obj.style.height = h + "px";
        }
    },
    Extend: function (obj, eobj, prefix) {
        for (var _prop in eobj) { if (_prop != "style") obj[(prefix || "") + _prop] = eobj[_prop]; } return obj;
    },
    ExtendPrivate: function (obj, eobj) {
        return $G.Extend(obj, eobj, "_");
    },
    Convert: function (obj, scheme) {
        if (obj && scheme) {
            var arr = $G.Is(obj, Array) ? obj : [obj];
            var _arr = [];
            for (var a = 0; a < arr.length; a++) {
                var __obj = arr[a];
                var _obj = {};
                for (var i in scheme) {
                    if (__obj[scheme[i]] != null) {
                        _obj[i] = __obj[scheme[i]];
                    }
                }
                _arr.push(_obj);
            }
            if ($G.Is(obj, Array))
                return _arr;
            else
                return _arr[0];
        }
        return obj;
    },
    Extract: function (obj, props, props2) {
        if (obj) {
            if ($global.Is(obj, Array)) {
                var a = []; for (var i = 0; i < obj.length; i++) { a.push($global.Extract(obj[i], props, props2)); }
                return a;
            }
            var a = {};
            for (var i = 0; i < props.length; i++) { if (obj[props[i]] != null) { a[props2[i]] = obj[props[i]]; } }
            return a;
        }
        return null;
    },
    ExtractPrivate: function (obj) {
        if (obj) {
            var props = [];
            var props2 = [];
            for (var i in obj) { if (i.length > 1 || i.toString().indexOf("_") == 0) { props.push(i); props2.push(i.substring(1, i.length)); } }
            return $global.Extract(obj, props, props2);
        }
        return null;
    },
    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, d) {
            if (!str || !d)
                return "";
            if (!$G.Is(d, Date))
                return d;
            var nrm = $G.Number.Norm;
            var gd = $G.Date;
            return str.replace(/dddd/gi, gd.DaysOfWeek[d.getDay()])
                      .replace(/ddd/gi, gd.DaysOfWeekShort[d.getDay()])
                      .replace(/dd/gi, nrm(d.getDate(), 2))
                      .replace(/d/gi, nrm(d.getDate(), 1))
                      .replace(/^MMMM/g, gd.MonthEntity[d.getMonth() + 1])
                      .replace(/MMMM/g, gd.Month[d.getMonth() + 1])
                      .replace(/MMM/g, gd.ShortMonth[d.getMonth() + 1])
                      .replace(/MM/g, nrm(d.getMonth() + 1, 2))
                      .replace(/M/g, nrm(d.getMonth() + 1, 1))
                      .replace(/yyyy/gi, $G.Number.Norm(d.getFullYear(), 4))
                      .replace(/yy/gi, d.getFullYear().toString().substring(2, 4))
                      .replace(/mm/g, nrm(d.getMinutes(), 2))
                      .replace(/m/g, d.getMinutes().toString())
                      .replace(/HH/g, nrm(d.getHours(), 2))
                      .replace(/H/g, nrm(d.getHours(), 1))
                      .replace(/hh/g, nrm(gd.ShortHours(d), 2))
                      .replace(/h/g, nrm(gd.ShortHours(d), 1))
                      .replace(/ss/g, nrm(d.getSeconds(), 2))
                      .replace(/s/g, nrm(d.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 (d1, d2) {
            return ((d1.getFullYear() == d2.getFullYear()) &
                    (d1.getMonth() == d2.getMonth()) &
                    (d1.getDate() == d2.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;
    },
    SwapClasses: function (class1, class2, obj) {
        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);
    },
    SwapVisibility: function (obj) {
        this.Display.Swap(obj, "none", "block");
    },
    Cookie:
    {
        Set: function (name, value, days, path, domain, secure) {
            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) {
            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) {
            if (obj) {
                obj.style.display = obj.style.display == value1 ? value2 : value1;
            }
        },
        Clear: function () {
            for (var i = 0; i < arguments.length; i++) {
                var obj = arguments[i];
                if (obj) {
                    var _obj = obj;

                    if (window["$ctrl"])
                        if ($ctrl.prototype.isPrototypeOf(obj))
                            _obj = obj.Holder;
                    _obj.style.display = "";
                }
            }
        },
        Block: function () {
            for (var i = 0; i < arguments.length; i++) {
                var obj = arguments[i];
                if (obj) {
                    var _obj = obj;

                    if (window["$ctrl"])
                        if ($ctrl.prototype.isPrototypeOf(obj))
                            _obj = obj.Holder;
                    _obj.style.display = "block";
                }
            }
        },
        Inline: function () {
            for (var i = 0; i < arguments.length; i++) {
                var obj = arguments[i];
                if (obj) {
                    var _obj = obj;

                    if (window["$ctrl"])
                        if ($ctrl.prototype.isPrototypeOf(obj))
                            _obj = obj.Holder;
                    _obj.style.display = "inline";
                }
            }
        },
        Hide: function () {
            for (var i = 0; i < arguments.length; i++) {
                var obj = arguments[i];
                if (obj) {
                    var _obj = obj;

                    if (window["$ctrl"])
                        if ($ctrl.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) {
        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;
    },
    GetAttrText: function (html) {
        var tag = /\<[^\>]*>/gi;

        var d = document.createElement("div");
        d.innerHTML = html;
        return (d.innerText || d.textContent || "").replace(tag, "").replace(/\"/gi, "\\\"").replace(/\'/gi, "\\'");
    },
    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) {
        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] };
    },
    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, ox, oy) {
        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 + (oy || 0)) > 0) ? (Math.floor(_centerH - _deltaY + (oy || 0)) + "px") : "0px";
            obj.style.left = ((_centerW - _deltaX + (ox || 0)) > 0) ? (Math.floor(_centerW - _deltaX + (ox || 0)) + "px") : "0px";
            $global.Display.Block(obj);
        }
    },
    ShowInPageCenter: function (obj, ox, oy) {
        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, ox, oy);
        }
    },
    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);
        };
        $G.CssFix.Init();
    },
    GetKeyCode: function (e) {
        var e = e ? e : window.event;
        if ($G.Browser.Detect.ie8)
            e = 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, key);
	        }
	        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;
	        if ($G.Browser.Detect.ie8)
	            e = event;
	        return e.target ? e.target : e.srcElement;
	    },
	    Button: function (e) {
	        var e = e ? e : event;
	        if ($G.Browser.Detect.ie8)
	            e = event;
	        return e.button ? e.button : e.which;
	    },
	    IsCapsLock: function (e) {
	        var ev = e ? e : window.event;
	        if (!ev) {
	            return;
	        }
	        var which = $G.Event.KeyCode(e);
	        // get shift status
	        var shift_status = false;
	        if (ev.shiftKey) {
	            shift_status = ev.shiftKey;
	        } else if (ev.modifiers) {
	            shift_status = !!(ev.modifiers & 4);
	        }
	        if (((which >= 65 && which <= 90) && !shift_status) || ((which >= 97 && which <= 122) && shift_status)) {
	            return true;
	        } else {
	            return false;
	        }
	    }
	},
    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) {
        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;
    },
    Str:
    {
        FirstBig: function (str) {
            return str.substring(0, 1).toUpperCase() + str.substring(1, str.length);
        },
        Shrink: function (str, chars, last, empty) {
            return str.length > chars ? str.substring(0, chars) + last : str.length == 0 ? empty : str;
        },
        SmartShrink: 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;
        },
        ShrinkLines: function (str, lines, inline, last, empty) {
            if (!str || !str.trim())
                return empty || "";
            var str = str.replace(/\<br\s*\/\>/gi, "<br />");
            var strs = str.split("<br />");
            var result = [];
            for (var i = 0; i < strs.length; i++) {
                if (strs[i].length < inline)
                    result.push({ str: strs[i], br: i != strs.length - 1 });
                else {
                    var tmp = strs[i];
                    do {
                        var s = tmp;
                        if (inline < tmp.length)
                            s = s.substr(0, inline);
                        result.push({ str: s, br: false });
                        if (result.length == lines) {
                            result[result.length - 1].str = $global.SmartShrinkStr(tmp, inline, last, "");
                            if (result[result.length - 1].str.indexOf(" ") != -1) {
                                result[result.length - 1].str = result[result.length - 1].str.substring(0, result[result.length - 1].str.lastIndexOf(" ")) + (last || "");
                            }
                        }
                        if (inline >= tmp.length)
                            tmp = "";
                        else
                            tmp = tmp.substring(inline, tmp.length - 1);
                        s = null;
                    }
                    while (tmp.length > 0)
                    tmp = null;
                }
            }
            var res = "";
            if (result.length <= lines)
                return str;
            for (var i = 0; i < lines; i++) {
                res += result[i].str + (result[i].br ? "<br />" : "");
            }
            str = strs = result = null;
            return res;
        }
    },
    ShrinkStr: function (str, chars, last, empty) {
        return $global.Str.Shrink(str, chars, last, empty);
    },
    SmartShrinkStr: function (str, chars, last, empty) {
        return $global.Str.SmartShrink(str, chars, last, empty);
    },
    ShrinkLinesStr: function (str, lines, inline, last, empty) {
        return $global.Str.ShrinkLines(str, lines, inline, last, empty);
    },
    ClassName:
    {
        Replace: function (obj, cname1, cname2) {
            var cname1 = $global.IsString(cname1) ? [cname1] : cname1;
            var cname2 = $global.IsString(cname2) ? [cname2] : cname2;

            var obj = (window["$ctrl"] && $ctrl.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();
            return obj;
        },
        Has: function (obj, cname) {
            var cname = $global.IsString(cname) ? [cname] : cname;
            var obj = (window["$ctrl"] && $ctrl.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) {
        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) {
        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:
    {
        Transliterate: function (str) {
            var rus = ["а", "б", "в", "г", "д", "е", "ё", "ж", "з", "и", "й", "к", "л", "м", "н", "о", "п", "р", "с", "т", "у", "ф", "х", "ц", "ч", "ш", "щ", "ъ", "ы", "ь", "э", "ю", "я"];
            var eng = ["a", "b", "v", "g", "d", "e", "yo", "zh", "z", "i", "y", "k", "l", "m", "n", "o", "p", "r", "s", "t", "u", "f", "h", "ts", "ch", "sh", "sch", "", "i", "", "e", "yu", "ya"];
            var res = "";
            var str = str.replace(/ /gi, "_");
            var tran = {};
            var _rus = [];
            var _eng = [];
            for (var i = 0; i < rus.length; i++) {
                _rus.push(rus[i]);
                _rus.push(rus[i].toUpperCase());
                _eng.push(eng[i]);
                _eng.push(eng[i].substr(0, 1).toUpperCase() + eng[i].substr(1, eng[i].length - 1));
            }
            for (var i = 0; i < _rus.length; i++) {
                tran[_rus[i]] = _eng[i];
            }
            for (var i = 0; i < str.length; i++) {
                var c = str.substr(i, 1);
                if (tran[c] != null) {
                    res += tran[c];
                }
                else {
                    res += c;
                }
            }
            return res;
        },
        SendEncode: function (inner) {
            var encoded = $global.HTML.SEncode(inner);
            encoded = encoded.replace(/\&/gi, "%26");
            return encoded;
        },
        SEncode: 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);
                }
            }
            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]");
        },
        GetParamUrl: function (param, value, url) {
            var Url = url || document.location.toString(); ;
            if ($G.HTML.GETVars(param, Url)) {
                var ex = new RegExp(param + "=[\-\_0-9a-z]+", "gi");
                Url = Url.replace(ex, param + "=" + value);
            }
            else {
                if (Url.toString().indexOf("?") > 0) {
                    Url = Url + "&" + param + "=" + value;
                }
                else
                    Url = Url + "?" + param + "=" + value;
            }
            return Url;
        },
        GETVars: function (id, _url) {
            var url = _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;
        },
        GetPage: function () {
            var url = document.location.toString();
            if (url.indexOf("?") != -1) {
                url = url.substr(0, url.indexOf("?"));
            }
            if (url.lastIndexOf("/") != -1) {
                return url.substring(url.lastIndexOf("/") + 1, url.length);
            }
            else
                return url;
        },
        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) {
                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")
                target.onselectstart = function () { return false };
            else if (typeof target.style.MozUserSelect != "undefined")
                target.style.MozUserSelect = "none";
            else
                target.onmousedown = function () { return false };
            target.style.cursor = "default";
        },
        Enable: function (target) {
            if (typeof target.onselectstart != "undefined")
                target.onselectstart = function () { };
            else if (typeof target.style.MozUserSelect != "undefined")
                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) {
            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) {
	        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;
	    },
	    Format: function (number, constantPart, one, two, many) {
	        var abs = Math.abs(number);
	        if (abs > 100)
	            abs %= 100;

	        if ((abs == 1) || (abs > 20 && (abs % 10 == 1)))
	            return [constantPart, one].join("");
	        if ((abs > 1 && abs < 5) || (abs % 10 >= 2) && (abs % 10 <= 4) && (abs > 20))
	            return [constantPart, two].join("");

	        return [constantPart, many].join("");
	    },
	    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 = $ctrl.prototype.isPrototypeOf(to) ? to.Content : to;
            _what = $ctrl.prototype.isPrototypeOf(what) ? what.Holder : what;
            _anchor = $ctrl.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)/*$ctrl.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 ($G.ClassName.Has(obj.childNodes[i], 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) {
        if (!obj && !path)
            return $global.LastGot;
        path = ($global.isString(obj) || $G.Is(obj, Array)) ? obj : path;
        obj = ($global.isString(obj) || $G.Is(obj, Array)) ? 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(strArray[i], 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 {
                        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), 1);
                    else {
                        var _tag = pair[0];
                        if (Number(_tag).toString() == _tag || _tag == "last") {
                            var _num = Number(_tag);
                            if (result && 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];
                                else
                                    result = null;
                                _nodes = null;
                            }
                            else
                                result = 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;
        }
        $global.LastGot = result;
        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;
//$G._old = window.onload;
//window.onload = function () {
//    if ($G._old)
//        $G._old();
//    $global.InitEvents();
//};
addDOMLoadEvent = (function () {
    // create event function stack
    var load_events = [],
        load_timer,
        script,
        done,
        exec,
        old_onload,
        init = function () {
            done = true;

            // kill the timer
            clearInterval(load_timer);

            // execute each function in the stack in the order they were added
            while (exec = load_events.shift())
                exec();

            if (script) script.onreadystatechange = '';
        };

    return function (func) {
        // if the init function was already ran, just run this function now and stop
        if (done) return func();

        if (!load_events[0]) {
            // for Mozilla/Opera9
            if (document.addEventListener)
                document.addEventListener("DOMContentLoaded", init, false);

            // for Internet Explorer
            /*@cc_on@*/
            /*@if (@_win32)
            document.write("<script id=__ie_onload defer src=//0><\/scr" + "ipt>");
            script = document.getElementById("__ie_onload");
            script.onreadystatechange = function () {
                if (this.readyState == "complete")
                    init(); // call the onload handler
            };
            /*@end@*/

            // for Safari
            if (/WebKit/i.test(navigator.userAgent)) { // sniff
                load_timer = setInterval(function () {
                    if (/loaded|complete/.test(document.readyState))
                        init(); // call the onload handler
                }, 10);
            }

            // for other browsers set the window.onload, but also execute the old window.onload
            old_onload = window.onload;
            window.onload = function () {
                init();
                if (old_onload) old_onload();
            };
        }

        load_events.push(func);
    }
})();
addDOMLoadEvent($global.InitEvents);
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;
};
// закончили упражнение
Array.from = function (iterable) {
    if (!iterable) return [];
    if (iterable.toArray) {
        return iterable.toArray();
    } else {
        var results = [];
        for (var i = 0, length = iterable.length; i < length; i++)
            results.push(iterable[i]);
        return results;
    }
};
Function.prototype.bind = function (obj) {
    var method = this, args = Array.from(arguments), obj = args.shift();
    temp = function () {
        return method.apply(obj, args.concat(Array.from(arguments)));
    };
    return temp;
}
Function.prototype.toNamespace = function (scope, name) {
    scope[name] = this;
}
Array.prototype.unique = function () {
    var result = [];
    for (var i = 0; i < this.length; i++) {
        if (!result.contains(this[i]))
            result.push(this[i]);
    }
    return result;
}
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.getNonEmpty = function () {
    var _arr = [];
    for (var i = 0; i < this.length; i++) {
        if (this[i])
            _arr.push(this[i]);
    }
    return _arr;
}
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 });
}
