﻿///<reference path="global.js" />
///<reference path="effects.js" />
///<reference path="rm.js" />
//Класс-обертка для контрола
function ctrl(obj) {
    this.obj = obj || $G.Tag("div");
    this.enabled = $G.GetAttribute(this.obj, "enabled");
    this.isRequired = ($G.GetAttribute(this.obj, "required") == "true");
    if (this.isRequired) {
        $G.ClassName.Replace(this.obj, "required", "required");
    }
    var _inp = this.obj.inp || $G.GetAttribute(this.obj, "inp") || "";
    if (_inp) {
        this.inp = $G.GET(this.obj, _inp);
    }
    this.disabledClass = "ctrl-disabled";
    this.enable = function () {
        $G.ClassName.Replace(this.obj, this.disabledClass, "");
    } .bind(this);
    this.disable = function () {
        $G.ClassName.Replace(this.obj, this.disabledClass, this.disabledClass);
    } .bind(this);
    if (this.enabled == "false") {
        this.disable();
    }
    this.disabled = function () {
        return $G.ClassName.Has(this.obj, this.disabledClass);
    }
    this.forctrl = this.obj["for"] || $G.GetAttribute(this.obj, "for") || "";
    this.pgroup = $G.GetAttribute(this.obj, "pgroup");
    this.pgroup = this.pgroup ? this.pgroup.split(",") : [];
    this.compound = $G.GetAttribute(this.obj, "compound");
    this.name = this.obj.name || $G.GetAttribute(this.obj, "name");
    this.add = $G.GetAttribute(this.obj, "add");
    this._changes = [];
    this.addOnChange = function (func, key) {
        this.onChange = function () {
            for (var i = 0; i < this._changes.length; i++) {
                this._changes[i].f();
            }
        } .bind(this);
        for (var i = 0; i < this._changes.length; i++) {
            if (key && key == this._changes[i].key) {
                this._changes[i].f = func;
                return;
            }
        }
        this._changes.push({ f: func, key: key });
    } .bind(this);
    this.removeOnChange = function (key) {
        var a = this._changes;
        for (var i = 0; i < a.length; i++) {
            if (key && key == a[i].key) {
                this._changes = this._changes.without(a[i]);
                break;
            }
        }
    } .bind(this);
    this.onChange = function () { };
    this.change = function () {
        if (!this.disabled()) {
            var val = this.getValue();
            if (this.cType != "compound") {
                if (!val || ($CS.emptyString(val) && !(this.empty && val == this.empty))) {
                    this.changed = false;
                }
                else {
                    this.changed = true;
                }
            }
            else
                this.changed = true;
            this.onChange();
        }
    } .bind(this);
    this.setChanged = function (c) {
        this.changed = !!c;
    } .bind(this);
    this.init = function () {
        if (this.compound) {
            if (this.cType != "compound") {
                var cmpds = this.compound.split(".");
                var group = null;
                var c = null;
                for (var i = 0; i < cmpds.length; i++) {
                    group = $CS.ctrls.compound(cmpds[i], group);
                    if (this.pgroup) {
                        group.pgroup = this.pgroup;
                    }
                    if (i == cmpds.length - 1) {
                        this.onChange = function () {
                            this.change();
                        } .bind(group);
                        group.options.push(this);
                    }
                }
            }
            this.nopush = true;
        }
        if (!$CS.dispatcher.contains(this)) {
            for (var i in $CS.ctrls) {
                if ($G.ClassName.Has(this.obj, i) && $G.Is($CS.ctrls[i], Function)) {
                    this.cType = i;
                    $CS.ctrls[i](this);
                }
            }
            if (!this.nopush) {
                $CS.clearByName(this);
                $CS.dispatcher.push(this);
            }
        }
        if (this.forctrl) {
            if (this.initfor) {
                this.initfor();
            }
            else {
                this.addOnChange(function () {
                    var c = $CS.get(this.forctrl);
                    if (c) {
                        c.setValue(this.getValue());
                    }
                } .bind(this));
                var c = $CS.get(this.forctrl);
                if (c) {
                    this.setValue(c.getValue());
                }
            }
        }
    } .bind(this);

    this.setValue = function (val) {
        if (this.value) {
            this.value = val;
        } else if (this.obj.value != null) {
            this.obj.value = val;
        }
    } .bind(this);
    this.getValue = function () {
        var val = (this.value == null ? this.obj.value : this.value);
        val = val == "undefined" ? "" : val;
        return val + (this.add ? " " + this.add : "");
    } .bind(this);
    this.beforeDispose = function () {
    }
    this.dispose = function () {
        if (this.beforeDispose) {
            this.beforeDispose();
        }
        if (this.obj && this.obj.parentNode) {
            this.obj.parentNode.removeChild(this.obj);
            this.obj = null;
        }
        if (this.compound) {
            $CS.get(this.compound).options = $CS.get(this.compound).options.without(this);
        }
        else {
            $CS.dispatcher = $CS.dispatcher.without(this);
        }
    } .bind(this);
    this.events = {};
    this.addEvent = function (evnt, func, key) {
        var evnt = $G.Is(evnt, Array) ? evnt : [evnt];
        for (var i = 0; i < evnt.length; i++) {
            if (!this.events[evnt[i]]) {
                this.obj["on" + evnt[i]] = function (e) {
                    for (var i in this.th.events[this.evnt]) {
                        if (this.th.events[this.evnt][i] && $G.Is(this.th.events[this.evnt][i], Function)) {
                            this.th.events[this.evnt][i](e);
                        }
                    }
                } .bind({ th: this, evnt: evnt[i] });
                this.events[evnt[i]] = {};
            }
            this.events[evnt[i]][key] = func;
        }
    } .bind(this);
}
var $CS = {
    slides: [], //Массив-диспетчер выпадающих дивов
    toServer: function (form, group) {
        var g = $CS.getGroup(group);
        if (g && g.length > 0) {
            for (var i = 0; i < g.length; i++) {
                if (!g[i].inp)
                    g[i].inp = $G.Append(form, $G.Tag("input", { type: "hidden", name: g[i].name }));
                g[i].inp.value = g[i].cType == "check" ? g[i].checked().toString() : g[i].getValue();

            }
        }
    },
    Init: function () {
        $CS.onKeyUp = document.body.onmouseup;
        document.body.onmouseup = function (e) {
            if ($CS.onKeyUp)
                $CS.onKeyUp(e);
            var t = $G.Event.Target(e);
            for (var i = 0; i < $CS.slides.length; i++) {
                var slide = $CS.slides[i];
                if (slide && slide != t) {
                    if (!slide.hidden) {
                        if ($G.IsChildOf(slide, t, 5)) {
                            if (slide.onSelect) {
                                slide.onSelect(t);
                            }
                            if (slide.noInnerClose) {
                                continue;
                            }
                        }
                        slide.style.height = "0";
                        slide.style.display = "none";
                        if (slide.onClose)
                            slide.onClose();
                        slide.hidden = true;
                    }
                }
            }
            //$nn.Tip.Hide(t);
        }
    },
    SlideSelector: function (obj, onSelect, a, arr, disp, onClose, onOpen) {
        if (obj) {
            obj.style.display = "block";
            obj.onSelect = onSelect;
            if (arr) {
                obj.innerHTML = "";
                var arr = $G.Is(arr, Function) ? arr() : $G.Is(arr, Array) ? arr : [arr];
                for (var i = 0; i < arr.length; i++) {
                    var val = $G.IsString(arr[i]) ? { name: arr[i], id: -1} : arr[i];
                    $G.Append(obj, $G.Tag("a", { href: "javascript://" + (val.name || val.title) + ";", value: val.id }, null, (val.name || val.title)));
                }
            }
            if (a) {
                $G.ClassName.Replace(a, "", "expand");
                obj.style.left = a.offsetLeft + "px";
                if ($G.IsChildOf($G.GET("#form"), obj, 10)) {
                    obj.style.marginTop = (a.offsetTop - a.parentNode.offsetTop + a.offsetHeight) + "px";
                }
                obj.onClose = function () {
                    $G.ClassName.Replace(this, "expand", "");
                } .bind(a);
            }
            if (!$CS.slides.contains(obj)) {
                $CS.slides.push(obj);
            }
            obj.hidden = false;
            if ($G.GetStyle(obj, "height", true) == 0) {
                obj.style.height = "0px";
                var disp = disp ? $G.Is(disp, Function) ? disp() : disp : 235;
                //$e.hiddenBy = obj;
                if (onClose)
                    obj.onClose = onClose;
                $FX.Time(500).Interval(10).AnimateStyle(obj, "height", disp, disp, onOpen, null, "OpenSelector");
            }
        }
    },
    dispatcher: [],
    emptyString: function (str) {
        return (str == "" || str == "undefined");
    },
    clearByName: function (c) {
        var arr = $CS.dispatcher;
        for (var i = 0; i < arr.length; i++) {
            if (c.name && arr[i].name == c.name) {
                arr[i].dispose();
            }
        }
    },
    getGroup: function (group) {
        var res = [];
        for (var i = 0; i < $CS.dispatcher.length; i++) {
            if ($CS.dispatcher[i].pgroup.contains(group)) {
                res.push($CS.dispatcher[i]);
            }
        }
        return res;
    },
    init: function (obj, except) {
        var except = except || [];
        var cs;
        //        if ($G.ClassName.Has(obj, "ctrl"))
        //            cs = [obj];
        //        else
        cs = $G.Get.ByClass(obj, "ctrl");
        for (var i = 0; i < cs.length; i++) {
            if (!except.contains($G.GetAttribute(cs[i], "name").toString().toLocaleLowerCase())) {
                (new ctrl(cs[i])).init();
            }
        }
    },
    get: function (name) {
        var name = name.split(".");
        var _c = null;
        for (var n = 0; n < name.length; n++) {
            if (_c == null) {
                for (var i = 0; i < $CS.dispatcher.length; i++) {
                    var c = $CS.dispatcher[i];
                    if (c && c.name == name[n]) {
                        _c = c;
                    }
                }
            }
            else {
                if (_c.cType != "compound") {
                    return null;
                }
                var opts = _c.options;
                var __c = _c;
                for (var i = 0; i < opts.length; i++) {
                    var c = opts[i];
                    if (c && c.name == name[n]) {
                        _c = c;
                        break;
                    }
                }
                if (_c && _c == __c) {
                    return null;
                }
            }
        }
        return _c;
    },
    byName: function (arr, name) {
        for (var i = 0; i < arr.length; i++) {
            if (arr[i].name == name)
                return arr[i];
        }
        return null;
    },
    ctrls: {
        input: function (c) {
            c.empty = c.obj.empty || $G.GetAttribute(c.obj, "empty");
            c.reg = c.obj.validate || $G.GetAttribute(c.obj, "validate") || "";
            c.validate = function () {
                var val = this.getValue();
                if (this.reg && val && !$CS.emptyString(val)) {
                    return (new RegExp(this.reg)).test(val) ? { res: true} : { res: false, text: "Поле %label% заполнено не верно" };
                }
                return { res: true };
            } .bind(c);
            if (c.empty) {
                c.addEvent("focus", function (e) {
                    var val = this.obj.value;
                    $G.ClassName.Replace(this.obj, "empty", "");
                    if (val == this.empty) {
                        this.obj.value = "";
                    }
                } .bind(c), "maskEmpty");
            }
            c.addEvent("blur", function (e) {
                var val = this.obj.value;
                if (this.empty) {
                    if (val == this.empty || !val) {
                        this.obj.value = this.empty;
                        $G.ClassName.Replace(this.obj, "", "empty");
                    }
                }
                this.change();
            } .bind(c), "maskEmpty");
            c.disable = function () {
                $G.ClassName.Replace(this.obj, this.disabledClass, this.disabledClass);
                this.obj.disabled = true;
            } .bind(c);
            c.enable = function () {
                $G.ClassName.Replace(this.obj, this.disabledClass, "");
                this.obj.disabled = false;
            } .bind(c);
            if (c.empty) {
                if (c.obj.value == c.empty || !c.obj.value) {
                    c.obj.value = c.empty;
                    $G.ClassName.Replace(c.obj, "", "empty");
                }
            }
            c.getValue = function () {
                if (this.empty && this.obj.value == this.empty)
                    return "" + (this.add ? " " + this.add : "");
                else
                    return this.obj.value + (this.add ? " " + this.add : "");
            } .bind(c);
            c.set = function (val) {
                if (this.empty && (val == this.empty || $CS.emptyString(val)))
                    this.obj.value = this.empty;
                else
                    this.obj.value = val;
            } .bind(c);
        },
        check: function (c, sel, desel) {
            var css = ($G.GetAttribute(c.obj, "css") || "").split(",");
            var sel = sel;
            var desel = desel;
            if (!sel && !desel && css.length == 2) {
                sel = css[0];
                desel = css[1];
            }
            c.initfor = function () {
                this.addOnChange(function () {
                    var c = $CS.get(this.forctrl);
                    if (c) {
                        c.setValue(this.checked() ? "true" : "false");
                    }
                } .bind(this));
                var c = $CS.get(this.forctrl);
                if (c) {
                    if (c.getValue() == "true") {
                        this.check();
                    }
                    else {
                        this.unCheck();
                    }
                }
            } .bind(c);
            c.disabledClass = "check-disabled";
            c.value = c.obj.value || $G.GetAttribute(c.obj, "value");
            c.sel = sel || $RM.ctrls.check.selected;
            c.desel = desel || $RM.ctrls.check.deselected;
            c.check = function () {
                $G.ClassName.Replace(this.obj, [this.sel, this.desel], this.sel);
            } .bind(c);
            c.unCheck = function () {
                $G.ClassName.Replace(this.obj, [this.sel, this.desel], this.desel);
            } .bind(c);
            c.toggle = function () {
                if ($G.ClassName.Has(this.obj, this.sel))
                    this.unCheck();
                else
                    this.check();
                this.change();
            } .bind(c);
            c.obj.onclick = function () {
                if (!this.disabled()) {
                    this.toggle();
                }
                //this.onChange();
            } .bind(c);
            c.checked = function () {
                return $G.ClassName.Has(this.obj, this.sel);
            } .bind(c);
            if (c.obj.checked == true) {
                c.check();
            }
            c.getValue = function () {
                return this.checked();
            } .bind(c);
            c.set = function (val) {
                if (val && val != "false") {
                    this.check();
                }
                else {
                    this.unCheck();
                }
            } .bind(c);
            c.setValue = c.set;
        },
        compound: function (name, g) {
            var group = null;
            group = g ? g.get(name) : $CS.get(name);
            if (!group) {
                group = new ctrl();
                group.cType = "compound";
                group.name = name;
                if (g) { group.compound = (g.compound ? g.compound + "." : "") + g.name; g.options.push(group); }

                group.options = [];
                group.get = function (name) {
                    for (var i = 0; i < this.options.length; i++) {
                        if (this.options[i].name == name)
                            return this.options[i];
                    }
                } .bind(group);
                group.dispose = function () {
                    var opts = this.options;
                    for (var i = 0; i < opts.length; i++) {
                        opts[i].dispose();
                    }
                    if (!this.compound) {
                        $CS.dispatcher = $CS.dispatcher.without(this);
                    }
                    else {
                        var g = $CS.get(this.compound);
                        if (g) {
                            g.options = g.options.without(this);
                        }
                    }
                } .bind(group);
                group.setChanged = function (c) {
                    for (var i = 0; i < this.options.length; i++) {
                        if (this.options[i].setChanged)
                            this.options[i].setChanged(c);
                    }
                    this.changed = !!c;
                } .bind(group);
                group.getValue = function () {
                    var res = {};
                    if (this.options[0].name == "min" || this.options[0].name == "max") {
                        if (this.options[0].down) {
                            var max = $CS.byName(this.options, "max").getValue();
                            var min = $CS.byName(this.options, "min").getValue();
                            if (!$CS.emptyString(max)) {
                                res.max = "31.12." + max;
                                if ($CS.emptyString(min))
                                    res.min = "1.1.1900";
                            }
                            if (!$CS.emptyString(min)) {
                                res.min = "1.1." + min;
                                if ($CS.emptyString(max))
                                    res.max = "31.12.2100";
                            }
                            if ($CS.emptyString(max) && $CS.emptyString(min)) {
                                res = "";
                            }
                        }
                        else {
                            var max = $CS.byName(this.options, "max").getValue();
                            var min = $CS.byName(this.options, "min").getValue();
                            var add = this.options[0].add || "";
                            if (max.trim() != add) {
                                res.max = max;
                                if (min.trim() == add)
                                    res.min = "-999999999 " + add;
                            }
                            if (min.trim() != add) {
                                res.min = min;
                                if (max.trim() == add)
                                    res.max = "999999999 " + add;
                            }
                            if (max.trim() == add && min.trim() == add) {
                                res = "";
                            }
                        }
                    }
                    else {
                        for (var i = 0; i < this.options.length; i++) {
                            res[this.options[i].name] = this.options[i].getValue() || "";
                        }
                    }
                    return res;
                } .bind(group);
                group.init();
                group.setEmpty = function () {
                    for (var i = 0; i < this.options.length; i++) {
                        if (this.options[i].setEmpty) {
                            this.options[i].setEmpty();
                        }
                        else
                            this.options[i].set("");
                    }
                } .bind(group);
                group.set = function (val) {
                    for (var i = 0; i < this.options.length; i++) {
                        if (val[this.options[i].name])
                            this.options[i].set(val[this.options[i].name]);
                    }
                } .bind(group);
            }
            return group;
        },
        radio: function (c) {
            var group = $CS.ctrls.radioGroup($G.GetAttribute(c.obj, "rgroup"), c.compound);
            var css = ($G.GetAttribute(c.obj, "css") || "").split(",");
            if (css.length == 2) {
                c.sel = css[0];
                c.desel = css[1];
            }
            else {
                c.sel = $RM.ctrls.radio.selected;
                c.desel = $RM.ctrls.radio.deselected;
            }
            $CS.ctrls.check(c, c.sel, c.desel);
            group.options.push(c);
            c.getValue = function () {
                return this.value;
            } .bind(c);
            c.group = group;
            c.toggle = function () {
                if (!this.disabled()) {
                    if (!this.checked())
                        this.check(true);
                }
            } .bind(c);
            c.check = function (evnt) {
                this.group.deselect();
                $G.ClassName.Replace(this.obj, [this.sel, this.desel], this.sel);
                if (evnt)
                    this.group.change();
            } .bind(c);
            c.beforeDispose = function () {
                if (this.group) {
                    this.group.options = this.group.options.without(this);
                }
            } .bind(c);
            c.disabled = function () {
                return $G.ClassName.Has(this.obj, "disabled");
            } .bind(c);
            c.disable = function () {
                $G.ClassName.Replace(this.obj, "disabled", "disabled");
                return this;
            } .bind(c);
            c.enable = function () {
                $G.ClassName.Replace(this.obj, "disabled", "");
                return this;
            } .bind(c);
        },
        radioGroup: function (name, compound) {
            var group = null;
            group = $CS.get(compound ? compound + "." + name : name);
            if (!group) {
                group = new ctrl();
                group.name = name;
                group.compound = compound;
                group.options = [];
                group.disable = function () {
                    for (var i = 0; i < this.options.length; i++) {
                        this.options[i].disable();
                    }
                } .bind(group);
                group.enable = function () {
                    for (var i = 0; i < this.options.length; i++) {
                        this.options[i].enable();
                    }
                } .bind(group);
                group.dispose = function () {
                    var opts = this.options;
                    for (var i = 0; i < opts.length; i++) {
                        opts[i].dispose();
                    }
                    if (!this.compound) {
                        $CS.dispatcher = $CS.dispatcher.without(this);
                    }
                    else {
                        var g = $CS.get(this.compound);
                        if (g) {
                            g.options = g.options.without(this);
                        }
                    }
                } .bind(group);
                group.getValue = function () {
                    for (var i = 0; i < this.options.length; i++) {
                        if ($G.ClassName.Has(this.options[i].obj, this.options[i].sel)) {
                            return this.options[i].getValue();
                        }
                    }
                } .bind(group);
                group.deselect = function () {
                    for (var i = 0; i < this.options.length; i++) {
                        this.options[i].unCheck();
                    }
                } .bind(group);
                group.set = function (val, change) {
                    for (var i = 0; i < this.options.length; i++) {
                        if (val == this.options[i].getValue()) {
                            this.options[i].check(change);
                            break;
                        }
                    }
                } .bind(group);
                group.init();
            }
            return group;
        },
        select: function (c) {
            var _o = ($G.GetAttribute(c.obj, "options") || "").split(",");
            c.tiles = +($G.GetAttribute(c.obj, "tiles") || "6");
            c.tileSize = +($G.GetAttribute(c.obj, "tilessize") || "28");
            var options = [];
            for (var i = 0; i < _o.length; i++) {
                var _s = _o[i].split(":");
                options.push({ text: _s[0], value: (_s.length == 2 ? _s[1] : null) });
            }
            var css = $G.GetAttribute(c.obj, "css");
            c.options = options;
            c.multy = $G.GetAttribute(c.obj, "multy") == "true";
            c.prefix = $G.GetAttribute(c.obj, "prefix");
            c.addOther = function () {
                this.removeOther();
                this.other = $G.Append($G.GET(this.obj, "up:1"), $G.Tag("input", "input mt10"));
            } .bind(c);
            c.removeOther = function () {
                if (this.other) {
                    this.other.parentNode.removeChild(this.other);
                    this.other = null;
                }
            } .bind(c);
            var v = c.obj.innerHTML.toString().trim();
            var _v = v.split(":");
            if (_v.length > 1) {
                c.value = _v[1];
            }
            c.obj.innerHTML = "";
            c.wid = c.obj.offsetWidth || $G.GetStyle(c.obj, "width", true) || 180;
            c.val = $G.Append(c.obj, $G.Tag("span", null, null, $G.ShrinkStr(_v[0], Math.round((c.wid - 40) / 7), "&hellip;")));
            c.down = $G.Append(c.obj, $G.Tag("div", "select-down"), c.val, true);
            if (css)
                $G.ClassName.Replace(c.down, "", css);
            c.down.style.width = ((c.obj.offsetWidth || 2) - 2) + "px";
            c.down.style.marginLeft = (($G.GetStyle(c.obj, "paddingLeft", true) + (($G.Browser.Detect.ie && !$G.Browser.Detect.ie9) ? 1 : 6)) * -1) + "px";
            c.down.style.display = "none";
            c.down.style.height = "0px";
            if (c.multy)
                c.down.noInnerClose = true;

            c.formList = function (options) {
                var m = this.tiles * this.tileSize;
                this.disp = options.length * this.tileSize > m ? m : options.length * this.tileSize;
                this.down.innerHTML = "";
                this.down.style.width = "0px";
                this.down.style.display = "";
                for (var i = 0; i < options.length; i++) {
                    var val = (options[i].value) ? options[i].value : (options[i].value == "" ? "undefined" : (options[i].text || options[i].title));
                    var a = $G.Append(this.down, $G.Tag("a", { href: "javascript://;", value: val }, null, options[i].text || options[i].title));
                    //                    if (i == options.length - 1) {
                    //                        $G.ClassName.Replace(a, "", "nobrd");
                    //                    }
                    var w = Math.round(options[i].text.length * 6.3) + 30;
                    if (this.down.offsetWidth < w) {
                        this.down.style.width = w + "px";
                    }
                    //a.style.width = (options[i].text.length * 10) + "px";
                    if (this.multy && !$CS.emptyString(a.value)) {
                        $G.ClassName.Replace(a, "", "des");
                    }
                }
                this.down.style.display = "none";
            } .bind(c);
            c.formList(options);
            c.removeOption = function (value) {
                var opts = $G.Get.ByTag(this.down, "a");
                for (var i = 0; i < opts.length; i++) {
                    if (opts[i].value == value) {
                        opts[i].parentNode.removeChild(opts[i]);
                    }
                }
            } .bind(c);
            c.onBeforeSlide = function () { };
            c.obj.onclick = function (e) {
                if (!this.disabled()) {
                    var t = $G.Event.Target(e);
                    if (t) {
                        if (!$G.IsChildOf(this.down, t, 5)) {
                            if (this.onBeforeSlide) {
                                this.onBeforeSlide();
                            }
                            this.down.style.display = "block";
                            var opts = $G.Get.ByTag(this.down, "a");
                            var w = (this.obj.offsetWidth || 2);
                            if (this.down.offsetWidth > w) {
                                w = this.down.offsetWidth;
                            }
                            this.down.style.width = (w - 2) + "px";
                            this.down.style.marginTop = (this.obj.offsetHeight - ($G.Browser.Detect.ie ? 2 : 2)) + "px";
                            $CS.SlideSelector(this.down, function (what) {
                                if (this.multy) {
                                    if ($CS.emptyString(what.value)) {
                                        this.clearmulty();
                                    }
                                    else {
                                        if ($G.ClassName.Has(what, "sel")) {
                                            $G.ClassName.Replace(what, ["des", "sel"], "des");
                                        }
                                        else
                                            $G.ClassName.Replace(what, ["des", "sel"], "sel");
                                    }
                                    this.updmulty();
                                }
                                else
                                    this.set(what.innerHTML, what.value);
                                this.change();
                            } .bind(this), null, null, this.disp, (this.onClose || function () { }));
                        }
                    }
                }
            } .bind(c);
            c.setEmpty = function () {
                if (!this.multy) {
                    var opt = $G.Get.ByTag(this.down, "a");
                    for (var i = 0; i < opt.length; i++) {
                        if ($CS.emptyString(opt[i].value)) {
                            this.set(opt[i].innerHTML, opt[i].value);
                            break;
                        }
                    }
                }
                else {
                    this.value = "";
                    this.val.innerHTML = "";
                }
            } .bind(c);
            c.clearmulty = function () {
                var opt = $G.Get.ByTag(this.down, "a");
                for (var i = 0; i < opt.length; i++) {
                    $G.ClassName.Replace(opt[i], ["sel", "des"], "des");
                }
            } .bind(c);
            c.checkmulty = function (val) {
                if (!$CS.emptyString(val)) {
                    var val = $G.IsString(val) ? val.split(",") : val;
                    var opt = $G.Get.ByTag(this.down, "a");
                    for (var i = 0; i < val.length; i++) {
                        for (var o = 0; o < opt.length; o++) {
                            if (opt[o].value.toString() == val[i]) {
                                $G.ClassName.Replace(opt[o], ["sel", "des"], "sel");
                                break;
                            }
                        }
                    }
                    this.updmulty();
                }
            } .bind(c);
            c.getTitle = function () {
                return this.val.innerHTML.toString().trim();
            } .bind(c);
            c.setmulty = function (opts, change) {
                if ($G.IsString(opts)) {
                    var opt = $G.Get.ByTag(this.down, "a");
                    var _o = opts.split(",");
                    for (var i = 0; i < _o.length; i++) {
                        var co = _o[i].split(":");
                        if (co.length > 0) {
                            for (var j = 0; j < opt.length; j++) {
                                if (opt[j].value == (co.length > 1 ? co[1] : co[0])) {
                                    $G.ClassName.Replace(opt[j], ["sel", "des"], ["sel"]);
                                    break;
                                }
                            }
                        }
                    }
                    this.updmulty();
                    if (change)
                        this.change();
                }
            } .bind(c);
            c.updmulty = function () {
                var opt = $G.Get.ByTag(this.down, "a");
                var val = [];
                var titles = [];
                for (var i = 0; i < opt.length; i++) {
                    if ($G.ClassName.Has(opt[i], "sel")) {
                        val.push(opt[i].value);
                        titles.push(opt[i].innerHTML.toString());
                    }
                }
                if (val.length == 0) {
                    this.setEmpty();
                }
                else if (val.length == 1) {
                    this.set(titles[0], val[0]);
                }
                else {
                    this.value = val.join(",");
                    this.val.innerHTML = "Выбрано <b>" + val.length + "</b> " + $G.Number.Format(val.length, "элемент", "", "а", "ов");
                }
            } .bind(c);
            c.set = function (title, value) {
                if (!value && $CS.emptyString(title)) {
                    this.setEmpty();
                }
                else {
                    var t = $G.ShrinkStr(title, Math.round((this.obj.offsetWidth - 40) / 8), "&hellip;")

                    this.val.innerHTML = t;
                    this.value = value;
                }
            } .bind(c);
            c.getValue = function () {
                if (this.other) {
                    return this.other.value;
                }
                return (this.value ? this.value : "undefined");

            } .bind(c);
            c.setValue = function (val, change) {
                if (!this.multy) {
                    var opt = $G.Get.ByTag(this.down, "a");
                    for (var i = 0; i < opt.length; i++) {
                        if (opt[i].value && opt[i].value.toString() == val.toString()) {
                            this.set(opt[i].innerHTML.toString(), opt[i].value.toString());
                            if (change == true)
                                this.change();
                            break;
                        }
                    }
                }
                else {
                    this.setmulty(val, true);
                }
            } .bind(c);
        },
        phones: function (c) {
            c.phones = [];
            c.single = c.obj.getAttribute("single") == "true";
            c.addPhone = function (p) {
                var _p = {};
                if (p && $G.IsString(p))
                    p = p.split(" ");
                if (!this.single) {
                    _p.btn = $G.Append(this.obj, $G.Tag("a", "btn-delete-phone fr", { href: "javascript://Удалить номер;", title: "Удалить номер" }), this.addBtn, true);
                    _p.btn.onclick = function () { this.th.removePhone(this.p); } .bind({ p: _p, th: this });
                }
                _p.country = $G.Append(this.obj, $G.Tag("input", "mr15 pl0 pr0 tac " + (this.single ? "" : "mb10"), { type: "text", maxlength: "5", value: (p && p.length == 3 ? p[0] : "") }), this.addBtn, true);
                _p.country.style.width = "40px";
                _p.city = $G.Append(this.obj, $G.Tag("input", "mr15 pl0 pr0 tac " + (this.single ? "" : "mb10"), { type: "text", maxlength: "5", value: (p && p.length == 3 ? p[1] : "") }), this.addBtn, true);
                _p.city.style.width = "40px";
                _p.phone = $G.Append(this.obj, $G.Tag("input", { type: "text", maxlength: "7", value: (p && p.length == 3 ? p[2] : "") }), this.addBtn, true);
                _p.phone.style.width = (124 + (this.single ? 31 : 0)) + "px";
                _p.cb = $G.Append(this.obj, $G.Tag("div", "cb"));
                $G.Event.Add(_p.country, "blur", function () { this.onChange(); } .bind(this));
                $G.Event.Add(_p.city, "blur", function () { this.onChange(); } .bind(this));
                $G.Event.Add(_p.phone, "blur", function () { this.onChange(); } .bind(this));
                this.phones.push(_p);
            } .bind(c);
            if (!c.single) {
                c.addBtn = $G.Append(c.obj, $G.Tag("a", "curtain tar", { href: "javascript://Добавить номер;", title: "Добавить номер телефона" }, "+ добавить телефон"));
                c.addBtn.onclick = c.addPhone;
            }
            c.removePhone = function (p, onlynode) {
                if (p) {
                    if (onlynode != true)
                        this.phones = this.phones.without(p);
                    p.btn.parentNode.removeChild(p.btn);
                    p.country.parentNode.removeChild(p.country);
                    p.city.parentNode.removeChild(p.city);
                    p.phone.parentNode.removeChild(p.phone);
                    p.cb.parentNode.removeChild(p.cb);
                }
            } .bind(c);
            c.validate = function () {
                var val = this.getValue();
                if (!val && this.isRequired)
                    return { res: false, text: "Поле %label% не заполнено" };
                if (val) {
                    val = val.split(",");
                    for (var i = 0; i < val.length; i++) {
                        if (val[i] && !(new RegExp("^[0-9]{1,4} [0-9]{2,5} [0-9]{4,7}$", "gi")).test(val[i])) {
                            return { res: false, text: "Поле %label% заполнено не корректно" };
                        }
                    }
                }
                return { res: true };
            } .bind(c);
            c.getValue = function () {
                var res = [];
                for (var i = 0; i < this.phones.length; i++) {
                    res.push([this.phones[i].country.value.replace(/[\-\+\ ]+?/gi, ""),
                              this.phones[i].city.value.replace(/[\-\+\ ]+?/gi, ""),
                              this.phones[i].phone.value.replace(/[\-\+\ ]+?/gi, "")
                             ].join(" "));
                }
                return res.join(",").trim();
            } .bind(c);
            c.setValue = function (str) {
                var str = (str || "").split(",");
                for (var i = 0; i < this.phones.length; i++) {
                    this.removePhone(this.phones[i], true);
                }
                this.phones = [];
                for (var i = 0; i < str.length; i++) {
                    this.addPhone(str[i]);
                }
            } .bind(c);
            c.setValue($G.GetAttribute(c.obj, "value") || "");
        },
        crumb: function (c) {
            c.levels = c.obj.getAttribute("levels").toString().split(",");
            c.regions = [];
            c.objs = [];
            c.downs = [];
            c.selected = [];
            c.getValue = function (level) {
                for (var i = this.selected.length - 1; i >= 0; i--) {
                    if (this.selected[i] != null) {
                        return this.selected[i];
                    }
                }
                return null;
            } .bind(c);
            c.setLevel = function (arr, level) {
                var level = level || 0;
                if (level < this.levels.length) {

                    this.regions[level] = arr;
                    if (arr.length > 0) {
                        this.objs[level].innerHTML = "Выберите&nbsp;" + this.levels[level];
                        this.objs[level].style.display = "";
                        this.selected[level] = null;
                        if (level != this.levels.length - 1) {
                            for (var i = level + 1; i < this.levels.length; i++) {
                                this.regions[i] = [];
                                this.objs[i].innerHTML = "Выберите&nbsp;" + this.levels[i];
                                this.objs[i].style.display = "none";
                                this.selected[i] = null;
                            }
                        }

                    } else {
                        this.objs[level].style.display = "none";
                        if (level != this.levels.length - 1) {
                            for (var i = level + 1; i < this.levels.length; i++) {
                                this.regions[i] = [];
                                this.objs[i].innerHTML = "Выберите&nbsp;" + this.levels[i];
                                this.objs[i].style.display = "none";
                                this.selected[i] = null;
                            }
                        }
                    }
                }
            } .bind(c);
            c.getItem = function (level, id) {
                for (var i = 0; i < this.regions[level].length; i++) {
                    if (this.regions[level][i].id == id)
                        return this.regions[level][i];
                }
            } .bind(c);
            c.setValue = function (val, level) {
                var val = this.getItem(level, val);
                var change = this.selected[level] != val.id;
                this.selected[level] = val.id;
                this.objs[level].innerHTML = val.name;
                if (level != this.levels.length - 1) {
                    for (var i = level + 1; i < this.levels.length; i++) {
                        this.objs[i].innerHTML = "Выберите&nbsp;" + this.levels[i];
                        this.selected[i] = null;
                        if (i > level + 1) {
                            this.objs[i].style.display = "none";
                            this.regions[i] = [];
                        }
                    }
                }
                //if (change)
                this.onSelect(level, val);
            } .bind(c);
            c.onSelect = function (level, value) {
            } .bind(c);
            c.getItems = function (level) {
                if (level < c.levels.length) {
                    return c.regions[level];
                }
                return [];
            } .bind(c);
            c.getHeight = function (level) {
                var itms = this.getItems(level);
                return itms.length > 5 ? 5 * 34 : itms.length * 34;
            } .bind(c);
            for (var i = 0; i < c.levels.length; i++) {
                c.regions.push([]);
                var d = $G.Append(c.obj, $G.Tag("div", "region-selector"), c.obj.firstChild, true);
                d.style.height = "0px";
                d.style.display = "none";
                c.downs.push(d);
                var o = $G.Append(c.obj, $G.Tag("a", { href: "javascript://Выберите " + c.levels[i] + ";" }, null, "Выберите&nbsp;" + c.levels[i]));
                $G.Append(c.obj, document.createTextNode("  "));
                c.objs.push(o);
                o.onclick = $CS.SlideSelector.bind(this, d, function (obj) {
                    if (obj) {
                        this.c.setValue(obj.value, this.lvl);
                    }
                } .bind({ lvl: i, c: c }), o, c.getItems.bind(c, i), c.getHeight.bind(c, i));
                c.selected.push(-1);
            }
        }
    }
}

addDOMLoadEvent($CS.Init);
