(function ($) {
    /**
     * 同步取书的控件
     * @class FR.SynchronBaseEditor
     * @extends FR.BaseEditor
     */
    FR.SynchronBaseEditor = FR.extend(FR.BaseEditor, /**@class FR.SynchronBaseEditor*/{
//        _confirmEvents: function () {
//            // b:只执行一次,大数据量时数据分批加载会有影响
//            this.once(FR.Events.DEFAULTINIT, function () {
//                this.fireEvent(FR.Events.AFTERINIT);
//            });
//        }
        // 绑定事件应该一开始就执行
        // 不然有可能在控件的_init阶段就触发了DEFAULTINIT而还没绑定
        _init: function () {
            FR.SynchronBaseEditor.superclass._init.apply(this, arguments);
            var self = this;
            // once也不保险啊 有可能afterinit里面又调用到了defaultinit
            this.once(FR.Events.DEFAULTINIT, function () {
                if (self.initFired) {
                    return;
                }
                self.initFired = true;
                this.fireEvent(FR.Events.AFTERINIT);
            });
        }
    });

    $.extend(FR, {
        createTreeConfig4Widget: function (widget) {

            FR.$defaultImport('/com/fr/web/core/js/jquerytree/tree.js', 'js');

            FR.$defaultImport('/com/fr/web/core/js/jquerytree/common.js', 'js');

            if (widget.options.widgetCss
                && widget.options.widgetCss.length !== 0) {
                $.each(widget.options.widgetCss, function (i, item) {
                    FR.$import(item, 'css', true);
                });
            }

            var o = {
                data: widget.options.data,
                showcheck: widget.options.mutiSelection,
                onnodeclick: function (item, triggerEvent) {
                    var disabledID = widget.options.disableID;
                    if (disabledID) {
                        if (disabledID == item.getID()) {
                            return;
                        }
                    }
                    widget._onEnterPressed(this, triggerEvent);
                },
                beforeSelectItemChange: function () {
                    return widget.fireEvent(FR.Events.BEFORESTATECHANGE);
                },
                flatStyle: false,
                widget: widget,
                selectLeafOnly: widget.options.selectLeafOnly,
                afterBuild: function () {
                    return widget.fireEvent(FR.Events.AFTERBUILD);
                },
                //wei,loadByLayer:是否强制一次只加载1层dom
                loadByLayer: widget.options.loadByLayer
            };
            return o;
        },

        /**
         * 处理"1,11,111;1,12,123"这种手输的树值
         * @param str
         * @returns {Array}
         * @private
         */
        parseString2Array4Tree: function (str, widget) {
            if (typeof str != 'string'|| FR.isEmpty(widget)) {
                return $.makeArray(str);;
            }
            var arr = [];
            //这边分隔符暂时没有自定义功能,先写这儿了.做自定义的话逻辑还是要改的.
            var reg1 = widget.options.nodeDelimiter || /[;;]/;
            var reg2 = widget.options.pathDelimiter || /[,,]/;
            if (str.indexOf(';') != -1 || str.indexOf(';') != -1) {
                arr = str.split(reg1);
            }
            if (arr.length > 0) {
                for (var i = 0; i < arr.length; i++) {
                    arr[i] = arr[i].split(reg2);
                }
            } else if (str.indexOf(',') != -1 || str.indexOf(',') != -1) {
                arr = str.split(reg2);
            }
            if (FR.isEmptyArray(arr)) {
                return str.split(';');
            }
            return arr;
        },
        /**
         * 一维数组转化成数组中的数组
         * @param arr
         * @return {*}
         */
        parseTo2DArray: function (arr) {
            if (!FR.isEmptyArray(arr) && !$.isArray(arr[0])) {
                var newArr = [];
                newArr[0] = arr;
                return newArr;
            } else {
                return arr;
            }
        },

        /**
         * "南京"  -->  ["江苏","南京"]
         * @param str
         * @param node
         */
        getTreeTrace: function (str, nodes, multi, selectLeafOnly) {
            var arr = [];
            var arrs = [];
            var find = false;
            for (var i = 0; i < nodes.length; i++) {
                // 如果只返回叶子节点而这个节点还有子节点 那就跳过
                if (nodes[i].hasChild() && selectLeafOnly) {
                    continue;
                }
                if (nodes[i].getValue() == str || nodes[i].getShowValue() == str) {
                    find = true;
                    var node = nodes[i];
                    arr[0] = node.getValue();
                    while (node.getParent()) {
                        node = node.getParent();
                        arr.push(node.getValue());
                    }
                    if (multi === true) {
                        arrs.push(arr.reverse());
                    } else {
                        return arr.reverse();
                    }
                }
            }
            // 到这里没有返回,说明不在这一层,到其子层找
            for (var i = 0; i < nodes.length; i++) {
                // 这个嵌套的函数不到后台加载数据 只用已经加载的
                //if(nodes[i].getChildren()) {
                if (nodes[i].ChildNodes || (nodes[i].data && nodes[i].data.ChildNodes)) {
                    var a = FR.getTreeTrace(str, nodes[i].getChildren(), multi, selectLeafOnly);
                    if (!FR.isEmptyArray(a)) {
                        find = true;
                        if (multi) {
                            for (var j = 0; j < a.length; j++) {
                                arrs.push(a[j]);
                            }
                        } else {
                            return a;
                        }
                    }
                }
            }
            if (find) { // must be multi then
                return arrs;
            }
            return [];
        },

        getValidTreeTrace: function (arr, nodes, selectLeafOnly) {
            if (!FR.isArray(arr) || FR.isEmptyArray(arr)) {
                return;
            }
            if (arr.length === 1) {
                return FR.getTreeTrace(arr[0], nodes, false, selectLeafOnly);
            } else {
                return valueInNode(arr, 0, nodes) ? arr : null;
            }
            function valueInNode(arr, deep, nodes) {
                if (deep >= arr.length) {
                    return true;
                }
                for (var i = 0; i < nodes.length; i++) {
                    if (nodes[i].getValue() == arr[deep]) {
                        return valueInNode(arr, deep + 1, nodes[i].getChildren());
                    } else if (nodes[i].getShowValue() == arr[deep]) {
                        arr[deep] = nodes[i].getValue();
                        return valueInNode(arr, deep + 1, nodes[i].getChildren());
                    }
                }
                return false;
            }
        },

        setAllNodeState: function (nodes, state) {
            for (var i = 0; i < nodes.length; i++) {
                nodes[i].setcheckstate(state);
                if (nodes[i].isLoadComplete() && nodes[i].getChildrenLength() > 0) {
                    FR.setAllNodeState(nodes[i].getChildren(), state);
                }
            }
        },

        setNodeStateByInitValue: function (nodes, deep, value_array, selectLeafOnly) {
            if (!FR.isArray(value_array)) {
                return;
            }
            for (var i = 0; i < nodes.length; i++) {
                if (nodes[i].getShowValue() == value_array[deep] || nodes[i].getValue() == value_array[deep]) {
                    //if (deep == value_array.length - 1) {
                    //    if (!selectLeafOnly || !nodes[i].hasChild()) {
                    //        nodes[i].setcheckstate(1);
                    //    }
                    //    return true;
                    //}
                    //zack:如果selectLeafOnly=false,就应该将valuearray里的所有节点设为选中状态而不应该限制在层级条件下上面的逻辑改一下

                    if (!selectLeafOnly ) {
                        nodes[i].setcheckstate(1);
                    }else{
                        if (deep == value_array.length - 1 && !nodes[i].hasChild()) {
                            nodes[i].setcheckstate(1);
                            return true;
                        }
                    }
                    var child = nodes[i].getChildren();
                    // self.options.selectLeafOnly
                    if (FR.setNodeStateByInitValue(child, deep + 1, value_array, selectLeafOnly) && selectLeafOnly) {
                        var allChildeSelected = true;
                        for (var j = 0; j < child.length; j++) {
                            if (child[j].getcheckstate() !== 1) {
                                allChildeSelected = false;
                                break;
                            }
                        }
                        nodes[i].setcheckstate(allChildeSelected ? 1 : 2);
                        return true;
                    }
                }
            }
        },

        findSelectedNode: function (nodes, deep, value_array, treeConfig) {
            if (!FR.isArray(value_array)) {
                // 必须是数组 不然字符串的话value_array[deep]也能取值但是不对
                return;
            }
            for (var i = 0; i < nodes.length; i++) {
                if (nodes[i].getShowValue() == value_array[deep] || nodes[i].getValue() == value_array[deep]) {
                    if (deep == value_array.length - 1) {
                        treeConfig.currentnode = nodes[i];
                    }
                    FR.findSelectedNode(nodes[i].getChildren(), deep + 1, value_array, treeConfig);
                }
            }
        },

        findTrueValue: function (nodes, deep, value_array, result_array, true_value) {
            if (!FR.isArray(value_array)) {
                return;
            }
            for (var i = 0; i < nodes.length; i++) {
                if (nodes[i].getValue() == value_array[deep]) {
                    if (deep == value_array.length - 1) {
                        result_array.push(nodes[i].getTextPath(false));
                        true_value.push(value_array);
                        return;
                    }
                    nodes = nodes[i].getChildren();
                    FR.findTrueValue(nodes, deep + 1, value_array, result_array, true_value);
                    return;
                }
            }
        },

        getTreeValueResult: function(arr, isMulti, returnFullPath) {
            if (returnFullPath) {
                return arr;
            } else {
                if (arr == null) {
                    return null;
                }
                if (isMulti) {
                    var res = [];
                    for (var i=0; i<arr.length; i++) {
                        if ($.isArray(arr[i])) {
                            var sub = arr[i];
                            res[i] = sub[sub.length - 1];
                        }
                    }
                    return res;
                } else {
                    return arr[arr.length - 1];
                }
            }
        }
    });

// FR.TreeEditor.Start
    FR.TreeEditor = FR.extend(FR.SynchronBaseEditor, {
        _defaultConfig: function () {
            return $.extend(FR.TreeEditor.superclass._defaultConfig.apply(), {
                width: 120,
                height: 200,
                limitData: 300,
                delimiter: ';'
            });
        },

        _init: function () {
            FR.TreeEditor.superclass._init.apply(this, arguments);
            this.initData();
            if (this.options.widgetName != null) {
                this.element.attr("id", this.options.widgetName);
            }
            if (this.options.width > -1) {
                this.element.css("width", this.options.width);
            }
            if (this.options.height > -1) {
                this.element.css("height", this.options.height);
            }

            this.element.css('overflow', 'auto');
            this.options.data.resetStatus(this.allPara());
            if (this.options.value || this.options.value === 0) {
                this._dealValueWithEvents(this.options.value);
            }
            this._setCheckStateByDefaultValue();
        },

        initData: function () {
            if (this.options.data) {
                return;
            }
            if (this.options.rootLoader) {
                this.options.data = new FR.TreeData({
                    treeLoader: this.options.rootLoader
                });
            } else if (this.options.widgetUrl) {
                this.options.data = new FR.TreeData({
                    url: this.options.widgetUrl
                });
            } else if (this.options.items) {
                this.options.data = new FR.ItemTreeData({
                    items: this.options.items
                });
            }
            if (this.options.controlAttr) {
                var data = this.options.controlAttr['data'] || this.options.controlAttr['value'];
                if (FR.isEmpty(data) || data == "") {
                    return;
                }
                this._confirmEvents = function () {
                    this.fireEvent(FR.Events.AFTERINIT);
                };
                var para = {
                    parameter:{
                        dependence: this.getDependenceObj(),
                        startIndex: 0,
                        limitIndex: this.options.limitData
                    }
                }
                this.options.data.setData(para, data);
                delete this.options.controlAttr;
            }
        },

        allPara: function (start, limit) {
            var para = this.createDependencePara4Data();
            para.parameter.startIndex = start ? start : 0;
            para.parameter.limitIndex = limit ? limit : this.options.limitData;
            return para;
        },

        isComboBoxTree: function () {
            return false;
        },

        _onEnterPressed: function (item) {
            this.fireEvent(FR.Events.CLICK, item);
            this.fireEvent(FR.Events.AFTEREDIT);
        },

        getValue: function () {
            var res;
            if (!this.options.mutiSelection) {
                res = this.element.getTCPValue() || this.value;
            } else {
                res = this.element.getTCPValues() || this.value;
            }
            return FR.getTreeValueResult(res, this.options.mutiSelection, this.options.returnFullPath);
        },

        setValue: function (value) {
            // 设置编辑器的值
            var self = this;
            var value_array;
            if (typeof value === "string") {
                value_array = value.split(this.options.delimiter);
            } else {
                value_array = $.makeArray(value);
            }
            if (!FR.isEmptyArray(value_array)) {
                var nodes = this.options.data.getData();
                var leafNodes = [];
                for (var i = 0; i < nodes.length; i++) {
                    leafNodes = leafNodes.concat(nodes[i].getLeafNode());
                }
                var relatedNodes = [];
                for (var idx = 0; idx < leafNodes.length; idx++) {
                    var item = leafNodes[idx];
                    var match;
                    if ($.isArray(value_array[0]) && self.options.mutiSelection) {
                        match = value_array.indexOf(item.getValuePath(false)) !== -1;
                    } else {
                        match = FR.equals(item.getValuePath(false), value_array)
                    }
                    if (match) {
                        item.setcheckstate(1);
                        relatedNodes.push(item);
                        if (!self.options.mutiSelection) {
                            break;
                        }
                    } else {
                        item.setcheckstate(0);
                    }
                }
                // wei : 处理父节点们
                $.each(relatedNodes, function (idx, item) {
                    var parentNode = item.getParent();
                    while (parentNode) {
                        parentNode.setcheckstate(parentNode.isAllChildrenChosen() ? 1 : 2);
                        // shoc 值选中的话父节点展开
                        parentNode.setexpand(true);
                        parentNode = parentNode.getParent();
                    }
                });
                var treeConfig = FR.createTreeConfig4Widget(this);
                this._createTreeView(treeConfig);
            }
        },
        _dealValueWithEvents: function (value) {
            var oldValue = this.options.mutiSelection ? [] : '';
            if (typeof value === "string") {
                var value_array = value.split(this.options.delimiter);
            } else {
                var value_array = $.makeArray(value);
            }
            var self = this;
            var result_array = [];
            var true_value = [];
            if (!this.options.mutiSelection) {
                FR.findTrueValue(this.options.data.getData(), 0, value_array, result_array, true_value);
            } else {
                value_array = FR.parseTo2DArray(value_array);
                for (var m = 0; m < value_array.length; m++) {
                    FR.findTrueValue(this.options.data.getData(), 0, $.isArray(value_array[m]) ? value_array[m] : value_array[m].split(","),
                        result_array, true_value);
                }
            }

            if (result_array.length !== 0) {
                this.value = this.options.mutiSelection ? true_value : true_value[0];
            } else {
                this.value = value_array;
            }
            leafNodes = nodes = null;
            if (oldValue != value) {
                this.options.need2BuildList = true;
            }
        },

        _setCheckStateByDefaultValue: function () {
            var self = this;
            var initArray = this.options.value ? this.options.value : [];
            var treeConfig = FR.createTreeConfig4Widget(this);
            /*change [[1,11],[2,21]] to ["1,11","2,21"]*/
            var sortArray = function (initArray) {
                if (!$.isArray(initArray)) {
                    return;
                }
                if (!FR.isEmptyArray(initArray)) {
                    for (var i = 0; i < initArray.length; i++) {
                        if ($.isArray(initArray[i])) {
                            initArray[i] = initArray[i].toString();
                        }
                    }
                }
            };
            if (!FR.isEmptyArray(initArray)) {
                var nodes = this.options.data.getData();
                // 把树节点中的某一项转化成具体的数组路径
                if (!FR.isArray(initArray)) {
                    initArray = FR.getTreeTrace(initArray, nodes, self.options.mutiSelection, self.options.selectLeafOnly);
                }
                if (self.options.mutiSelection) {
                    // 把一维数组转化成二维数组
                    initArray = FR.parseTo2DArray(initArray);
                    sortArray(initArray);
                    FR.setAllNodeState(nodes, 0);
                    for (var m = 0; m < initArray.length; m++) {
                        FR.setNodeStateByInitValue(nodes, 0, initArray[m].split(","), self.options.selectLeafOnly);
                    }
                } else {
                    FR.findSelectedNode(nodes, 0, initArray, treeConfig);
                }
            }
            this._createTreeView(treeConfig);
        },

        reset: function () {
            // 重置,目前主要用于联动时,与当前控件相关的控件值改变时,需要做重置操作
            this.setValue("");
            // 把树的选择展开状态也还原
            var nodes = this.options.data.getData();
            FR.setAllNodeState(nodes, 0);
            var treeConfig = FR.createTreeConfig4Widget(this);
            this._createTreeView(treeConfig);
        },
        doResize: function (give) {
            FR.TreeEditor.superclass.doResize.call(this, give);
        },
        _createTreeView : function(treeConfig){
            this.element.treeview(treeConfig);
        }

    });
    $.shortcut('tree', FR.TreeEditor);

// FR.TreeEditor.End

    // FR.ListEditor.Start
    /**
     * 列表控件
     * @class FR.ListEditor
     * @extends FR.SynchronBaseEditor
     */
    FR.ListEditor = FR.extend(FR.SynchronBaseEditor, /**@class FR.ListEditor*/{

        _defaultConfig: function () {
            return $.extend(
                FR.ListEditor.superclass._defaultConfig.apply(), {
                    width: 120,
                    height: 200,
                    icon: false,
                    multi: false,
                    removeSelf: false,
                    textAlign: 'left'
                });
        },

        _init: function () {
            FR.ListEditor.superclass._init.apply(this, arguments);
            this.initData();
            this._initList();
            // b:这部分太碍眼了,提供api让客户自己在afterinit || 其他事件里注册event
            var self = this;
            this.options.data.once(FR.Events.AFTERREAD, function () {
                self.fireEvent(FR.Events.DEFAULTINIT);
            });
        },
        /**
         * 初始化数据
         */
        initData: function () {
            if (this.options.data) {
                return;
            }

            if (this.options.controlAttr) {
                this.setSource(this.options.controlAttr);
                this._confirmEvents = function () {
                    this.fireEvent(FR.Events.AFTERINIT);
                };
                return;
            }

            if (this.options.widgetUrl) {
                this.options.data = FR.DataFactory.createSynchronJSONData(
                    this.options.widgetUrl, false);
            } else if (this.options.items) {
                this.options.data = FR.DataFactory
                    .createSynchronArrayData(this.options.items);
            }
        },

        refreshList: function () {
            if (this.options.controlAttr && this.options.widgetUrl) {
                this.options.controlAttr = null;
                this.options.data = FR.DataFactory.createSynchronJSONData(
                    this.options.widgetUrl, false);
            }
            this.jlist(
                {needHead: this.options.needHead
                });
        },

        setSource: function (source) {
            var self = this;
            if (source["value"] !== undefined && source["value"] !== "") {
                this.once(FR.Events.DEFAULTINIT, function () {
                    self.setValue(source["value"], false);
                });
            }
            this.options.data = FR.DataFactory
                .createSynchronArrayData(source["data"]);
        },

        _initList: function () {
            FR.$defaultImport('/com/fr/fs/web/platform/js/jquery.jlist.js',
                'js');
            var o = this.options;
            if (o.width > -1) {
                this.element.css("width", o.width);
            }
            if (o.height > -1) {
                this.element.css("height", o.height);
            }
            if (o.textAlign) {
                this.element.css("text-align", o.textAlign);
            }
            this.jlist(
                {needHead: o.needHead
                });
        },

        getValue: function () {
            var record = this.getSelectedItem();
            return record != null ? record.getValue() : null;
        },

        _dealValueWithEvents: function (val, it) {
            var currentText = this.getSelectedText(), data = this.options.data;
            for (var index = 0, len = data.getLength(); index < len; index++) {
                var dt = this.options.data.getRecord(index);
                if (it && (it.getShowValue() == dt.getShowValue())) {
                    dt.setValue(val);
                    break;
                }
            }
        },

        getSelectedText: function () {
            var record = this.getSelectedItem();
            return record != null ? record.getShowValue() : null;
        },

        /**
         * 添加子项
         * @param item {JQuery} 子项元素的DOM对象
         */
        addItem: function (item) {
            this.doAddItem(item);
        },

        getAll: function () {
            var all = [], data = this.options.data;
            for (var i = 0, len = data.getLength(); i < len; i++) {
                var nd = data.getRecord(i);
                all.push({
                    text: nd.getShowValue(),
                    value: nd.getValue() != null
                        ? nd.getValue()
                        : nd.getShowValue()
                });
            }
            return all;
        },

        setAll: function (val) {
            var self = this;
            //b:role pane only
            $.each(val, function (name, nd) {
                var record = FR.DataFactory.createItemRecord({
                    text: name, value: nd
                });
                self.doAddItem(record, true);
                self.options.data.addRecord(record);
            })
        },

        clear: function () {
            this.doClear();
        },

        clearSelected: function () {
            $('.fr-list-node', this.element)
                .removeClass('fr-list-node-selected');
            this.fireEvent(FR.Events.NOSELECT);
        },

        doFilter: function (args) {
            var lis = $('.fr-list-node', this.element);
            if (args || args === 0) {
                args = args.toUpperCase();
                $.each(lis, function (idx, item) {
                    var text = $('a > span', $(this)).html();
                    if (text.toUpperCase().indexOf(args) > -1) {
                        $(this).show();
                    }
                    else {
                        $(this).hide();
                    }
                });
            } else {
                lis.show();
            }
        },

        popData: function (data) {
            this.doClear();
            this.options.data = new FR.SynchronData({
                dataSource: new FR.SynchronObjectSource({
                    object: data
                })
            });
            this.jlist();
            if (this.getSelectedIndex() < 0) {
                this.fireEvent(FR.Events.NOSELECT);
            }
        },

        /**
         * 选中指定项
         * @param index 位置索引
         */
        setSelectedIndex: function (index) {
            var ulContent = $('ul.fr-list-content', this.element);
            var li = $('li', ulContent);
            if (!li) {
                this.fireEvent(FR.Events.NOSELECT);
            }
            this.doSelected(null, $(li[index]));
        }

    });
    $.shortcut("list", FR.ListEditor);
// FR.ListEditor.End


    /**
     * 按钮组
     * @class FR.ToggleButtonGroup
     * @extends FR.SynchronBaseEditor
     * @abstract
     */
    FR.ToggleButtonGroup = FR.extend(FR.SynchronBaseEditor, /**@class FR.ToggleButtonGroup*/{
        _defaultConfig: function () {
            return $.extend(FR.ToggleButtonGroup.superclass._defaultConfig.apply(),
                {
                    // 每一行有的列数,0表示只有一行
                    columnsInRow: 0
                });
        },
        _init: function () {
            FR.ToggleButtonGroup.superclass._init.apply(this, arguments);
            var o = this.options;
            var hm;
            var vm;
            if (o.border) {
                vm = o.border.b || o.border.t;
                hm = o.border.l || o.border.r;
                if (o.border.b1) {
                    o.height = o.height - 1;
                    o.width = o.width - 1;
                } else if (vm) {
                    o.height = o.height - vgap.w;
                } else if (hm) {
                    o.width = o.width - hgap.w;
                }
            }
            var width = o.width > 0 ? o.width : 0;
            var height = o.height > 0 ? o.height : 0;
            // richer:必须在值初始化之前生成该按钮组的容器
            this.$container = this.element.addClass("fr-form-btn-group");
            this.$container.css({
                "width": width,
                "height": height
            }).addClass(this.lbox_class);
            this.buttonArray = [];
            // IE8 IE7 杂项模式元素高度为0的话,还是会显示出来
            if (FR.Browser.isIE8Before() && !$.support.boxModel && height === 0) {
                this.$container.css({
                    height: 1, // overflow为hidden 高度为0居然还显示 改成1就不显示了
                    "overflow": "hidden"
                })
            }

            if (o.value != null) {
                this.once(FR.Events.DEFAULTINIT, function () {
                    this.setValue(o.value, false);
                });
            }

            this.initData();

        },

        initData: function () {
            if (this.options.data) {
                return;
            }

            if (this.options.controlAttr) {
                // 已经加载过了的。所以应该立即执行AFTERINIT
                this.setSource(this.options.controlAttr);
                this._confirmEvents = function () {
                    this.fireEvent(FR.Events.AFTERINIT);
                };
                return;
            }

            if (this.options.widgetUrl) {
                this.options.data = FR.DataFactory.createSynchronJSONData(
                    this.options.widgetUrl, false);
                this.options.data.resetStatus(this.createDependencePara4Data());
            } else if (this.options.items) {
                this.options.data = FR.DataFactory
                    .createSynchronArrayData(this.options.items);
            }
            var self = this;
            this.options.data.afterRead(function (items) {
                if (self.isBoxBuild !== true) {
                    self._buildBox(items);
                }
            });
            this.options.data.loadData();
        },

        setSource: function (source) {
            var self = this;
            if (source["value"] !== undefined && source["value"] != "") {
                this.once(FR.Events.DEFAULTINIT, function () {
                    self.setValue(source["value"], false);
                });
            }
            this.options.data = FR.DataFactory
                .createSynchronArrayData(source["data"]);
            this.options.data.afterRead(function (items) {
                self._buildBox(items);
            });
            this.options.data.loadData();
        },

        reset: function () {
            this.setValue(null);
            this.isBoxBuild = undefined;
            if (this.options.data.resetStatus(this.createDependencePara4Data())) {
                this.options.data.loadData();
            }
        },

        rebuild: function (items) {
            this.setValue(null);
            this.options.data = null;
            this.options.widgetUrl = null;
            this.element.empty();
            this.options.items = items;
            this.isBoxBuild = undefined;
            if (items.widgetUrl) {
                this.options.widgetUrl = items.widgetUrl;
            }
            if (!this.options.renderEl) {
                this.options.renderEl = this.element;
            }
            this._init();
        },

        clearContent: function () {
            this.$container.empty();
        },

        _buildBox: function () {
            this.clearContent();
            var items = this.options.data.getRecords();
            this._initGridConfig(items);
            this._setItems(items);
            this.isBoxBuild = true;
            this.fireEvent(FR.Events.DEFAULTINIT);
        },

        _initGridConfig: function (items) {
            var len = items.length + (this.options.chooseAll === true ? 1 : 0), ci = this.options.columnsInRow, ro = ci === 0
                ? 1
                : 1 + Math.floor((len - 0.1) / ci);
            this.gridConfig = {
                columns: ci === 0 || ro === 0 ? len : ci,
                rows: ro,
                items: [],
                renderEl: this.$container
            };
            return this.gridConfig;
        },

        setEnable: function (arg) {
            if (this.buttonArray) {
                for (var i = 0; i < this.buttonArray.length; i++) {
                    this.buttonArray[i].setEnable(arg);
                }
            }
            FR.ToggleButtonGroup.superclass.setEnable.apply(this, arguments);
        },

        getErrorMessage: function () {
            return this.options.errorMsg || FR.i18nText("FR-Base_NOT_NULL_Des");
        },
        doResize: function (give) {
            FR.ToggleButtonGroup.superclass.doResize.call(this, give);
            this.$container.css({
                width: give.width,
                height: give.height
            });
            if (this.grid) {
                this.grid.doLayout();
                this._checkTable();
            }
        },
        // b:table中absolute处理
        _checkTable: function () {
            if (this.$container.parent()[0]
                && this.$container.parent()[0].tagName == "TD") {
                this.$container.css('position', 'relative');
            }
        }
    });
    $.shortcut("togglebuttongroup", FR.ToggleButtonGroup);


    // 兼容
    // FR.TableTree.Start
    FR.TableTree = FR.extend(FR.BaseEditor, {
        _defaultConfig: function () {
            return $.extend(FR.TableTree.superclass._defaultConfig.apply(),
                {
                    width: 120,
                    height: 200
                });
        },
        _init: function () {
            FR.TableTree.superclass._init.apply(this, arguments);

            FR.$defaultImport(
                '/com/fr/web/platform/js/jquery.tabletree.js', 'js');
            FR.$defaultImport(
                '/com/fr/web/platform/css/jquery.tabletree.css', 'css');
            var o = this.options;

            this.$TableTreeDiv = this.element;
            if (o.width > -1) {
                this.$TableTreeDiv.css("width", o.width);
            }
            if (o.height > -1) {
                this.$TableTreeDiv.css("height", o.height);
            }
            // b:cvns & data
            var cvns;
            if(!this.options.data) {
                this.options.data = new FR.Data({
                    dataSource: new FR.URLSource({
                        url: this.options.widgetUrl
                    }),
                    dataReader: new FR.DataReader({
                        choosedFields: ['name', 'state']
                    })
                });
            }

            if (this.options.rootLoader) {
                this.options.treedata = new FR.TreeData({
                    treeLoader: this.options.rootLoader
                });
            } else if (this.options.url) {
                this.options.treedata = new FR.TreeData({
                    url: this.options.url
                });
            } else {
                return;
            }

            var config = {
                // b:nodes
                data: this.options.treedata.getData(),
                // b:records
                cvns: this.options.data.getData(),
                treedatatype:this.options.treedatatype,
                width:this.options.width,
                height:this.options.height,
                needleaficon:this.options.needleaficon,
                oncheckboxclick:this.options.oncheckboxclick
            };
            this.$TableTreeDiv.tabletree(config);
        },

        getValue: function () {
            return this.$TableTreeDiv.getTableTreeValue();
        },

        _setValue: function (value) {
            this.$TableTreeDiv.setTableTreeValue(value);
        }
    });
    $.shortcut("tabletree", FR.TableTree);
// FR.TableTree.End

})(jQuery);