﻿/// <reference path="global.js" />
/// <reference path="effects.js" />
/*************************************************
*												 *
*		Модуль всевозможных UI Элементов         *
*												 *
*		Дата:				Автор:               *
*		02.11.2007			Агроник А.Ю.         *
*											   	 *
*                                               *
*		Внимание! данный файл является           *
*		частью программного продукта SCSC        *
*      и не поставляется отдельно. Права        *
*      на программный продукт SCSC              *
*      принадлежат компании A2 www.a2soft.ru    *
*											   	 *
*************************************************/

$UI = {
    _old: null,
    _resOld: null,
    FixPng: function(obj)
    {
        if (navigator.userAgent.indexOf("IE 6") != -1)
        {
            var obj = obj ? obj : document;
            var _imgs = obj.getElementsByTagName("img");
            for (var i = 0; i < _imgs.length; i++)
            {
                setTimeout(function()
                {
                    if (/\.png$/gi.test(this.src.toLowerCase()))
                    {
                        var _img = this;
                        var h = _img.height;
                        var w = _img.width;
                        if (h && w)
                        {
                            var src = _img.src;
                            _img.src = "resource/images/px.gif";
                            _img.style.width = w + "px";
                            _img.style.height = h + "px";
                            _img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', SizingMethod='scale')";
                        }
                    }
                } .bind(_imgs[i]), 1);
            }
        }
    },
    Wheel:
    {
        _handlers: {},
        Register: function(obj, formal, func, prevent)
        {
            $UI.Wheel._handlers[formal] = { obj: obj, func: func, prevent: prevent };
        },
        UnRegister: function(formal)
        {
            $UI.Wheel._handlers[formal] = null;
        },
        Process: function(event)
        {
            var delta = 0;
            var event = event ? event : window.event;
            var obj = $G.Event.Target(event);
            obj = obj.tagName ? obj : obj.parentNode;
            if (event.wheelDelta)
            {
                delta = event.wheelDelta / 120;
                if (window.opera) delta = -delta;
            } else if (event.detail)
            {
                delta = -event.detail / 3;
            }
            var prevent = false;
            if (delta)
            {
                for (var i in $UI.Wheel._handlers)
                {
                    if ($UI.Wheel._handlers[i] != null)
                    {
                        if ($G.IsChildOf($UI.Wheel._handlers[i].obj, obj, 5) || $UI.Wheel._handlers[i].obj == obj)
                        {
                            $UI.Wheel._handlers[i].func(delta);
                            prevent = prevent || $UI.Wheel._handlers[i].prevent;
                        }
                    }
                }
            }
            if (prevent)
            {
                if (event.preventDefault)
                    event.preventDefault();
                event.returnValue = false;
            }
        },
        Invoke: function()
        {
        },
        Init: function()
        {
            if (window.addEventListener)
                window.addEventListener('DOMMouseScroll', $UI.Wheel.Process, false);
            window.onmousewheel = document.onmousewheel = $UI.Wheel.Process;
        }
    },
    Hotkey:
	{
	    Keys:
		{
		    Ctrl: 17,
		    Alt: 18,
		    Space: 32,
		    Shift: 16,
		    CapsLock: 20,
		    Tab: 9,
		    Esc: 27,
		    Enter: 13,
		    ArrowLeft: 37,
		    ArrowRight: 39,
		    ArrowUp: 38,
		    ArrowDown: 40
		},
	    Pressed: new Array(),
	    Combinations: new Array(),
	    _old: null,
	    _oldU: null,
	    Init: function()
	    {
	        this._old = $G.Browser.Detect.gecko ? window.onkeydown : document.body.onkeydown;
	        if ($G.Browser.Detect.gecko)
	            window.onkeydown = $UI.Hotkey.Process.bind(this);
	        else
	            document.body.onkeydown = $UI.Hotkey.Process.bind(this);
	        var _oldU = $G.Browser.Detect.gecko ? window.onkeyup : document.body.onkeyup;
	        this._oldU = _oldU;
	        if ($G.Browser.Detect.gecko)
	            window.onkeyup = $UI.Hotkey.Clear.bind(this);
	        else
	            document.body.onkeyup = $UI.Hotkey.Clear.bind(this);
	        if ($G.Browser.Detect.ie)
	            try { document.execCommand("BackgroundImageCache", false, true); } catch (e) { };
	    },
	    UnRegister: function(keys, uid)
	    {
	        var array = new Array();
	        for (var i = 0; i < this.Combinations.length; i++)
	            if (!this.Compare(this.Combinations[i].keys, keys) && (uid != null ? (this.Combinations[i].uid != uid) : true))
	            array.push(this.Combinations[i]);
	        this.Combinations = array;
	    },
	    Register: function(keys, func, uid)
	    {
	        this.UnRegister(keys, uid);
	        this.Combinations.push({ keys: keys, func: func, uid: uid });
	        return func;
	    },
	    Clear: function(e)
	    {
	        this.Pressed = new Array();
	    },
	    Compare: function(val1, val2)
	    {
	        var res = true;
	        for (var i = 0; i < val1.length; i++)
	            res = res && (val1[i] == val2[i]);
	        return res;
	    },
	    GetFuncs: function(keys)
	    {
	        var result = new Array();
	        for (var i = 0; i < this.Combinations.length; i++)
	            if (this.Compare(this.Combinations[i].keys, keys))
	            result.push(this.Combinations[i].func);
	        return result;
	    },
	    Invoke: function(functions)
	    {
	        for (var i = 0; i < functions.length; i++)
	            functions[i]();
	    },
	    Process: function(e)
	    {
	        if (this._old)
	            this._old(e);
	        var _code = $G.GetKeyCode(e);
	        this.Pressed.push(_code);
	        this.Invoke(this.GetFuncs(this.Pressed));
	    }
	},
    Body: new UIControl(),
    Head: new UIControl(),
    Styles: null,
    Init: function()
    {
        //Инициализация модулей UI
        $UI.Hotkey.Init();
        this.Body.Content = this.Body.Holder = document.body;
        this.Head.Content = this.Head.Holder = document.getElementsByTagName("head")[0];
        // ---- из Resize Init ----
        $UI.FixPng();
        // ---- конец ----
        $UI.Wheel.Init();
        $UI.Collector = $G.Tag("div");
        $UI.Collector.style.display = "none";
    }
}
$UI._old = window.onload;
window.onload = function()
{
    if ($UI._old)
        $UI._old();
    $UI.Init();
}

