﻿/// <reference path="global.js" />
/// <reference path="effects.js" />
/// <reference path="UIElements.js" />
/// <reference path="nicEdit.js" />
A2.UI.DropDown = function(win)
{
    this.Controls = new Array();
    this.Holder = $G.Tag("div", "DDContainer");
    this.TitleContainer = $G.Append(this.Holder, $G.Tag("div", "dropdown"));
    this.Title = $G.Append(this.TitleContainer, $G.Tag("span", "JSdropdown"));
    this.Button = $G.Append(this.TitleContainer, $G.Tag("img", "dropDownImage", { src: A2.UI.Url + "resource/images/dropdown.gif", width: "16", height: "16" }));
    $G.Append(this.Holder, $G.Tag("div", "clear"));
    this.Content = $G.Append($UI.Body.Holder, $G.Tag("div", "DDItems" + (win ? " dddialog" : "")));
    this.SelectedItem = null;
    this.Window = win;
    this.SetTitle = function(title)
    {
        this.Title.innerHTML = title;
    }
    this.GetTitle = function()
    {
        return this.Title.innerHTML;
    }
    this.OnSelect = null;
    this.Select = function(item, noEvent)
    {
        if (item)
        {
            this.SelectedItem = item
            this.SetTitle(item.GetTitle());
            this.Collapse();
            if (!noEvent && this.OnSelect)
                this.OnSelect();
        }
    }
    this.Expand = function(bclick)
    {
        if (!bclick)
            this.Content.style.display = "block";
        var pos = $G.GetTopLeft(this.Holder);
        this.Content.style.zIndex = 99999;
        this.Content.style.left = pos.x + "px";
        this.Content.style.top = pos.y + this.Holder.offsetHeight - (this.Window ? this.Window.ScrollWraper.scrollTop : 0) + "px";
        this.Content.style.width = (this.Holder.offsetWidth - 5) + "px";
        if (!bclick)
        {              
            setTimeout(function()
            {
                document.body.onclick = function()
                {
                    if (this._bclick)
                        this._bclick();
                    this.Collapse();
                } .bind(this);
            } .bind(this), 10);
        }
        setTimeout(function()
        {
            if (this.Content.style.display == "block")
            {
                this.Expand(true);
            }
        } .bind(this), 50)
    }
    this._oldClick = null;
    this.Collapse = function()
    {
        this.Content.style.display = "none";
        if (this._bclick)
            document.body.onclick = this._bclick;
        else
            document.body.onclick = function() { };
    }
    this.Toggle = function()
    {
        if ($G.GetStyle(this.Content, "display") != "none")
            this.Collapse()
        else
            this.Expand();
    }
    this._blclick = document.body.onclick;
    this.OnLoad = function()
    {
        $G.Event.Add(this.TitleContainer, "click", this.Toggle.bind(this));
        this.Collapse();
    }
    this.OnParentDeleted = function()
    {
        if (this.Content.parentNode)
            this.Content.parentNode.removeChild(this.Content);
    }
}
A2.UI.DropDown.prototype = new A2.UI.Control();
A2.UI.SuggestList = function(list, ctrl, onChange, cssName)
{
    this.SelectedClass = "Selected";
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("div", "SuggestList");
    if (cssName)
        $G.ClassName.Replace(this.Holder, "", cssName);
    this.Holder.style.position = "absolute";
    this.Ctrl = ctrl;
    this.list = list || [];
    this.OnChange = (onChange || null);
    this.OnLoad = function()
    {
        this.Show(this.list);
        $UI.Hotkey.Register([$UI.Hotkey.Keys.ArrowDown], this.NavDown.bind(this), "SuggestNavDown");
        $UI.Hotkey.Register([$UI.Hotkey.Keys.ArrowUp], this.NavUp.bind(this), "SuggestNavUp");
        $UI.Hotkey.Register([$UI.Hotkey.Keys.Enter], function() { var sel = this.GetSelected(); if (sel) { sel.ClickCall(); } } .bind(this), "SuggestEnter");
    }
    this.OnUnload = function()
    {
        $UI.Hotkey.UnRegister([], "SuggestNavDown");
        $UI.Hotkey.UnRegister([], "SuggestNavUp");
        $UI.Hotkey.UnRegister([], "SuggestEnter");
    }
    this.GetSelected = function()
    {
        for (var i = 0; i < this.Controls.length; i++)
        {
            if ($G.ClassName.Has(this.Controls[i], this.SelectedClass))
                return this.Controls[i];
        }
        return null;
    }
    this.NavDown = function()
    {
        if (this.Controls.length > 0)
        {
            var current = this.GetSelected();
            var index = -1;
            if (current)
                index = current.Index;
            this.DeselectAll();
            if (this.Controls.length - 1 >= index + 1)
            {
                this.Select(this.Controls[index + 1]);
            }
        }
    }
    this.NavUp = function()
    {
        if (this.Controls.length > 0)
        {
            var current = this.GetSelected();
            var index = this.Controls.length;
            if (current)
                index = current.Index;
            this.DeselectAll();
            if (index > 0)
            {
                this.Select(this.Controls[index - 1]);
            }
        }
    }
    this.Select = function(ctrl)
    {
        $G.ClassName.Replace(ctrl, this.SelectedClass, this.SelectedClass);
    }
    this.Deselect = function(ctrl)
    {
        $G.ClassName.Replace(ctrl, this.SelectedClass, "");
    }
    this.DeselectAll = function()
    {
        for (var i = 0; i < this.Controls.length; i++)
        {
            this.Deselect(this.Controls[i]);
        }
    }
    this._oldClick = null;
    this._newClick = function()
    {
        this.Ctrl.currentSuggest = null;
        $UI.Body.RemoveControl(this);
        this._newClick = null;
    } .bind(this)
    this.Show = function(list)
    {
        this.ClearControls();
        for (var i = 0; i < list.length; i++)
        {
            var listitem = list[i];
            var _atext = $G.isString(listitem) ? listitem : listitem.Title ? listitem.Title : "<span class='Suggest_add'>" + listitem.first + "</span> " + listitem.second;
            var _aclass = i == 0 ? "first" : i == list.length - 1 ? "last" : "";
            var lnk = this.AddControl(new A2.UI.Control($G.Tag("a", _aclass, { href: "javascript:void(0)" }, _atext)));
            lnk["Index"] = i;
            lnk["ClickCall"] = function()
            {
                var text = this.GetText(); //.replace(/<span class=[\"\']?Suggest_add[\"\']?>/gi, "").replace(/<\/span>/gi, " г.,").despace();
                if (this.Parent.OnChange)
                    this.Parent.OnChange(text);
                else
                    this.Parent.Ctrl.SetText(text);
                this.Parent.Parent.RemoveControl(this.Parent);
            } .bind(lnk);
            $G.Event.Add(lnk, "click", lnk.ClickCall);
        }
        this._oldClick = document.body.onclick;
        document.body.onclick = function()
        {
            if (this && this._oldClick)
                this._oldClick();
            if (this && this._newClick)
                this._newClick();
        } .bind(this);
        $G.ShowUnderObject(this.Holder, this.Ctrl.Holder, false);
    }
}
A2.UI.SuggestList.prototype = new A2.UI.Control();
A2.UI.DDItem = function(title)
{
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("a", { href: "javascript:void(0)" });
    this.SetTitle = function(title) { this.Holder.innerHTML = title || ""; };
    this.GetTitle = function() { return this.Holder.innerHTML; };
    this.Select = function(noEvent)
    {
        if (this.Parent)
            this.Parent.Select(this, noEvent);
    }
    this.OnLoad = function()
    {
        $G.Event.Add(this, "click", this.Select.bind(this));
    }
    if (title)
        this.SetTitle(title);
}
A2.UI.DDItem.prototype = new A2.UI.Control();
A2.UI.DialogRow = function(title, description)
{
    this.Controls = new Array();
    this.Holder = $G.Tag("div", "UIRow");
    this.Left = $G.Append(this.Holder, $G.Tag("div", "Left"));
    this.Content = $G.Append(this.Holder, $G.Tag("div", "Right"));
    this.Title = $G.Append(this.Left, $G.Tag("label", null, null, (title || "Заголовок")));
    this.Description = $G.Append(this.Left, $G.Tag("span", null, null, (description || "")));
    $G.Append(this.Holder, $G.Tag("div", "clear"));
    this.SetTitle = function(title)
    {
        this.Title.innerHTML = title || "Заголовок";
    }
    this.GetTitle = function()
    {
        return this.Title.innerHTML;
    }
    this.SetDescription = function(descr)
    {
        this.Description.innerHTML = descr || "";
    }
    this.OnLoad = function()
    {
        this.Fix();
    }
    this.OnChildAdded = function()
    {
        this.Fix();
    }
    this.Fix = function()
    {
        this.Content.style.height = "auto";
        if (this.Content.offsetHeight < this.Left.offsetHeight)
            this.Content.style.height = this.Left.offsetHeight + "px";
    }
}
A2.UI.DialogRow.prototype = new A2.UI.Control();
A2.UI.ToggleGroup = function(boxes)
{
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("div");
    this.CheckedItem = null;
    this.OnCheckedChanged = function() { };
    this.ListenChange = function(ctrl)
    {
        if (ctrl.Checked)
        {
            for (var i = 0; i < this.Controls.length; i++)
            {
                if (this.Controls[i] != ctrl)
                    this.Controls[i].DoUnCheck();
            }
            this.CheckedItem = ctrl;
            this.OnCheckedChanged();
        }
    }
    this.OnChildAdded = function(ctrl)
    {
        ctrl.OnCheckedChange = this.ListenChange.bind(this);
    }
    if (boxes)
    {
        for (var i = 0; i < boxes.length; i++)
        {
            if (boxes[i].title)
            {
                $G.Extend(this.AddControl(new A2.UI.CheckBox(boxes[i].title, false)), boxes[i], "");
            }
        }
    }
}
A2.UI.ToggleGroup.prototype = new A2.UI.Control();
A2.UI.CheckBox = function(title, checked)
{
    this.Controls = new Array();
    this.CheckedClassName = "Checked";
    this.UnCheckedClassName = "UnChecked";
    this.Holder = this.Content = $G.Tag("div", "UICheck");
    this.Toggle = this.AddControl(new A2.UI.Control($G.Tag("img", { src: A2.UI.Url + "resource/px.gif", width: 16, height: 16 })));
    this.Title = this.AddControl(new A2.UI.Control($G.Tag("span", null, null, (title || "чек бокс"))));
    this.OnLoad = function()
    {
        $G.Event.Add(this.Holder, "click", this.ToggleCheck.bind(this));
    }
    this.SetTitle = function(title)
    {
        if (title)
            this.Title.Holder.innerHTML = title;
    }
    this.GetTitle = function()
    {
        return this.Title.Holder.innerHTML;
    }
    this.Checked = !!checked;
    this.OnCheckedChange = function() { };
    this.ToggleCheck = function()
    {
        if (this.Checked)
            this.DoUnCheck();
        else
            this.DoCheck();
    }
    this.DoCheck = function()
    {
        this.Checked = true;
        $G.ClassName.Replace(this.Holder, this.UnCheckedClassName, this.CheckedClassName);
        this.OnCheckedChange(this);
    }
    this.DoUnCheck = function()
    {
        this.Checked = false;
        $G.ClassName.Replace(this.Holder, this.CheckedClassName, this.UnCheckedClassName);
        this.OnCheckedChange(this);
    }
    if (checked)
        this.DoCheck();
    else
        this.DoUnCheck();
}
A2.UI.CheckBox.prototype = new A2.UI.Control();
A2.UI.LabeledMarker = function(latlng, options)
{
    this.latlng = latlng;
    this.labelText = options.labelText || "";
    this.labelClass = options.labelClass || "markerLabel";
    this.labelOffset = options.labelOffset || new GSize(0, 0);
    google.maps.Marker.apply(this, arguments);
}
A2.UI.InitLabeledMarkerPrototype = function()
{
    A2.UI.LabeledMarker.prototype = new google.maps.Marker(new GLatLng(0, 0));
    A2.UI.LabeledMarker.prototype.initialize = function(map)
    {
        google.maps.Marker.prototype.initialize.call(this, map);
        var div = document.createElement("div");
        div.className = this.labelClass;
        div.innerHTML = this.labelText;
        div.style.position = "absolute";
        map.getPane(G_MAP_MARKER_PANE).appendChild(div);
        this.map = map;
        this.div = div;
    }
    A2.UI.LabeledMarker.prototype.redraw = function(force)
    {
        google.maps.Marker.prototype.redraw.call(this, map);
        if (!force) return;

        var p = this.map.fromLatLngToDivPixel(this.latlng);
        var z = google.maps.Overlay.getZIndex(this.latlng.lat());
        this.div.style.left = (p.x + this.labelOffset.width) + "px";
        this.div.style.top = (p.y + this.labelOffset.height) + "px";
        this.div.style.zIndex = z + 1;
    }
    A2.UI.LabeledMarker.prototype.drag = function()
    {
        google.maps.Maker.prototype.drag.call(this, map);

        var p = this.map.fromLatLngToDivPixel(this.latlng);
        var z = google.maps.Overlay.getZIndex(this.latlng.lat());
        this.div.style.left = (p.x + this.labelOffset.width) + "px";
        this.div.style.top = (p.y + this.labelOffset.height) + "px";
        this.div.style.zIndex = z + 1;
    }
    A2.UI.LabeledMarker.prototype.remove = function()
    {
        this.div.parentNode.removeChild(this.div);
        this.div = null;
        google.maps.Marker.prototype.remove.call(this);
    }
}
A2.UI.Map = function(state)
{
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("div", "UIMap");
    this.OnPreLoad = function() { };
    this.OnPostLoad = function() { };
    this.gMap = null;
    this.State = state || {};
    this.OnLoad = function()
    {
        if (this.OnPreLoad)
            this.OnPreLoad();
        if (google && google.maps)
            this.Construct();
        else
            google.load("maps", "2", { base_domain: "google.ru", language: "ru", "callback": this.Construct.bind(this) });
    }

    this.Construct = function()
    {
        A2.UI.InitLabeledMarkerPrototype();
        this.gMap = new google.maps.Map2(this.Content);
        google.maps.Event.addListener(this.gMap, "load", function()
        {
            if (this.State)
            {
                if (this.State.markers)
                {
                    for (var i = 0; i < this.State.markers.length; i++)
                    {
                        this.AddMarker(new google.maps.LatLng(this.State.markers[i].lat, this.State.markers[i].lng), A2.UI.Url + "resource/images/target.png", true);
                    }
                }
            }
            if (this.OnPostLoad)
                this.OnPostLoad();
        } .bind(this));
        if (this.State.Location)
        {
            this.SetLocation(new google.maps.LatLng(this.State.Location.lat, this.State.Location.lng), this.State.Location.zoom);
        }
        else
            this.SetLocation("Moscow", 9);
        this.gMap.addMapType(G_NORMAL_MAP);
        this.gMap.addMapType(G_SATELLITE_MAP);
        this.gMap.addMapType(G_HYBRID_MAP);
        this.gMap.addMapType(G_PHYSICAL_MAP);
        this.gMap.addControl(new google.maps.MapTypeControl());
        this.gMap.addControl(new google.maps.LargeMapControl());
    }
    this.Overlays = new Array();
    this.GetMapMarkerIcon = function(str)
    {
        var baseIcon = new google.maps.Icon();
        baseIcon.iconSize = new google.maps.Size(32, 32);
        baseIcon.image = str;
        baseIcon.iconAnchor = new google.maps.Point(15, 15);
        return baseIcon;
    },
    this.AddMarker = function(point, icon, drag)
    {
        var baseIcon = this.GetMapMarkerIcon(icon);
        var marker = new google.maps.Marker(point, { icon: baseIcon, draggable: drag });
        this.gMap.addOverlay(marker);
        this.Overlays.push(marker);
        return marker;
    },
    this.AddLabeledMarker = function(point, icon, text, css)
    {
        var baseIcon = this.GetMapMarkerIcon(icon);
        var marker = new A2.UI.LabeledMarker(point, { icon: baseIcon, draggable: false, labelText: text, labelClass: css });
        this.gMap.addOverlay(marker);
        this.Overlays.push(marker);
        return marker;
    },
    this.SetLocation = function(location, zoom)
    {
        var geocoder = new google.maps.ClientGeocoder();
        var _map = this.gMap;
        var _call = function(point)
        {
            if (point)
            {
                var _z = Number(zoom == null ? (_map.getZoom().toString() == "NaN") ? 10 : _map.getZoom() : zoom);
                _map.setCenter(point, _z);
            }
        }
        if (google.maps.LatLng.prototype.isPrototypeOf(location))
            _call(location);
        else
            geocoder.getLatLng(location, _call);
    }
}
A2.UI.Map.prototype = new A2.UI.Control();
A2.UI.Panel = function(title, width, height)
{
    this.Controls = new Array();
    this.SavedX = 0;
    this.SavedY = 0;
    this.Subject = null;
    this.Title = null;
    this.Content = null;
    this.ControlBox = null;
    this.FitDelta = 30;
    this.ScrollWraper = $G.Tag("div", "ScrollWrapper");

    this.Construct = function()
    {
        this.Holder = $G.Tag("div", "Dialog Static");
        this.Content = $G.Tag("div", "Content");
        this.PostConstruct();
        var drag = new A2.UI.SystemControl($G.Tag("div", "DragHandler"));
        this.Title = $G.Tag("h4", "Title");
        drag.Holder.appendChild(this.Title);
        this.AddControl(drag);
        $G.Append(this.Holder, this.ScrollWraper);
        $G.Append(this.ScrollWraper, this.Content);
    }
    this.FixContentHeight = function()
    {
        $G.SetStyle("height", ($G.GetStyle(this.Holder, "height", true) - this.FitDelta) + "px", this.ScrollWraper)
    }
    this.FitToContent = function()
    {
        var height = this.Content.offsetHeight;
        $G.SetStyle("height", (height + this.FitDelta) + "px", this.Holder);
        this.FixContentHeight();
        return this;
    }
    this.PostConstruct = function()
    {
        if (this.ControlBox == null)
        {
            this.ControlBox = new A2.UI.SystemControl();
            this.ControlBox.Holder = $G.Tag("div", "ControlBox");
            this.ControlBox.Content = this.ControlBox.Holder;
            var closeBtn = new A2.UI.IconButton("", { src: A2.UI.Url + "resource/btnMinimize.gif", w: 16, h: 16 }, function() { this.Parent.Parent.ToggleMinimize(); });
            closeBtn.SetClass("CloseBtn");
            this.ControlBox.AddControl(closeBtn);
            this.AddControl(this.ControlBox);
        }
    }
    this.Lock = false;
    this.ToggleMinimize = function(func)
    {
        if (!this.Lock)
        {
            this.Lock = true;
            if (this.SavedY == 0)
            {
                this.SavedY = $G.GetStyle(this.Holder, "height", true);
                $FX.Time(500).AnimateStyle(this.Holder, "height", -this.SavedY + this.FitDelta, this.FitDelta, function()
                {
                    this.itm.Lock = false;
                    this.itm.ControlBox.Controls[0].SetIcon(A2.UI.Url + "resource/btnRestore.gif");
                    if (this.func)
                        this.func();
                } .bind({ itm: this, func: func }), null, "PanelMinimize");
            }
            else
            {
                $FX.Time(500).AnimateStyle(this.Holder, "height", this.SavedY - this.FitDelta, this.SavedY, function()
                {
                    this.itm.Lock = false;
                    this.itm.ControlBox.Controls[0].SetIcon(A2.UI.Url + "resource/btnMinimize.gif");
                    if (this.func)
                        this.func();
                } .bind({ itm: this, func: func }), null, "PanelMinimize");
                this.SavedY = 0;
            }
        }
    }
    this.Construct();
    var _baseOnLoad = this.OnLoad.bind(this);
    this.OnLoad = function()
    {
        _baseOnLoad(arguments);
        this.FixContentHeight();
    }
    this.SetTitle = function(text)
    {
        this.Title.innerHTML = text;
    }
    if (title)
        this.SetTitle(title);
}
A2.UI.Panel.prototype = new A2.UI.Control();
A2.UI.ItemList = function(items, allowDrag)
{
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("ul", "UIItemList");
    this.AllowDrag = !!allowDrag;
    this.AddItem = function(item)
    {
        return this.AddControl(new A2.UI.ListItem(item.title, item.props, item.actions, item.css, this.AllowDrag));
    }
    this.AddItems = function(items)
    {
        for (var i = 0; i < items.length; i++)
            this.AddItem(items[i]);
    }
    this.GetByProps = function(props)
    {
        var items = new Array();
        for (var i = 0; i < this.Controls.length; i++)
        {
            var itm = this.Controls[i].GetProperties();
            var res = true;
            for (var j in props)
            {
                if (!Function.prototype.isPrototypeOf(props[j]))
                {
                    res = res && (itm[j] == props[j]);
                }
            }
            if (res)
                items.push(this.Controls[i]);
        }
        return items;
    }
    this.OnLoad = function()
    {
        if (this.AllowDrag)
        {
            $G.Event.Add(this.Holder, "mousemove", function()
            {
                if (this.ChildDraging)
                {
                    var _pos = $G.GetTopLeft(this.Holder);
                    if (A2.UI.Dialog.prototype.isPrototypeOf(this.Parent))
                    {
                        _pos.scroll = this.Parent.ScrollWraper.scrollTop
                    }
                    var current = null;
                    for (var i = 0; i < this.Controls.length; i++)
                    {
                        var item = this.Controls[i];
                        if (A2.UI.ListItem.prototype.isPrototypeOf(item))
                        {
                            var _itempos = $G.GetTopLeft(item.Holder);
                            if (_pos.scroll)
                                _itempos.y -= _pos.scroll;
                            if (_itempos.x < $G.Mouse.X && _itempos.x + item.Holder.offsetWidth > $G.Mouse.X &&
                            _itempos.y < $G.Mouse.Y && _itempos.y + item.Holder.offsetHeight > $G.Mouse.Y)
                            {
                                current = item;
                                break;
                            }
                        }
                        item = null;
                    }
                    this.CurrentOvered = current;
                    if (this.OnOverChange)
                        this.OnOverChange();

                }
            } .bind(this));
        }
    }
    if (items)
        this.AddItems(items);
}
A2.UI.ItemList.prototype = new A2.UI.Control();
A2.UI.ListItem = function(title, props, actions, css, drag)
{
    this.AllowDrag = !!drag;
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("li");

    if (css)
        $G.ClassName.Replace(this.Holder, css, css);
    if (this.AllowDrag) // чтоб надпись не съезжала
        $G.ClassName.Replace(this.Holder, "Draggable", "Draggable");

    this.AddAction = function(action)
    {
        var act = this.AddControl(new A2.UI.Image(action.icon, "ListAction"), (this.DragImage || this.Title), true);
        $G.Event.Add(act, "click", function() { action.func(this); } .bind(this));
    }
    this.AddActions = function(actions)
    {
        for (var i = 0; i < actions.length; i++)
            this.AddAction(actions[i]);
    }
    this.MoveUp = function()
    {
        var prev = this.GetPrevious();
        if (prev)
        {
            $G.Append(this.Parent.Content, this.Holder, prev.Holder, true);
            return true;
        }
        return false;
    }
    this.MoveDown = function()
    {
        var next = this.GetNext();
        if (next)
        {
            $G.Append(this.Parent.Content, this.Holder, next.Holder, false);
            return true;
        }
        return false;
    }
    this.GetPrevious = function()
    {
        if (this.Parent && this.Parent.Controls)
        {
            var prev = $G.Previous(this.Holder);
            for (var i = 0; i < this.Parent.Controls.length; i++)
            {
                var ctrl = this.Parent.Controls[i];
                if (ctrl.Holder == prev)
                {
                    return ctrl;
                }
            }
        }
        return null;
    }
    this.GetNext = function()
    {
        if (this.Parent && this.Parent.Controls)
        {
            var prev = $G.Next(this.Holder);
            for (var i = 0; i < this.Parent.Controls.length; i++)
            {
                var ctrl = this.Parent.Controls[i];
                if (ctrl.Holder == prev)
                {
                    return ctrl;
                }
            }
        }
        return null;
    }
    this.OnParentDeleted = this.OnUnload = function()
    {
        if (this.AllowDrag)
        {
            var _drag = $UI.Move.GetDragByObject(this.Holder);
            if (_drag)
            {
                $UI.Move.Remove(_drag.Holder);
            }
            $UI.Move.OrganizeDialogs(this);
        }
    } .bind(this);
    this.OnLoad = function()
    {
        if (this.AllowDrag)
        {
            $G.Selection.Disable(this.Holder);
        }
    }
    if (this.AllowDrag)
    {
        this.DragImage = new _UIDrag();
        this.DragImage.LockH = true;
        this.DragImage.LockV = true;
        this.DragImage.Holder = this.DragImage.Content = $G.Tag("div", "DragImage", null, "<!-- -->");
        this.AddControl(this.DragImage);
    }
    this.Title = new A2.UI.Control();
    this.Title.Holder = this.Title.Content = $G.Tag("a", { href: "javascript:void(0)" }, null, (title || "Элемент списка"));
    this.AddControl(this.Title);
    this.EmptyString = "";
    if (this.AllowDrag)
    {
        this.DragImage.OnStart = function(drag)
        {

            var tip = $G.Get.ById("A2-UI-ListItem-Drag");
            if (tip)
                tip.parentNode.removeChild(tip);
            var text = $G.TagToString(this.Title.Holder) + $G.TagToString(this.Properties.Holder);
            this.EmptyString = text;
            tip = $G.Append($UI.Body.Holder, $G.Tag("div", null, "A2-UI-ListItem-Drag", text), $UI.Body.Holder.firstChild, true);
            tip.style.top = ($G.Mouse.Y + 15) + "px";
            tip.style.left = ($G.Mouse.X + 15) + "px";
            this.Parent.ChildDraging = true;
            this.Parent.OnOverChange = function()
            {
                if (this.item.Parent.CurrentOvered != null)
                {
                    if (!this.item.Parent.Separator)
                        this.item.Parent.Separator = new A2.UI.Control($G.Tag("div", null, "A2-UI-ListItem-Separator"));
                    this.item.Parent.AddControl(this.item.Parent.Separator, this.item.Parent.CurrentOvered, false, true);
                }
                else
                {
                    if (this.item.Parent.Separator)
                        this.item.Parent.RemoveControl(this.item.Parent.Separator);
                    this.item.Parent.Separator = null;
                }
                if (this.item.Parent && this.item.Parent.CurrentOvered && this.item.Parent.CurrentOvered != this)
                {
                    var current = $G.TagToString(this.item.Parent.CurrentOvered.Title.Holder) + $G.TagToString(this.item.Parent.CurrentOvered.Properties.Holder)
                    this.tip.innerHTML = "<strong>переместить </strong><br />" + this.item.EmptyString + "<br /><strong> после </strong><br />" + current;
                }
                else
                {
                    this.tip.innerHTML = "<strong>переместить </strong><br />" + this.item.EmptyString;
                }
            } .bind({ item: this, tip: tip });
        } .bind(this);
        this.DragImage.OnMove = function(drag, x, y)
        {
            var tip = $G.Get.ById("A2-UI-ListItem-Drag");
            if (tip)
            {
                tip.style.top = ($G.Mouse.Y + 15) + "px";
                tip.style.left = ($G.Mouse.X + 15) + "px";
            }
        }
        this.DragImage.OnStop = function()
        {
            var tip = $G.Get.ById("A2-UI-ListItem-Drag");
            if (tip)
                tip.parentNode.removeChild(tip);
            if (this.Parent.CurrentOvered && this.Parent.CurrentOvered != this)
            {
                $G.Append(this.Parent.Content, this.Holder, this.Parent.CurrentOvered.Holder, false);
            }
            if (this.Parent.Separator)
                this.Parent.RemoveControl(this.Parent.Separator);
            this.Parent.OnOverChange = null;
            this.Parent.ChildDraging = false;
        } .bind(this);
    }
    this.Properties = this.AddControl(new A2.UI.Control($G.Tag("small")));
    this.SetTitle = function(title)
    {
        this.Title.Holder.innerHTML = title || "";
    }
    this.GetTitle = function()
    {
        return this.Title.Holder.innerHTML;
    }
    this.SetProperties = function(props)
    {
        this.Properties.Holder.innerHTML = "";
        if (props)
        {
            this.Properties.Holder.innerHTML += " (";
            for (var i in props)
            {
                this.Properties.Holder.innerHTML += i + ":<span class='value'>" + props[i] + "</span>";
                this.Properties.Holder.innerHTML += ", ";
            }
            this.Properties.Holder.innerHTML = this.Properties.Holder.innerHTML.replace(/, $/gi, "");
            this.Properties.Holder.innerHTML += ")";
        }
    }
    this.GetProperties = function()
    {
        var str = this.Properties.Holder.innerHTML.replace(/\)$/gi, "").replace(/^\&nbsp;\(/gi, "").replace(/\(/gi, "").trim().split(", ");
        var props = {};
        for (var i = 0; i < str.length; i++)
        {
            var val = str[i].split(":");
            if ($G.Browser.Detect.webkit)
                val[0] = val[0].substr(1, val[0].length - 1); //Уебищьный вебкит

            if (val.length == 2)
                props[val[0]] = $G.GET($G.Tag("div", null, null, val[1]), "span:0").innerHTML;
        }
        return props;
    }
    this.RemoveFromList = function()
    {
        if (this.Parent)
            this.Parent.RemoveControl(this);
    }
    if (props)
        this.SetProperties(props);
    if (actions)
        this.AddActions(actions);
}
A2.UI.ListItem.prototype = new A2.UI.Control();
A2.UI.TextEditor = function(text)
{
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("div", "TextEditor");
    this.Editor = null;
    this.EditorPanel = null;
    this.Instance = null;
    this._text = text;
    this.GetText = function()
    {
        return this.Editor.nicInstances[0].getContent();
    }
    this.SetText = function(text)
    {
        return this.Editor.nicInstances[0].setContent(text);
    }
    this.OnLoad = function()
    {
        this.EditorPanel = this.AddControl(new A2.UI.Control($G.Tag("div", "EditorPanel")));
        this.Instance = this.AddControl(new A2.UI.Control($G.Tag("div", "EditorInstance", null, (this._text || ""))));
        this.Editor = new nicEditor({ fullPanel: true });
        this.Editor.nicInstances = [];
        this.Editor.addInstance(this.Instance.Content).setPanel(this.EditorPanel.Content);
    }
}
A2.UI.TextEditor.prototype = new A2.UI.Control();
A2.UI.Dialog = function(title, actions, onClose, scroll)
{
    this.Controls = new Array();
    this.SavedX = 0;
    this.SavedY = 0;
    this.Subject = null;
    this.Title = null;
    this.Content = null;
    this.DragBounds = null;
    this.ResizeBounds = null;
    this.DragHandler = null;
    this.ControlBox = null;
    this.ActionBar = null;
    this.FitDelta = $G.Browser.Detect.ie ? 57 : 63;
    this.Modal = new Array();
    this.Actions = actions;
    this.ScrollWraper = $G.Tag("div", "ScrollWrapper");
    this.ActiveClassName = "DialogActive";
    this.InActiveClassName = "DialogInActive";
    if ($G.Browser.Detect.ie)
    {
        this.IeFrame = $G.Tag("iframe", { src: "javascript:false;", frameBorder: "0" });
        this.IeFrame.style.position = "absolute";
        this.IeFrame.style.display = "block";
    }
    this.Disabler = null;
    if (scroll)
    {
        $G.ClassName.Replace(this.ScrollWraper, "", "Scroll");
    }

    this.OnClose = onClose || function() { };
    this.Activate = function()
    {
        $G.ClassName.Replace(this.Holder, this.InActiveClassName, this.ActiveClassName);
    }
    this.DeActivate = function()
    {
        $G.ClassName.Replace(this.Holder, this.ActiveClassName, this.InActiveClassName);
        this.Disabler.style.width = $G.GetStyle(this.Holder, "width", true) + "px";
        this.Disabler.style.height = $G.GetStyle(this.Holder, "height", true) + "px";
        this.Disabler.style.top = "0px";
        this.Disabler.style.left = "0px";
        $G.SetOpacity(this.Disabler, 0.1);
    }
    this.Construct = function()
    {
        this.DragBounds = new UIDialogDragBounds();
        this.ResizeBounds = new UIBounds(500, 300, 301, 301);
        this.Holder = $G.Tag("div", "Dialog");
        this.Content = $G.Tag("div", "Content");
        this.PostConstruct();
        var drag = new _UIDrag();
        drag.Holder = drag.Content = $G.Tag("div", "DragHandler");
        this.Title = $G.Tag("h4", "Title");
        drag.Holder.appendChild(this.Title);
        drag.OnStart = function() { this._onMoveStart(); } .bind(this);
        drag.OnMove = function() { this.FixIframe(); } .bind(this);
        this.AddControl(drag);
        this.DragHandler = drag;
        this["Panels"] = this.AddControl(new A2.UI.SystemControl($G.Tag("div")));
        $G.Append(this.Holder, this.ScrollWraper);
        $G.Append(this.ScrollWraper, this.Content);
        this.Disabler = $G.Append(this.Holder, $G.Tag("div", "Disabler"));
    }
    this.DockInContent = function(ctrl, xdelta, ydelta)
    {
        if (ctrl)
        {
            ctrl.Holder.style.height = ($G.GetStyle(this.ScrollWraper, "height", true) + (ydelta || 0)) + "px";
            ctrl.Holder.style.width = ($G.GetStyle(this.Holder, "width", true) + (xdelta || 0)) + "px";
        }
    }
    this.FixContentHeight = function()
    {
        $G.SetStyle("height", ($G.GetStyle(this.Holder, "height", true) - this.FitDelta) + "px", this.ScrollWraper)
    }
    this.FitToContent = function()
    {
        var height = this.Content.offsetHeight;
        $G.SetStyle("height", (height + this.FitDelta) + "px", this.Holder);
        this.FixContentHeight();
        this.FixIframe();
        return this;
    }
    this.PostConstruct = function()
    {
        if (this.ControlBox == null)
        {
            this.ControlBox = new A2.UI.SystemControl();
            this.ControlBox.Holder = $G.Tag("div", "ControlBox");
            this.ControlBox.Content = this.ControlBox.Holder;
            var closeBtn = new A2.UI.IconButton("", { src: A2.UI.Url + "resource/btnClose.gif", w: 16, h: 16 }, function() { this.Parent.Parent.Close(); });
            $G.Event.Add(closeBtn, "mouseover", function()
            {
                var p = new A2.UI.Control($G.Tag("p")).SetText("Закрыть окно (<img src='" + A2.UI.Url + "resource/images/key.gif' alt='' />Ctrl+Q)");
                $E.ToolTipShow(p, false, false, 200, 5, 5);
            });
            $G.Event.Add(closeBtn, "mouseout", $E.ToolTipHide);

            closeBtn.SetClass("CloseBtn");
            this.ControlBox.AddControl(closeBtn);
            this.AddControl(this.ControlBox);
        }
        this.ActionBar = this.AddControl(new A2.UI.SystemControl($G.Tag("div", "ActionBar")));

        if (this.Actions)
        {
            for (var i = 0; i < this.Actions.length; i++)
            {
                this.ActionBar.AddControl(new A2.UI.DialogAction(this.Actions[i].title, this.Actions[i].func, this.Actions[i].css));
            }
        }
        this.ActionBar.OnChildAdded = function()
        {
            if (this.ActionBar.Controls.length == 1)
            {
                $G.Event.Add(this.ActionBar.Controls[0], "mouseover", function()
                {
                    $E.ToolTipShow((new A2.UI.Control($G.Tag("p"))).SetText("<img src='" + A2.UI.Url + "resource/images/key.gif' alt='' />Ctrl+Enter"), false, false, 130, 5, 10);
                });
                $G.Event.Add(this.ActionBar.Controls[0], "mouseout", $E.ToolTipHide);
            }
        } .bind(this);
    }
    this.Close = function()
    {
        for (var i = 0; i < this.Modal.length; i++)
            if (this.Modal[i].Close)
            this.Modal[i].Close();
        this.OnClose();
        this.Parent.RemoveControl(this);
        $E.ToolTipHide();
    }
    this.Hide = function()
    {
        this.Holder.style.display = "none";
        if (this.IeFrame)
            this.IeFrame.style.display = "none";
    }
    this.Show = function()
    {
        this.Holder.style.display = "block";
        if (this.IeFrame)
            this.IeFrame.style.display = "block";
    }
    this.OnStop = function()
    {
        this.Save();
        this.FixIframe();
    }
    this.Center = function(x, y)
    {
        var _w = $G.GetStyle(this.Holder, "width", true);
        var _h = $G.GetStyle(this.Holder, "height", true);
        this.Holder.style.left = ($G.Window.Width() / 2 - _w / 2 + $G.Window.Scroll.Left() + (x || 0)) + "px";
        this.Holder.style.top = ($G.Window.Height() / 2 - _h / 2 + $G.Window.Scroll.Top() + (y || 0)) + "px";
        this.FixIframe();
        return this;
    }
    this.Move = function(x, y, relative)
    {
        if (x != null)
        {
            var sx = relative ? $G.GetStyle(this.Holder, "left", true) : 0;
            this.Holder.style.left = (x + sx) + "px";
        }
        if (y != null)
        {
            var sy = relative ? $G.GetStyle(this.Holder, "top", true) : 0;
            this.Holder.style.top = (y + sy) + "px";
        }
        this.FixIframe();
    }
    this.FixIframe = function()
    {
        if (this.IeFrame)
        {
            this.IeFrame.style.left = this.Holder.style.left;
            this.IeFrame.style.top = this.Holder.style.top;
            this.IeFrame.style.width = this.Holder.style.width;
            this.IeFrame.style.height = this.Holder.style.height;
            this.IeFrame.style.zIndex = (($G.GetStyle(this.Holder, "z-index", true) || 1) - 1).toString();
        }
    }
    this.Construct();
    var _onInit = this.OnInit.bind(this);
    this.OnInit = function()
    {
        _onInit(arguments);
    }
    this.HasModal = function(dialog)
    {
        var result = false;
        if (dialog)
        {
            for (var i = 0; i < this.Modal.length; i++)
            {
                if (A2.UI.Dialog.prototype.isPrototypeOf(this.Modal[i]))
                {
                    if (this.Modal[i] == dialog || this.Modal[i].HasModal(dialog))
                        return true;
                }
            }
        }
        return result;
    }
    var _baseOnLoad = this.OnLoad.bind(this);
    this.OnLoad = function()
    {
        this.Holder.style.width = this.ResizeBounds.MinX + "px";
        this.Holder.style.height = this.ResizeBounds.MinY + "px";
        if (this.IeFrame)
            $UI.Body.AddControl(new A2.UI.Control(this.IeFrame));
        _baseOnLoad(arguments);
        if (this.ControlBox)
            $UI.Move._ieStop.bind(this.ControlBox)();
        var _g = $UI.Move.GetWithUpLimit($UI.Move.HighestDepth());
        if ((_g != null) && (_g.Parent.Holder.style.display != "none"))
        {
            var _pt = $G.GetStyle(_g.Parent.Holder, "top", true);
            var _pl = $G.GetStyle(_g.Parent.Holder, "left", true);
            var _w = $G.GetStyle(this.Holder, "width", true);
            var _h = $G.GetStyle(this.Holder, "height", true);
            this.Move((($G.Window.Width() + $G.Window.Scroll.Left() - 30 > (_pl + _w)) ? (_pl + 30) : $G.Window.Scroll.Left() + 10), (($G.Window.Height() + $G.Window.Scroll.Top() - 30 > (_pt + _h)) ? (_pt + 30) : $G.Window.Scroll.Top() + 35));
        }
        else
        {
            this.Center();
        }
        this.FixContentHeight();
        $UI.Move.OrganizeDialogs(this);
        this.FixIframe();
        this.OnUnload = function()
        {
            var _drag = $UI.Move.GetDragByObject(this.Holder);
            if (_drag)
                $UI.Move.Remove(_drag.Holder);
            $UI.Move.OrganizeDialogs(this);
            if (this.IeFrame)
            {
                this.IeFrame.parentNode.removeChild(this.IeFrame);
                this.IeFrame = null;
            }
        }
    }
    this.SetTitle = function(text)
    {
        this.Title.innerHTML = text;
        return this;
    }
    if (title)
        this.SetTitle(title);
}
A2.UI.DialogAction = function(title, func, css)
{
    this.Holder = this.Content = $G.Tag("a", "Action" + (css ? " " + css : ""), null, title, { href: "javascript:void(0)" });
    this.Controls = new Array();
    this.onClick = func;
    this.AddEvent = function(type, func)
    {
        if (type == "click")
            this.onClick = func;
        $G.Event.Add(this.Holder, type, func);
        return this;
    }
    this.OnLoad = function()
    {
        $G.Event.Add(this.Holder, "click", function() { this.onClick(this); } .bind(this));
    }
}
$DM = $DialogManager =
{
    _oldLoad: null,
    Init: function()
    {
        A2.UI.Dialog.prototype = new A2.UI.Control();
        A2.UI.DialogAction.prototype = new A2.UI.Control();
        $UI.Hotkey.Register([$UI.Hotkey.Keys.Ctrl, $UI.Hotkey.Keys.Enter], function()
        {
            var win = $UI.Move.GetHighest();
            if (win && win.Parent && A2.UI.Dialog.prototype.isPrototypeOf(win.Parent)
                && win.Parent.ActionBar && win.Parent.ActionBar.Controls.length > 0
                && win.Parent.ActionBar.Controls[0].onClick)
            {
                win.Parent.ActionBar.Controls[0].onClick(win.Parent.ActionBar.Controls[0]);
            }
        }, "OKindaHighestWindow");
        //Ctrl+Q
        $UI.Hotkey.Register([$UI.Hotkey.Keys.Ctrl, 81], function()
        {
            var win = $UI.Move.GetHighest();
            if (win && win.Parent && A2.UI.Dialog.prototype.isPrototypeOf(win.Parent))
            {
                win.Parent.Close();
            }
        }, "CloseindaHighestWindow");
        window["SysAlert"] = window["alert"];
        window["SysPromt"] = window["promt"];
        window["SysConfirm"] = window["confirm"];
        window["confirm"] = function(text, title, onOk)
        {
            var a = new A2.UI.Dialog(title || "Сообщение:");
            a["OnOk"] = onOk;
            $UI.Body.AddControl(a);
            a.AddControl(new A2.UI.Control($G.Tag("p", "Text", null, text)));
            a.ActionBar.AddControl(new A2.UI.DialogAction("Да", function()
            {
                if (this.OnOk)
                    this.OnOk();
                this.Close();
            } .bind(a)));
            a.ActionBar.AddControl(new A2.UI.DialogAction("Нет", function()
            {
                this.Close();
            } .bind(a)));
            a.FitToContent();
            return a;
        }
        window["alert"] = function(text, title)
        {
            var a = new A2.UI.Dialog(title || "Сообщение:");
            $UI.Body.AddControl(a);
            a.AddControl(new A2.UI.Control($G.Tag("p", "Text", null, text)));
            a.ActionBar.AddControl(new A2.UI.DialogAction("ОК", function()
            {
                this.Close();
            } .bind(a)));
            a.FitToContent();
            return a;
        }
    }
}

A2.UI.Tree = function()
{
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("ul", "UITree");
    this.AddNode = function(node, anchor, noinit, before)
    {
        if (A2.UI.TreeNode.prototype.isPrototypeOf(node))
            return this.AddControl(node, anchor, (before == null ? !!anchor : before), noinit);
        return null;
    }
    this.GetNodes = function(obj)
    {
        var result = new Array();
        for (var i = 0; i < this.Controls.length; i++)
        {
            if ($G.Match(this.Controls[i], obj))
                result.push(this.Controls[i]);
            result = result.concat(this.Controls[i].GetNodes(obj));
        }
        return result;
    }
    this.GetChecked = function()
    {
        var checked = new Array();
        for (var i = 0; i < this.Controls.length; i++)
        {
            var node = this.Controls[i];
            if (A2.UI.TreeNode.prototype.isPrototypeOf(node))
            {
                if (node.Checked && node.WithCheck)
                    checked.push(node);
                var sel = node.GetChecked();
                checked = checked.concat(sel);
            }
        }
        return checked;
    }
    this.GetNodeList = function()
    {
        var nodes = new Array();
        for (var i = 0; i < this.Controls.length; i++)
        {
            var node = this.Controls[i];
            if (A2.UI.TreeNode.prototype.isPrototypeOf(node))
            {
                nodes.push(node);
                nodes = nodes.concat(node.GetNodeList());
            }
        }
        return nodes;
    }
    this.GetSelected = function()
    {
        for (var i = 0; i < this.Controls.length; i++)
        {
            var node = this.Controls[i];
            if (A2.UI.TreeNode.prototype.isPrototypeOf(node))
            {
                var sel = node.GetSelected();
                if (sel)
                    return sel;
            }
        }
    }
    this.GetMainTree = function()
    {
        if (this.Parent && A2.UI.TreeNode.prototype.isPrototypeOf(this.Parent) && this.Parent.GetMainTree)
            return this.Parent.GetMainTree();
        return this;
    }
    this.GetMainNode = function(node)
    {
        if (this.Parent && A2.UI.TreeNode.prototype.isPrototypeOf(this.Parent) && this.Parent.GetMainNode)
            return this.Parent.GetMainNode();
        return node;
    }
    this.SelectedChanged = function()
    {
        this.OnSelectedChanged();
        if (this.Parent && A2.UI.TreeNode.prototype.isPrototypeOf(this.Parent) && this.Parent.SelectedChanged)
            this.Parent.SelectedChanged();
    }
    this.UniqueParams = function(params)
    {
        var result = true;
        for (var i = 0; i < this.Controls.length; i++)
        {
            result = result && this.Controls[i].UniqueParams(params);
            if (!result)
                break;
        }
        return result;
    }
    this.OnSelectedChanged = function() { }
    this.ExpandAll = function()
    {
        for (var i = 0; i < this.Controls.length; i++)
        {
            if (this.Controls[i].ExpandAll)
                this.Controls[i].ExpandAll();
        }
    }
    this.CheckAll = function()
    {
        for (var i = 0; i < this.Controls.length; i++)
        {
            if (this.Controls[i].CheckAll)
                this.Controls[i].CheckAll();
        }
    }
    this.CollapseAll = function()
    {

        for (var i = 0; i < this.Controls.length; i++)
        {
            if (this.Controls[i].CollapseAll)
                this.Controls[i].CollapseAll();
        }
    }
    this.UnCheckAll = function()
    {
        for (var i = 0; i < this.Controls.length; i++)
        {
            if (this.Controls[i].UnCheckAll)
                this.Controls[i].UnCheckAll();
        }
    }
}

A2.UI.TreeNode = function(title, icon, withCheck, hasInner, description)
{
    this.SelectedClassName = "Selected";
    this.CollapsedClassName = "Collapsed";
    this.EmptyClassName = "Empty";
    this.ExpandedClassName = "Expanded";
    this.CheckedClassName = "Checked";
    this.UnCheckedClassName = "UnChecked";
    this.TableRowClassName = "TableRow";
    this.Controls = new Array();
    this.WithCheck = withCheck == true;
    this.Holder = this.Content = $G.Tag("li", !hasInner ? this.EmptyClassName : this.CollapsedClassName);
    this.Toggle = this.AddControl(new A2.UI.Image({ src: A2.UI.Url + "resource/px.gif", width: "15", height: "15" }, "TreeToggle"));
    this.Check = this.AddControl(new A2.UI.Image({ src: A2.UI.Url + "resource/px.gif", width: "16", height: "16" }, "TreeCheck"));
    if (!withCheck)
        this.Check.Holder.style.display = "none";
    else if (withCheck && withCheck == "empty")
        this.Check.Holder.style.visibility = "hidden";
    this.Image = this.AddControl(new A2.UI.Image(icon, "TreePict"));
    this.Label = this.AddControl(new A2.UI.Control($G.Tag("a", { href: "javascript:void(0)" }, null, title)));
    if (description)
        this.Description = this.AddControl(new A2.UI.Control($G.Tag("small"))).SetText(description);
    this.AddControl(new A2.UI.Control($G.Tag("div", "clear")));
    this.SubTree = this.AddControl(new A2.UI.Tree());
    this.EventHandlers = new Array();
    this.Checked = false;
    this.Cells = new Array();
    this.Invoke = function(type)
    {
        for (var i = 0; i < this.EventHandlers.length; i++)
            if (this.EventHandlers[i].type == type)
            this.EventHandlers[i].func();
        this.FirstToggle = false;
    }
    this.AddCell = function(width)
    {
        var ctrl = new A2.UI.Control($G.Tag("div", "TreeCell"));
        this.Cells.push(ctrl);
        ctrl.Holder.style.width = (width || 100) + "px";
        this.AddControl(ctrl, this.Controls[0], true);
        $G.ClassName.Replace(this.Holder, this.TableRowClassName, this.TableRowClassName);
        return ctrl;
    }
    this.ExpandAll = function()
    {
        this.Expand();
        this.SubTree.ExpandAll();
    }
    this.CheckAll = function()
    {
        this.DoCheck();
        this.SubTree.CheckAll();
    }
    this.CollapseAll = function()
    {
        this.Collapse();
        this.SubTree.CollapseAll();
    }
    this.UnCheckAll = function()
    {
        this.UnCheck()
        this.SubTree.UnCheckAll();
    }
    this.UniqueParams = function(params)
    {
        var result = true;
        for (var param in params)
            result = result && this[param] != params[param];
        if (result && this.SubTree)
            result = result && this.SubTree.UniqueParams(params);
        return result;
    }
    this.SetTitle = function(title)
    {
        this.Label.Holder.innerHTML = title || "Нода дерева";
    }
    this.GetTitle = function()
    {
        return this.Label.Holder.innerHTML;
    }
    this.GetNodes = function(obj)
    {
        return this.SubTree.GetNodes(obj);
    }
    this.GetHandler = function(type)
    {
        for (var i = 0; i < this.EventHandlers.length; i++)
            if (this.EventHandlers[i].type == type)
            return this.EventHandlers[i];
        return null;
    }
    this.AddEvent = function(type, func)
    {
        if (!this.GetHandler(type))
        {
            $G.Event.Add(this.Label, type, function() { this.ctrl.Invoke(this.type); } .bind({ ctrl: this, type: type }));
        }
        this.EventHandlers.push({ func: func, type: type });
        return this;
    }
    this.FirstToggle = !!hasInner;
    this.AddNode = function(node, before, noinit)
    {
        this.Holder.className = this.Holder.className.replace(this.EmptyClassName, this.CollapsedClassName);
        return this.SubTree.AddNode(node, before, noinit);
    }
    this.isSelected = function()
    {
        return this.Holder.className.indexOf(this.SelectedClassName) != -1;
    }
    this.Collapse = function()
    {
        $G.ClassName.Replace(this.Holder, this.ExpandedClassName, this.CollapsedClassName);
    }
    this.Expand = function()
    {
        if (!this.Empty())
            $G.ClassName.Replace(this.Holder, this.CollapsedClassName, this.ExpandedClassName);
    }
    this.Expanded = function()
    {
        return this.Holder.className.indexOf(this.ExpandedClassName) != -1;
    }
    this.Collapsed = function()
    {
        return this.Holder.className.indexOf(this.CollapsedClassName) != -1;
    }
    this.Empty = function()
    {
        return this.Holder.className.indexOf(this.EmptyClassName) != -1;
    }
    this.ToggleCheck = function()
    {
        if (this.Checked) { this.UnCheck(); } else { this.DoCheck(); };
    }
    this.OnCheckChange = function() { }
    this.DoCheck = function(nochange)
    {
        if (this.WithCheck)
        {
            $G.ClassName.Replace(this.Check.Holder, this.UnCheckedClassName, this.CheckedClassName);
            this.Checked = true;
            if (!nochange)
                this.OnCheckChange();
        }
    }
    this.FixToggle = function()
    {
        if (this.SubTree.Controls.length == 0)
            $G.ClassName.Replace(this.Holder, [this.ExpandedClassName, this.CollapsedClassName], this.EmptyClassName);
    }
    this.UnCheck = function(nochange)
    {
        if (this.WithCheck)
        {
            $G.ClassName.Replace(this.Check.Holder, this.CheckedClassName, this.UnCheckedClassName);
            this.Checked = false;
            if (!nochange)
                this.OnCheckChange();
        }
    }
    this.GetSelected = function()
    {
        if (this.isSelected())
            return this;
        else
            return this.SubTree.GetSelected();
    }
    this.GetChecked = function()
    {
        return this.SubTree.GetChecked();
    }
    this.GetNodeList = function()
    {
        return this.SubTree.GetNodeList();
    }
    this.OnSelect = function() { };
    this.Select = function()
    {
        var current = this.GetMainTree().GetSelected();
        if (current)
            current.Deselect();
        $G.ClassName.Replace(this.Holder, this.SelectedClassName, this.SelectedClassName);
        this.ToggleState();
        if (!this.isSelected())
            this.SelectedChanged();
        this.OnSelect();
    }
    this.SelectedChanged = function()
    {
        if (this.Parent && A2.UI.Tree.prototype.isPrototypeOf(this.Parent) && this.Parent.SelectedChanged)
            this.Parent.SelectedChanged();
    }
    this.Deselect = function()
    {
        $G.ClassName.Replace(this.Holder, this.SelectedClassName, "");
    }
    this.GetMainTree = function()
    {
        if (this.Parent && this.Parent.GetMainTree)
            return this.Parent.GetMainTree();
        return null;
    }
    this.GetMainNode = function()
    {
        if (this.Parent && A2.UI.Tree.prototype.isPrototypeOf(this.Parent) && this.Parent.GetMainNode)
            return this.Parent.GetMainNode(this);
    }
    this.ToggleState = function()
    {
        if (this.Expanded())
            this.Collapse();
        else
            this.Expand();
    }
    this.OnLoad = function()
    {
        if (this.WithCheck)
            $G.Event.Add(this.Check, "click", function()
            {
                this.ToggleCheck();
            } .bind(this));
        $G.Event.Add(this.Toggle, "click", function()
        {
            this.ToggleState();
            if (this.FirstToggle)
            {
                this.Invoke("click");
            }
        } .bind(this));
        $G.Event.Add(this, "click", function()
        {
            this.Select();
        } .bind(this));
        if (this.SubTree)
        {
            this.SubTree.OnClearControls = function()
            {
                $G.ClassName.Replace(this.Holder, [this.CollapsedClassName, this.ExpandedClassName, this.EmptyClassName], this.EmptyClassName);
            } .bind(this);
        }
    }
    if (this.WithCheck)
        this.UnCheck(true);
}
A2.UI.Tree.prototype = new A2.UI.Control();
A2.UI.TreeNode.prototype = new A2.UI.Control();
A2.UI.ContextMenu = function(actions)
{
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("ul", "ContextMenu");
    this.AddAction = function(action)
    {
        this.AddControl(new A2.UI.ContextAction(action.title, action.icon, action.action, action.href));
    }
    this.AddActions = function(actions)
    {
        if (actions)
            for (var i = 0; i < actions.length; i++)
            this.AddAction(actions[i]);
    }
    if (actions)
        this.AddActions(actions);
    this.Show = function()
    {
        if (A2.UI["_CurrentContextMenu"])
            A2.UI["_CurrentContextMenu"].Parent.RemoveControl(A2.UI["_CurrentContextMenu"]);
        A2.UI["_CurrentContextMenu"] = this;
        $G.ShowAtPosition(this.Holder, false, 5, 5);
        var x = $G.GetStyle(this.Holder, "left", true);
        var y = $G.GetStyle(this.Holder, "top", true);
        var w = $G.Window.Width();
        var h = $G.Window.Height();
        h += $G.Window.Scroll.Top();
        if (h < this.Holder.offsetHeight + y)
        {
            this.Holder.style.top = (h - this.Holder.offsetHeight) + "px";
        }
        if (w < this.Holder.offsetWidth + x)
        {
            this.Holder.style.left = (w - this.Holder.offsetWidth) + "px";
        }
        var bclick = document.body.onclick;
        document.body.onclick = function(e)
        {
            if (bclick)
                bclick(e);
            var target = $G.Event.Target(e);
            if (!this.ContainsElement(target))
                this.Parent.RemoveControl(this);
        } .bind(this);
    }
}
A2.UI.ContextMenu.prototype = new A2.UI.Control();
A2.UI.ContextAction = function(title, icon, action, href)
{
    this.Controls = new Array();
    this.Holder = this.Content = $G.Tag("li");
    this.Image = this.AddControl(new A2.UI.Image({ src: A2.UI.Url + "/resource/px.gif" }));
    this.Title = this.AddControl(new A2.UI.Control($G.Tag("a", { href: (!href ? "javascript:void(0);" : href) })));
    this.AddControl(new A2.UI.Control($G.Tag("div", "clear")));
    this.SetText = function(text)
    {
        this.Title.Holder.innerHTML = text;
    }
    this.SetImage = function(img)
    {
        this.Image.SetImage(img);
    }
    if (title)
        this.SetText(title);
    if (icon)
        this.SetImage(icon);
    $G.Event.Add(this, "click", function() { (action || function() { })(); this.Parent.Parent.RemoveControl(this.Parent); } .bind(this));
}
A2.UI.ContextAction.prototype = new A2.UI.Control();
$DM._oldLoad = window.onload;
window.onload = function()
{
    if ($DM._oldLoad)
        $DM._oldLoad();
    $DM.Init();
}