function UIControl(_holder, _content)
{   
    this._defaultClassName = new String();
    this._operafix = $G.Tag("input");
    this.Parent = null;
    this.Controls = new Array();
    this.FromArguments = function(_holder, _content)
    {
        this.Holder = _holder;
        this.Content = _content ? _content : _holder;
    }
    this.FromArguments(_holder, _content);
    this.SetText = function(text)
    {
        if (this.Content.value != null)
            this.Content.value = text;
        else
            this.Content.innerHTML = text;
        return this;
    }
    this.GetText = function()
    {
        if (this.Content.value != null)
            return this.Content.value;
        return this.Content.innerHTML;
    }
    this.AddControl = function(control, anchor, before)
    {
        if (!UIControl.prototype.isPrototypeOf(control) && control.tagName != null)
            control = new A2.UI.Control(control);

        if (!this.Controls.contains(control))
        {
            if (!UIControl.prototype.isPrototypeOf(control))
            {
                return $G.Append(this.Content, control);
            }
            this.Controls.push(control);
            control.Parent = this;
            //Event-flow ;)
            if (control.OnInit)
                control.OnInit();
            if (control.Visualize)
                control.Visualize(anchor, before);
            if (control.OnLoad)
                control.OnLoad();
            if (this.OnChildAdded)
                this.OnChildAdded(control);
            return control;
        }
    }
    this.AddControls = function(array)
    {
        for (var i in array)
            this.AddControl(array[i]);
    }
    this.OnLoad = function() { }; // Срабатывает при загрузке
    this.OnUnload = function() { }; // Срабатывает при выгрузке	
    this.OnInit = function() { };
    this.OnResize = function() { };
    this.OnChildAdded = function() { }; // Срабатывает, если добавить контрол в данный контрол
    this.OnClearControls = function() { }; // Срабатывает, если вызвать метод ClearControls после того, как очистить коллекцию контролов
    this._onMoveStart = function()
    {
        for (var i = 0; i < this.Controls.length; i++)
            this.Controls[i]._onMoveStart.bind(this.Controls[i])();
        this.OnMoveStart();
    }
    this.OnMoveStart = function() { };
    this.Resize = function(size)
    {
        var _size;
        if (size == null)
            _size = new _UISize(this.Content.offsetWidth, this.Content.offsetHeight);
        else
            _size = new _UISize((this.Content.offsetWidth != 0 ? this.Content.offsetWidth : size.Width)
	                         , (this.Content.offsetHeight != 0 ? this.Content.offsetHeight : size.Height));
        this.OnResize(_size);
        for (var i = 0; i < this.Controls.length; i++)
            this.Controls[i].Resize.bind(this.Controls[i])(_size);
    }
    this.Visualize = function(anchor, before)
    {
        if (this.Parent)
            $G.Append(this.Parent.Content, this.Holder, anchor, before);
        else
            $G.Append(document.body, this.Holder, anchor, before);
    }
    this.GetControlByObject = function(obj)
    {
        for (var i = 0; i < this.Controls.length; i++)
        {
            if (this.Controls[i].Holder == obj)
                return this.Controls[i];
        }
        return null;
    }
    this.GetControlsByObject = function()
    {
        var result = new Array();
        for (var i = 0; i < this.Content.childNodes.length; i++)
        {
            var ctrl = this.GetControlByObject(this.Content.childNodes[i]);
            if (ctrl)
            {
                result.push(ctrl);
            }
        }
        return result;
    }
    this.GetControl = function(obj)
    {
        var result = null;
        for (var i = 0; i < this.Controls.length; i++)
        {
            if (this.Controls[i] == obj)
            {
                result = this.Controls[i];
                break;
            }
        }
        return result;
    }
    this.MoveControl = function(control, dest)
    {
        this.Controls.remove(control);
        dest.Controls.push(control);
        control.Parent = dest;
        control.Visualize();
    }
    this.RemoveControl = function(control)
    {
        this.Controls.remove(control);
        control.OnUnload();
        control.Dispose();
    }
    this.ClearControls = function()
    {
        while (this.Controls.length > 0)
        {
            this.RemoveControl(this.Controls[0]);
        }
        this.Controls = new Array();

        if (this.OnClearControls)
            this.OnClearControls();
    }
    this.ParentDeleted = function()
    {
        this.OnParentDeleted();
        for (var i = 0; i < this.Controls.length; i++)
        {
            this.Controls[i].ParentDeleted();
        }
        this.ClearInstance();
    }
    this.OnParentDeleted = function() { };
    this.Dispose = function()
    {
        this.Holder.style.display = "none";
        for (var i = 0; i < this.Controls.length; i++)
            this.Controls[i].ParentDeleted();
        $G.Append($UI.Collector, this.Holder);
        $UI.Collector.innerHTML = "";
        this.ClearInstance();
    }
    this.ClearInstance = function()
    {
        if (this.BeforeClear)
            this.BeforeClear();
        this.Holder = this.Content = this._operafix = this.Parent = null;
        for (var i in this)
        {
            this[i] = null;
        }
    }
    this.SetClass = function(className)
    {
        this.Holder.className = this._defaultClassName + " " + className;
        return this;
    }
    this.RemoveClassName = function(className)
    {
        this.Holder.className = this.Holder.className.replace(className, "");
    }
    this.Visible = function(st)
    {
        this.Holder.style.display = st;
        return this;
    }
    this.AddEvent = function(type, func)
    {
        $G.Event.Add(this.Holder, type, func);
        return this;
    }
    this.ContainsElement = function(elem)
    {
        var res = false;
        var elems1 = this.Holder.childNodes;
        var elems2 = this.Content.childNodes;
        for (var i = 0; i < elems1.length; i++)
        {
            if (elem == elems1[i])
            {
                res = true;
                break;
            }
        }
        for (var i = 0; i < elems2.length; i++)
        {
            if (elem == elems2[i])
            {
                res = true;
                break;
            }
        }
        if (!res)
        {
            for (var i = 0; i < this.Controls.length; i++)
            {
                res = this.Controls[i].ContainsElement(elem);
                if (res)
                    break;
            }
        }
        return res;
    }
    this.toString = function()
    {
        return ($G.Append($G.Tag("div"), this.Holder)).parentNode.innerHTML;
    }
}
function UISystemControl(_holder, _content)
{
    this.Controls = new Array();
    this.FromArguments(_holder, _content);
    this.Visualize = function()
    {
        if (this.Parent)
            this.Parent.Holder.appendChild(this.Holder);
        else
            document.body.appendChild(this.Holder);
    }
}
UISystemControl.prototype = new UIControl();

A2 = {
    UI: {
        Url: "",
        Calendar: function(onChange, date)
        {
            this.NextButton = { src: A2.UI.Url + "resource/images/calendarNext.png", width: "16", height: "16" };
            this.PreviousButton = { src: A2.UI.Url + "resource/images/calendarPrev.png", width: "16", height: "16" };
            this.Holder = this.Content = $G.Tag("div", "UICalendar");
            this.Controls = new Array();
            this.CurrentDate = (date || new Date());
            this.OnChange = onChange;

            this.BeforeClear = function()
            {
                this.NextButton = this.PreviousButton = this.CurrentDate = this.OnChange = null;
            }
            this.SelectDate = function(date, accept)
            {
                if ((this.Days.Controls.length == 49) && (date.getMonth() != this.CurrentDate.getMonth()))
                    this.RenderDate(date);
                else if ((this.Days.Controls.length == 12) && ($G.Date.Decade(date) != $G.Date.Decade(this.CurrentDate)))
                    this.RenderYear(date);
                else
                {
                    var _c = this.GetByDate(this.CurrentDate);
                    _c.Holder.className = _c.Holder.className.replace(" Selected", "");
                    _c = this.GetByDate(date);
                    _c.Holder.className += " Selected";
                }
                this.CurrentDate = date;
                this._focusFixer.focus();
                if (accept)
                    this.Accept();
            }
            this.GetByDate = function(date)
            {
                for (var i = 0; i < this.Days.Controls.length; i++)
                {
                    var _day = this.Days.Controls[i];
                    if (_day.Holder.className.indexOf("NotThis") == -1)
                        if (this.Days.Controls.length == 49)
                    {
                        if (_day.GetText() == date.getDate().toString())
                            return _day;
                    }
                    else if (this.Days.Controls.length == 12)
                    {
                        if (_day.GetText() == date.getFullYear().toString())
                            return _day;
                    }
                }
            }
            this.SelectNext = function()
            {
                var date = this.CurrentDate;
                var _wd = $G.Date.Clone(date);
                if (this.Days.Controls.length == 49)
                    _wd.setDate(_wd.getDate() + 1);
                else if (this.Days.Controls.length == 12)
                    _wd.setFullYear(_wd.getFullYear() + 1);
                this.SelectDate(_wd);
            }
            this.SelectPrevious = function()
            {
                var date = this.CurrentDate;
                var _wd = $G.Date.Clone(date);
                if (this.Days.Controls.length == 49)
                    _wd.setDate(_wd.getDate() - 1);
                else if (this.Days.Controls.length == 12)
                    _wd.setFullYear(_wd.getFullYear() - 1);
                this.SelectDate(_wd);
            }
            this.NextWeek = function()
            {
                var date = this.CurrentDate;
                var _wd = $G.Date.Clone(date);
                if (this.Days.Controls.length == 49)
                    _wd.setDate(_wd.getDate() + 7);
                else if (this.Days.Controls.length == 12)
                    _wd.setFullYear(_wd.getFullYear() + 4);
                this.SelectDate(_wd);
            }
            this.PreviousWeek = function()
            {
                var date = this.CurrentDate;
                var _wd = $G.Date.Clone(date);
                if (this.Days.Controls.length == 49)
                    _wd.setDate(_wd.getDate() - 7);
                else if (this.Days.Controls.length == 12)
                    _wd.setFullYear(_wd.getFullYear() - 4);
                this.SelectDate(_wd);
            }
            this.NextMonth = function()
            {
                var date = this.CurrentDate;
                var _wd = $G.Date.Clone(date);
                if (this.Days.Controls.length == 49)
                    _wd.setMonth(_wd.getMonth() + 1);
                else if (this.Days.Controls.length == 12)
                    _wd.setFullYear(_wd.getFullYear() + 10);
                this.SelectDate(_wd);
            }
            this.PreviousMonth = function()
            {
                var date = this.CurrentDate;
                var _wd = $G.Date.Clone(date);
                if (this.Days.Controls.length == 49)
                    _wd.setMonth(_wd.getMonth() - 1);
                else if (this.Days.Controls.length == 12)
                    _wd.setFullYear(_wd.getFullYear() - 10);
                this.SelectDate(_wd);
            }
            this.Accept = function()
            {
                if (this.OnChange)
                    this.OnChange(this.CurrentDate);
            }
            this.Rendered = false;
            this.RenderDate = function(date)
            {
                this.Rendered = false;
                this.Days.ClearControls();
                var _dow = $G.Date.DaysOfWeekShort;
                for (var i = 0; i < _dow.length; i++)
                    this.Days.AddControl(new A2.UI.Label(_dow[i], "Day Label floatLeft"));
                this.Month.SetText($G.Date.MonthEntity[date.getMonth() + 1] + ", " + date.getFullYear());
                this.Month.Holder.onclick = function()
                {
                    this.th.RenderYear(this.date);
                } .bind({ th: this, date: date });
                var _wd = $G.Date.Clone(date);
                _wd.setDate(1);
                for (var i = 0; i < 42; i++)
                {
                    var _td = $G.Date.Clone(_wd);
                    _td.setDate(i - (_wd.getDay() || 7) + 2);
                    var _day = this.Days.AddControl(new A2.UI.Label(_td.getDate(),
		                 "Day floatLeft" + ($G.Date.Compare(date, _td) ? " Selected" : "")
		                       + ($G.Date.Compare(_td, (new Date())) ? " Current" : "")
		                       + (_td.getMonth() != date.getMonth() ? " NotThis" : "")
		                    ));
                    $G.Event.Add(_day, "click", function()
                    {
                        this.th.SelectDate(this.date, true);
                    } .bind({ th: this, date: _td }));
                }
                this.Rendered = true;
            }
            this.RenderYear = function(date)
            {
                this.Rendered = false;
                this.Days.ClearControls();
                var _tyear = $G.Date.Decade(date);
                this.Month.SetText($G.Number.Norm(_tyear, 4) + " - " + $G.Number.Norm(_tyear + 9, 4));
                this.Month.Holder.onclick = function() { };
                for (var i = -1; i < 11; i++)
                {
                    var _ld = new Date();
                    _ld.setFullYear(_tyear + i);
                    var _year = this.Days.AddControl(new A2.UI.Label(_ld.getFullYear(), "Day Year floatLeft" +
		                  (_ld.getFullYear() == date.getFullYear() ? " Selected" : "")
		                + (_ld.getFullYear() == (new Date()).getFullYear() ? " Current" : "")
		                + ($G.Date.Decade(_ld) != $G.Date.Decade(date) ? " NotThis" : "")
		                ));
                    $G.Event.Add(_year, "click", function()
                    {
                        this.th.SelectDate(this.date, false);
                        this.th.RenderDate(this.date);
                        document.body.onclick = function()
                        {
                            document.body.onclick = $E.BodyClick.bind(this);
                        } .bind(this.th);
                    } .bind({ th: this, date: _ld }));
                }
                this.Rendered = true;
            }
            var _header = this.AddControl(new A2.UI.Control($G.Tag("div", "Header")));
            var _prev = _header.AddControl(new A2.UI.Image(this.PreviousButton, "Button floatLeft"));
            $G.Event.Add(_prev, "click", function()
            {
                this.PreviousMonth();
            } .bind(this));
            this.Month = _header.AddControl(new A2.UI.Label("Январь", "Month floatLeft"));
            var _next = _header.AddControl(new A2.UI.Image(this.NextButton, "Button floatLeft"));
            $G.Event.Add(_next, "click", function()
            {
                this.NextMonth();
            } .bind(this));
            this.Days = this.AddControl(new A2.UI.Control($G.Tag("div", "DaysContainer floatLeft")));
            this.OnLoad = function()
            {
                this.RenderDate(this.CurrentDate);
                $UI.Hotkey.Register([$UI.Hotkey.Keys.ArrowLeft], function()
                {
                    this.SelectPrevious();
                } .bind(this), "CalendarLeft");
                $UI.Hotkey.Register([$UI.Hotkey.Keys.ArrowRight], function()
                {
                    this.SelectNext();
                } .bind(this), "CalendarRight");
                $UI.Hotkey.Register([$UI.Hotkey.Keys.ArrowDown], function()
                {
                    this.NextWeek();
                } .bind(this), "CalendarDown");
                $UI.Hotkey.Register([$UI.Hotkey.Keys.ArrowUp], function()
                {
                    this.PreviousWeek();
                } .bind(this), "CalendarUp");
                $UI.Hotkey.Register([$UI.Hotkey.Keys.Enter], function()
                {
                    if (this.Days.Controls.length == 49 && this.Accept)
                        this.Accept();
                    else
                        this.RenderDate(this.CurrentDate);
                } .bind(this), "CalendarEnter");
                this.OnParentDeleted = function()
                {
                    this.OnUnload();
                }
            }
            this.OnUnload = function()
            {
                $UI.Hotkey.UnRegister([], "CalendarLeft");
                $UI.Hotkey.UnRegister([], "CalendarRight");
                $UI.Hotkey.UnRegister([], "CalendarUp");
                $UI.Hotkey.UnRegister([], "CalendarDown");
                $UI.Hotkey.UnRegister([], "CalendarEnter");
            }
            this._focusFixer = $G.Append(this.Holder, $G.Tag("input", "almostHidden", { type: "text" }));
        },
        Image: function(obj, css, onLoad)
        {
            this.Holder = this.Content = $G.Tag("img");
            this.OnImageLoad = Function.prototype.isPrototypeOf(css) ? css : onLoad ? onLoad : function() { };
            this._ieIntrval = null;
            this.Loaded = false;
            this._ieOnLoad = function()
            {
                this._ieIntrval = setInterval(function()
                {
                    if (!this.Loaded)
                    {
                        if (this.Holder.complete)
                        {
                            this.Loaded = true;
                            this.OnImageLoad();
                            clearInterval(this._ieIntrval);
                        }
                    }
                } .bind(this), 50);
            }
            this.BeforeClear = function()
            {
                clearInterval(this._ieIntrval);
            }
            this.SetImage = function(_obj)
            {
                this.Loaded = false;
                if ($G.Browser.Detect.ie)
                {
                    this._ieOnLoad();
                }
                this.Holder.onload = function() { this.Loaded = true; this.OnImageLoad(); } .bind(this);

                if ($G.isString(_obj))
                    this.SetSrc(_obj);
                else
                {
                    $G.Extend(this.Holder, _obj, "");
                    this.SetSrc(_obj.src);
                    if ($G.Browser.Detect.ie)
                    {
                        if (_obj.width)
                            this.Holder.width = _obj.width;
                        if (_obj.height)
                            this.Holder.height = _obj.height;
                    }
                }
            }
            this.SetSrc = function(src)
            {
                if ((src.toLocaleLowerCase().indexOf(".png") != -1) && ($G.Browser.Detect.ie && !$G.Browser.Detect.ie7))
                {
                    this.Holder.style.background = "";
                    this.Holder.style.filter = "";
                    this.Holder.src = "/resource/px.gif";
                    this.Holder.style.background = "url(/resource/px.gif) repeat left top";
                    this.Holder.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', SizingMethod='scale')";
                }
                else
                    this.Holder.src = src;
            }
            if (obj)
                this.SetImage(obj);
            this.SetClass(css || "");
        },
        SystemControl: UISystemControl,
        Control: UIControl
    },
    Init: function()
    {
        A2.UI.Calendar.prototype = new A2.UI.Control();
        A2.UI.Image.prototype = new A2.UI.Control();
    }
}
function _UISize(w, h)
{
    this.Width = w ? w : 0;
    this.Height = h ? h : 0;
}
A2.Init();