;
(function($) {
    $.extend({
        "cuiTreeTable":function(options){
            return new CuiTreeTable(options);
        }
    });
    $.fn.extend({
       "cuiTreeTable":function(options){
           var g = new CuiTreeTable(options);
           return g.show(this);
       }
    });
})(jQuery);
/***
 * -CLASS-
 * @name CuiTreeTable
 * @package cui.widget
 * @description cui树表格
 * @pageTag <div></div>
 * @depend CuiTreeTableView
 * @paramType JSON
 * @param id string <treeTable展示到的元素id>
 * @param data json <treeTable的数据>
 * @param tree json <树结构的设置，详细参数查看addTreeColumn方法的参数说明>
 * @param columns json <header的设置，详细参数查看setColumns方法的参数说明>
 * @param config json <treeTable的设置，详细参数查看setConfig方法的参数说明>
 * @author ypu<ypu@cenonet.com>
 * @version 2011-10-15
 * @since 0.1
 */
var CuiTreeTable = function(options) {
     //显示到的元素id
//    var _id_;
    //解析后的数据,tid作为索引，内容为该索引的数据对象
    var _data_ = [];
    //树结构，tid作为索引，内容为该索引的子节点tid
    var _tree_ = [];
    //显示内容索引
    var _idxs_ = [];
    //树节点
    var _treeCol_ = {};
    //表格列头
    var _columns_ = [];
    //cell显示回调函数
    var _cellCallbacks_ = [];
    //数据临时存放
    var _tmp_;
    //树视图
    var _view_ = new CuiTreeTableView();
    //当前树对象
    var _self_ = this;
    //树上下文
    var _context_;
    //树配置
    var _config_ = {
        parent_tag:"parent",       //数据中关联父节点的属性名
        children_tag:"children",  //数据中关联子节点的属性名
        node_css:"cui_iconFile",  //node样式
        leaf_css:"cui_iconRole",  //leaf样式
        process_data:1,             //数据解析方式
        node_show:true,             //是否显示node的表格内容
        collapsed:false    //默认树展开 collapsed为关闭
    }

    /**
     * -METHOD-
     * @summary 设置数据
     * @description 设置tree的数据内容
     * @method setData
     * @param data json <tree data数据>
     * @return CuiTreeTable
     * @since 0.1
     */
    this.setData = function(data) {
        _tmp_ = data;
        return _self_;
    }
    /**
     * -METHOD-
     * @summary 设置数据
     * @description 设置tree的数据内容
     * @method getData
     * @param id int/string <数据主键，tid>
     * @return json
     * @since 0.1
     */
    this.getData = function(id) {
        if (typeof id != 'undefined') {
            return _data_[id];
        } else {
            return _data_;
        }
    }

    this.privateProcessDataChild = function(data, parentId) {
        for (var i in data) {
           var id = data[i][_treeCol_.tid]
            _data_[id] = data[i];
            if (typeof parentId != 'undefined') {
                if (_tree_[parentId]) {
                    _tree_[parentId].push(id);
                } else {
                    _tree_[parentId] = [id];
                }
            } else {
                if (_tree_["_root"]) {
                    _tree_["_root"].push(id);
                } else {
                    _tree_["_root"] = [id];
                }
            }

            if (typeof data[i][_config_["children_tag"]] != "undefined") {
                this.privateProcessDataChild(data[i][_config_["children_tag"]], id);
            }
        }
    }


    this.privateProcessData = function(data) {
        for (var i in data) {
            var id = data[i][_treeCol_.tid]
            _data_[id] = data[i];
            var tag = data[i][_config_["parent_tag"]];
            if (tag) {
                if (_tree_[tag]) {
                    _tree_[tag].push(id);
                } else {
                    var t = [];
                    t.push(id);
                    _tree_[tag] = t;
                }
            } else {
                if (_tree_["_root"]) {
                    _tree_["_root"].push(id);
                } else {
                    var t = [];
                    t.push(id);
                    _tree_["_root"] = t;
                }
            }
        }
    }
    /**
     * -METHOD-
     * @summary CuiTreeTable添加头部
     * @description CuiTreeTable添加头部
     * @method setColumns
     * @param columns json <列json对象>
     * @param idx string <data中在该列显示的key> hInfo
     * @param name string <头部的名称> hInfo
     * @param title string <头部的title> hInfo
     * @param css string <头部的class样式> hInfo
     * @param style string <头部的style样式> hInfo
     * @param width int <头部的宽度> hInfo
     * @param height int <头部的高度> hInfo
     * @param maxlength int <该列内容显示的最大长度> hInfo
     * @param align string <该列内容显示的对齐方式，默认为center> hInfo
     * @return CuiTreeTable
     * @since 0.1
     */
    this.setColumns = function(columns) {
        for (var i in columns) {
            var o = {};
            o.idx = columns[i].idx;
            o.title = columns[i].title;
            o.name = columns[i].name;
            o.width = columns[i].width;
            o.maxlength = columns[i].maxlength;
            o.align = columns[i].align;
            o.css = columns[i].css;
            o.style = columns[i].style;
            _idxs_.push(o.idx);
            _columns_[o.idx] = o;
        }
        return _self_;
    }
/*即将废弃，由setColumns替代*/
    this.setHeader = function(headers) {
        for (var i in headers) {
            var o = {};
            o.idx = headers[i].idx;
            o.title = headers[i].title;
            o.name = headers[i].name;
            o.width = headers[i].width;
            o.maxlength = headers[i].maxlength;
            o.align = headers[i].align;
            o.css = headers[i].css;
            o.style = headers[i].style;
            _idxs_.push(o.idx);
            _columns_[o.idx] = o;
        }
        return _self_;
    }

    /**
     * -METHOD-
     * @summary 设置tree自动加载数据
     * @description 设置tree自动加载数据
     * @method loadData
     * @param url string <请求数据地址>
     * @param params json <请求参数>
     * @param func function <数据显示完的回调函数>
     * @param data json <返回的数据>  func
     * @param flag boolean <是否请求成功>  func
     * @return CuiTreeTable
     * @since 0.1
     */
    this.loadData = function(url, params, func) {
        if (!params) {
            params = {};
        }
        $.cuiAjax(url, params, function(data, flag) {
            if (!flag) {
                if (typeof func == 'function') {
                    func(data, flag);
                }
                return;
            }
            if (_config_["dataAdapter"]) {
                data = _config_["dataAdapter"].apply(_self_, [data]);
            }
            _self_.setData(data);
			_self_.initData();
            _self_.refreshData();
            if (typeof func == 'function') {
                func(data, flag);
            }
        });
        return _self_;
    }
    /**
     * -METHOD-
     * @summary 设置tree栏
     * @description 设置tree栏
     * @method addTreeColumn
     * @param tree json <tree属性>
     * @param tid string <tree组织结构对应id> tree
     * @param idx string <tree内容显示属性>  tree
     * @param name string <tree头部显示名称>  tree
     * @param style json <tree样式,可选>
     * @param css string <头部的class样式> style
     * @param style string <头部的style样式> style
     * @param width int <头部的宽度> style
     * @param height int <头部的高度> style
     * @param maxlength int <该列内容显示的最大长度> style
     * @param title string <该列内容显示的title> style
     * @param css string <列的class> style
     * @param style string <列的style样式> style
     * @return CuiTreeTable
     * @since 0.1
     */
    this.addTreeColumn = function(tree) {
        _treeCol_.tid = tree.tid;
        _treeCol_.idx = tree.idx;
        _treeCol_.name = tree.name;
        _treeCol_.width = '';
        if (tree && tree.width) {
            _treeCol_.width = style.width;
        }
        _treeCol_.style = tree;
        return _self_;
    }
    /**
     * -METHOD-
     * @summary 设置tree设置
     * @description 设置tree设置
     * @method setConfig
     * @param config json <tree设置内容>
     * @param width int <treeTable的宽度，默认为自动> config
     * @param parent_tag string <tree数据中父节点的标记名称，默认为"parent"> config
     * @param children_tag string <tree数据中子节点的标记名称，默认为"children"> config
     * @param node_css string <tree节点的css,默认为“folder”> config
     * @param leaf_css string <tree叶子的css,默认为“cui_iconRole”> config
     * @param collapsed string <tree显示是否折叠，true为折叠，false为展开> config
     * @param node_show boolean <是否显示非叶子节点的表格内容，true为显示，false为否> config
     * @param process_data int <处理数据模式，1为自身包含children的组织结构[{"id":"1","children":[{"id":"2","children":[]}]},{"id":3,"children":[]}]，2为只包含parent主键无组织结构[{"id":1,"parent":""},{"id":2,"parent":1},{"id":3,"parent":""}]> config
     * @param dataAdapter func <使用loadData函数，请求返回数据的转换函数，返回转换后的数据内容> config
     * @return CuiTreeTable
     * @since 0.1
     */
    this.setConfig = function(config) {
        if (!config)return _self_;
//        if (typeof config["parent_tag"] != 'undefined')_config_["parent_tag"] = config["parent_tag"];
//        if (typeof config["node_css"] != 'undefined')_config_["node_css"] = config["node_css"];
//        if (typeof config["leaf_css"] != 'undefined')_config_["leaf_css"] = config["leaf_css"];
//        if (typeof config["process_data"] != 'undefined')_config_["process_data"] = config["process_data"];
//        if (typeof config["node_show"] != 'undefined')_config_["node_show"] = config["node_show"];
//        if (typeof config["display_type"] != 'undefined')_config_["display_type"] = config["display_type"];
//        if (typeof config["dataAdapter"] != 'undefined' && typeof config["dataAdapter"] == "function") {
//            _config_["dataAdapter"] = config["dataAdapter"];
//        }
        _config_ = $.extend(_config_,config);
        return _self_;
    }

//    this.privateShowNodes = function(data, tag, parent) {
//
//        for (var i in data) {
//            _data_[data[i][_treeCol_.tid]] = data[i];
//
////            if (parent) {
////                if (_tree_[parent[_treeCol_.tid]]) {
////                    _tree_[parent[_treeCol_.tid]].push(data[i][_treeCol_.tid]);
////                } else {
////                    var o = [];
////                    o.push(data[i][_treeCol_.tid]);
////                    _tree_[parent[_treeCol_.tid]] = o;
////                }
////            } else {
////                if (_tree_["root"]) {
////                    _tree_["root"].push(data[i][_treeCol_.tid]);
////                } else {
////                    var o = [];
////                    o.push(data[i][_treeCol_.tid]);
////                    _tree_["root"] = o;
////                }
////            }
//
//            if (data[i][_config_["children_tag"]] && data[i][_config_["children_tag"]].length > 0) {
//                var row = $(_view_.bodyRowHtml);
//
//                row.attr("id", "node_" + data[i][_treeCol_.tid]);
//                if (parent)row.addClass("cui_child_node_" + parent[_treeCol_.tid]);
//                var cell = $(_view_.bodyCellHtml);
//                var content = data[i][_treeCol_.idx];
//                var nick = content;
//                if (typeof content == "string" && _treeCol_.style && _treeCol_.style.maxlength) {
//                    content = content.substr(0, _treeCol_.style.maxlength);
//                }
//                if (_cellCallbacks_[_treeCol_.idx]) {
//                    content = _cellCallbacks_[_treeCol_.idx].apply(_self_, [_treeCol_.idx,data[i]]);
//                }
//
//                cell.append($(_view_.contentHtml).html(content).addClass(_config_["node_css"]).attr("title", nick));
//                if (!_config_["node_show"]) {
//                    cell.attr("colspan", _idxs_.length + 1);
//                }
//                this.privateSetStyle(cell, _treeCol_.style);
//                row.append(cell);
//
//                if (_config_["node_show"]) {
//                    for (var m in _idxs_) {
//                        cell = $(_view_.bodyCellHtml);
//                        content = data[i][_idxs_[m]];
//                        nick = content;
//                        if (typeof content == "string" && _headers_[_idxs_[m]] && _headers_[_idxs_[m]]["maxlength"]) {
//                            content = content.substr(0, _headers_[_idxs_[m]]["maxlength"]);
//                        }
//                        if (_cellCallbacks_[_idxs_[m]]) {
//                            content = _cellCallbacks_[_idxs_[m]].apply(_self_, [_idxs_[m], data[i]]);
//                        }
//
//                        cell.html(content).attr("title", nick);
//                        this.privateSetStyle(cell, _treeCol_.style);
//                        row.append(cell);
//                    }
//                }
//                tag.append(row);
//                this.privateShowNodes(data[i][_config_["children_tag"]], tag, data[i]);
//            } else {
//                var row = $(_view_.bodyRowHtml);
//
//                row.attr("id", _view_.idStr + data[i][_treeCol_.tid]);
//                if (parent)row.addClass(_view_.nodeCssStr + parent[_treeCol_.tid]);
//                var cell = $(_view_.bodyCellHtml);
//                var content = data[i][_treeCol_.idx];
//                var nick = content;
//                if (typeof content == "string" && _treeCol_.style && _treeCol_.style.maxlength) {
//                    content = content.substr(0, _treeCol_.style.maxlength);
//                }
//                if (_cellCallbacks_[_treeCol_.idx]) {
//                    content = _cellCallbacks_[_treeCol_.idx].apply(_self_, [_treeCol_.idx,data[i]]);
//                }
//
//                cell.append($(_view_.contentHtml).html(content).addClass(_config_["leaf_css"]).attr("title", nick));
//                this.privateSetStyle(cell, _treeCol_.style);
//                row.append(cell);
//
//                for (var m in _idxs_) {
//                    cell = $(_view_.bodyCellHtml);
//                    content = data[i][_idxs_[m]];
//                    nick = content;
//                    if (typeof content == "string" && _headers_[_idxs_[m]] && _headers_[_idxs_[m]]["maxlength"]) {
//                        content = content.substr(0, _headers_[_idxs_[m]]["maxlength"]);
//                    }
//                    if (_cellCallbacks_[_idxs_[m]]) {
//                        content = _cellCallbacks_[_idxs_[m]].apply(_self_, [_idxs_[m], data[i]]);
//                    }
//
//                    cell.html(content).attr("title", nick);
//                    this.privateSetStyle(cell, _treeCol_.style);
//                    row.append(cell);
//                }
//                tag.append(row);
//            }
//        }
//    }


    this.privateShowNodes = function(tlist, tag, parent) {
        //display leaf first
//        var leafs = [];
//        var nodes = [];
//        for (var i in tlist) {
//            if (_tree_[tlist[i]]) {
//                nodes.push(tlist[i]);
//            } else {
//                leafs.push(tlist[i]);
//            }
//        }

        for (var i in tlist) {
            var id = tlist[i];
            var row = $(_view_.bodyRowHtml);

            row.attr("id", _view_.idStr + id);
            if (parent)row.addClass("cui_child_node_" + parent);
            var cell = $(_view_.bodyCellHtml);
            var content = _data_[id][_treeCol_.idx];
            var nick = content;

            if (_cellCallbacks_[_treeCol_.idx]) {
                content = _cellCallbacks_[_treeCol_.idx].apply(_self_, [_treeCol_.idx,_data_[id]]);
            }else if (typeof content == "string" && _treeCol_.style && _treeCol_.style.maxlength) {
                content = content.substr(0, _treeCol_.style.maxlength);
            }

            if (_tree_[id] && _tree_[id].length > 0) {
                cell.append($(_view_.contentHtml).html(content).addClass(_config_["node_css"]).attr("title", nick));
                if (!_config_["node_show"]) {
                    cell.attr("colspan", _idxs_.length + 1);
                }
                this.privateSetStyle(cell, _treeCol_.style);
                row.append(cell);

                if (_config_["node_show"]) {
                    for (var m in _idxs_) {
                        var t =  _idxs_[m];
                        cell = $(_view_.bodyCellHtml);
                        content = _data_[id][t];
                        nick = content;

                        if (_cellCallbacks_[t]) {
                            content = _cellCallbacks_[t].apply(_self_, [t, _data_[id],cell]);
                        }else if (typeof content == "string" && _columns_[t] && _columns_[t]["maxlength"]) {
                            content = $.cuiShortStr(content,_columns_[t]["maxlength"]);
                        }
                        //todo style;
                        cell.html(content).attr("title", nick);
                        this.privateSetStyle(cell, _columns_[t]);
                        row.append(cell);
                    }
                }
                tag.append(row);
                this.privateShowNodes(_tree_[id], tag, id);
            } else {
                cell.append($(_view_.contentHtml).html(content).addClass(_config_["leaf_css"]).attr("title", nick));
                this.privateSetStyle(cell, _treeCol_.style);
                row.append(cell);

                for (var m in _idxs_) {
                    cell = $(_view_.bodyCellHtml);
                    content = _data_[id][_idxs_[m]];
                    nick = content;
                    if(typeof _cellCallbacks_ == 'function'){
                        content = _cellCallbacks_.apply(_self_, [_idxs_[m], _data_[id],cell]);
                    } else if (_cellCallbacks_[_idxs_[m]]) {
                        content = _cellCallbacks_[_idxs_[m]].apply(_self_, [_idxs_[m], _data_[id],cell]);
                    }else if (typeof content == "string" && _columns_[_idxs_[m]] && _columns_[_idxs_[m]]["maxlength"]) {
                        content = content.substr(0, _columns_[_idxs_[m]]["maxlength"]);
                    }

                    cell.html(content).attr("title", nick);
                    this.privateSetStyle(cell,_columns_[_idxs_[m]]);
                    row.append(cell);
                }
                tag.append(row);
            }
        }

//        for (var i in leafs) {
//            var row = $(_view_.bodyRowHtml);
//
//            row.attr("id", _view_.idStr + leafs[i]);
//            if (parent)row.addClass(_view_.nodeCssStr + parent);
//            var cell = $(_view_.bodyCellHtml);
//            var content = _data_[leafs[i]][_treeCol_.idx];
//            var nick = content;
//            if (typeof content == "string" && _treeCol_.style && _treeCol_.style.maxlength) {
//                content = content.substr(0, _treeCol_.style.maxlength);
//            }
//            if (_cellCallbacks_[_treeCol_.idx]) {
//                content = _cellCallbacks_[_treeCol_.idx].apply(_self_, [_treeCol_.idx,_data_[leafs[i]]]);
//            }
//
//            cell.append($(_view_.contentHtml).html(content).addClass(_config_["leaf_css"]).attr("title", nick));
//            this.privateSetStyle(cell, _treeCol_.style);
//            row.append(cell);
//
//            for (var m in _idxs_) {
//                cell = $(_view_.bodyCellHtml);
//                content = _data_[leafs[i]][_idxs_[m]];
//                nick = content;
//                if (typeof content == "string" && _headers_[_idxs_[m]] && _headers_[_idxs_[m]]["maxlength"]) {
//                    content = content.substr(0, _headers_[_idxs_[m]]["maxlength"]);
//                }
//                if (_cellCallbacks_[_idxs_[m]]) {
//                    content = _cellCallbacks_[_idxs_[m]].apply(_self_, [_idxs_[m], _data_[leafs[i]]]);
//                }
//
//                cell.html(content).attr("title", nick);
//                this.privateSetStyle(cell, _treeCol_.style);
//                row.append(cell);
//            }
//            tag.append(row);
//        }
    }

    this.initData = function(){
        _tree_ = [];
        _data_ = [];
        if (_config_["process_data"] == 2) {
            this.privateProcessData(_tmp_);
        } else {
            this.privateProcessDataChild(_tmp_);
        }
        return _self_;
    }
	
    /**
     * -METHOD-
     * @summary 刷新tree内容
     * @description 刷新tree内容
     * @method refreshData
     * @since 0.1
     */
    this.refreshData = function() {
        $('.cui_treeBody',_context_).empty();
        this.privateShowNodes(_tree_["_root"], $('.cui_treeBody',_context_));
        $(".cui_treeTable",_context_).cui_treeTable({
            initialState: _config_["collapsed"]?"collapsed":"expanded"
        });
        $(".cui_treeTable tbody tr").mousedown(function() {
            $("tr.selected").removeClass("selected");
            $(this).addClass("selected");
        });
        $(".cui_treeTable tbody tr span").mousedown(function() {
            $($(this).parents("tr")[0]).trigger("mousedown");
        });
        return _self_;
    }
    /**
     * -METHOD-
     * @summary 刷新tree头部
     * @description 刷新tree头部
     * @method refreshHeader
     * @since 0.1
     */
    this.refreshHeader = function() {
        $('.cui_treeHead',_context_).empty();

        var cell = $(_view_.headerCellHtml);
        this.privateSetStyle(cell, _treeCol_);
        $(".cui_treeHead",_context_).append(cell.text(_treeCol_.name));


        for (var i in _idxs_) {
            if (_columns_[_idxs_[i]]) {
                var cell = $(_view_.headerCellHtml);
                this.privateSetStyle(cell, _columns_[_idxs_[i]]);
                $(".cui_treeHead",_context_).append(cell.text(_columns_[_idxs_[i]].name));
            }
        }
        return _self_;
    }
    /**
     * -METHOD-
     * @summary 更新树节点
     * @description 更新树节点
     * @method updateNode
     * @param data json <节点数据>
     * @return CuiTreeTable
     * @since 0.1
     */
    this.updateNode = function(data) {
        if (typeof data[_treeCol_.idx] == 'undefined')return _self_;;
        var nodes = $('#node_' + data[_treeCol_.tid] + ' td');
        var content = data[_treeCol_.idx];
        var nick = content;
        if (typeof content == "string" && _treeCol_.style && _treeCol_.style.maxlength) {
            content = content.substr(0, _treeCol_.style.maxlength);
        }
        if (_cellCallbacks_[_treeCol_.idx]) {
            content = _cellCallbacks_[_treeCol_.idx].apply(_self_, [_treeCol_.idx,data]);
        }
        $(nodes[0]).find(' span').last().html(content).attr("title",nick);

        for (var i = 1; i < nodes.length; i++) {
            var idx =  _idxs_[i - 1];
            content = data[idx];
            nick = content;
            if (typeof content == "string" && _columns_[idx] && _columns_[idx]["maxlength"]) {
                content = content.substr(0, _columns_[idx]["maxlength"]);
            }
            if (_cellCallbacks_[idx]) {
                content = _cellCallbacks_[idx].apply(_self_, [idx, data]);
            }
            $(nodes[i]).html(content).attr("title",nick);
        }
        _data_[data[_treeCol_.idx]] = data;
        return _self_;
    }
    /**
     * -METHOD-
     * @summary 删除树节点
     * @description 删除树节点
     * @method removeNode
     * @param id int/string <节点id，tid>
     * @return CuiTreeTable
     * @since 0.1
     */
    this.removeNode = function(id) {
        if (typeof id == 'undefined')return _self_;;

        if (_tree_[id] && _tree_[id].length > 0)return _self_;

        var css = $('#node_' + id).attr('class').split(' ');
        var parentId = -1;
        for (var i = 0; i < css.length; i++) {
            if (css[i].indexOf(_view_.nodeCssStr) > -1) {
                parentId = css[i].substr(_view_.nodeCssStr.length);
                break;
            }
        }
        if (parentId != -1) {
            var children = _tree_[parentId];
            var index = 0;
            if (children) {
                if(children.length == 1){
                    var parentNode = $('#node_' + parentId);
                    parentNode.removeClass('parent');
                    parentNode.find('span:first').remove();
                    parentNode.find('span').last().removeClass(_config_["node_css"] ).addClass(_config_["leaf_css"] );
                }
            }
        }else{
            parentId = "_root";
        }
        var child =  _tree_[parentId];
        var nchild = [];
        for (var i in child) {
            if (child[i] != id) {
                nchild.push(child[i]);
            }
        }
        _tree_[parentId] = nchild;

        $('#node_' + id).remove();
        _data_[id] = null;
        return _self_;
    }
    /**
     * -METHOD-
     * @summary 添加树节点
     * @description 添加树节点
     * @method addNode
     * @param parentId int/string <父节点id，tid>
     * @param data json <节点数据>
     * @return CuiTreeTable
     * @since 0.1
     */
    this.addNode = function(data,pid) {
        if(typeof pid == 'undefined'){
            pid = '_root';
        }else if(typeof _data_[pid] == 'undefined'){
            return _self_;
        }
        var id = data[_treeCol_.tid];
        _data_[id] = data;
        if(_tree_[pid]){
           _tree_[pid].push(id);
        }else{
           _tree_[pid] = [id];
        }

//        if (_config_["process_data"] == 2) {
//            data[_config_["parent_tag"]] = parentId;
//            if (_tmp_)_tmp_.push(data);
//        } else {
//            var childrenNode = parentNode[_config_["children_tag"]];
//            if (!childrenNode)return _self_;
//            childrenNode.push(data);
//        }
        this.refreshData();
        return _self_;
    }


    this.privateSetStyle = function(obj, styles) {
        if (!styles)return;
        if (styles.width)obj.attr('width', styles.width);
        if (styles.height)obj.attr('height', styles.height);
        if (styles.title)obj.attr('title', styles.title);
        if (styles.style)obj.css(styles.style);
        if (styles.css)obj.addClass(styles.css);
    }

    /**
     * -METHOD-
     * @summary 显示tree
     * @description 显示tree
     * @method show
     * @param id string <设置显示id，树根据此id显示>
     * @return CuiTreeTable
     * @since 0.1
     */
    this.show = function(id) {
        if (!_treeCol_.tid)return null;
//        _id_ = id;
        if (id) {
            if (typeof id == 'string') {
                _context_ = $('#' + id);
            } else if (id.jquery) {
                _context_ = id;
            } else {
                _context_ = $(id);
            }
        }
        _context_.append(_view_.frameHtml);
        if(_config_.width){
            _context_.css({"width":_config_.width});
        }
        this.refreshHeader();
        this.initData();
		this.refreshData();
        return _self_;
    }
    /**
     * -METHOD-
     * @summary 设置tree节点显示的回调函数
     * @description 设置tree节点显示的回调函数
     * @method setCellCallback
     * @param idx string <列的idx>
     * @param func function <tree节点显示回调函数，返回显示内容>
     * @param data json <此节点的data对象>  func
     * @return CuiTreeTable
     * @since 0.1
     */
    this.setCellCallback = function(idx, func) {
        if(typeof idx == 'object'){
             for(var i in idx){
                if(typeof idx[i] == 'function'){
                    _cellCallbacks_[i] = idx[i];
                }
             }
        }
        else if (typeof func == "function") {
            _cellCallbacks_[idx] = func;
        }

        return _self_;
    }
    /**
     * -METHOD-
     * @summary 设置tree内容显示器
     * @description 设置tree内容显示器
     * @method setView
     * @param view CuiTreeTableView <CuiTreeTableView内容显示器>
     * @since 0.1
     */
    this.setView = function(view) {
        if (view)_view_ = view;
        return _self_;
    }

    if (options) {
        _tmp_ = options.data;
//        _id_ = options.id;
        this.setColumns(options.columns);
        this.addTreeColumn(options.tree);
        this.setConfig(options.config);
        if (options.cellCallback) {
            this.setCellCallback(options.cellCallback);
        }
    }
}
///EndClass
var CuiTreeTableView = function() {

    this.frameHtml = '<table class="cui_treeTable"><thead><tr class="cui_treeHead"></thead><tbody class="cui_treeBody"></tbody></table>';

    this.headerCellHtml = '<th></th>'

    this.bodyRowHtml = '<tr></tr>';

    this.bodyCellHtml = '<td></td>';

    this.contentHtml = '<span></span>';

    this.idStr = 'node_';

    this.nodeCssStr = 'cui_child_node_';
}

        ;
(function($) {
    var options;
    var defaultPaddingLeft;

    $.fn.cui_treeTable = function(opts) {
        options = $.extend({}, $.fn.cui_treeTable.defaults, opts);

        return this.each(function() {
            $(this).addClass("cui_treeTable").find("tbody tr").each(function() {
                // Initialize root nodes only if possible
                if (!options.expandable || $(this)[0].className.search("cui_child_") == -1) {
                    // To optimize performance of indentation, I retrieve the padding-left
                    // value of the first root node. This way I only have to call +css+
                    // once.
                    if (isNaN(defaultPaddingLeft)) {
                        defaultPaddingLeft = parseInt($($(this).children("td")[options.treeColumn]).css('padding-left'), 10);
                    }

                    initialize($(this));
                } else if (options.initialState == "collapsed") {
                    this.style.display = "none"; // Performance! $(this).hide() is slow...
                }
            });
        });
    };

    $.fn.cui_treeTable.defaults = {
        childPrefix: "cui_child_",
        clickableNodeNames: false,
        expandable: true,
        indent: 15,
        initialState: "collapsed",
        treeColumn: 0
    };

    // Recursively hide all node's children in a tree
    $.fn.collapse = function() {
        $(this).addClass("collapsed");

        childrenOf($(this)).each(function() {
            if (!$(this).hasClass("collapsed")) {
                $(this).collapse();
            }

            this.style.display = "none"; // Performance! $(this).hide() is slow...
        });

        return this;
    };

    // Recursively show all node's children in a tree
    $.fn.expand = function() {
        $(this).removeClass("collapsed").addClass("expanded");

        childrenOf($(this)).each(function() {
            initialize($(this));

            if ($(this).is(".expanded.parent")) {
                $(this).expand();
            }

            // this.style.display = "table-row"; // Unfortunately this is not possible with IE :-(
            $(this).show();
        });

        return this;
    };

    // Add an entire branch to +destination+
    $.fn.appendBranchTo = function(destination) {
        var node = $(this);
        var parent = parentOf(node);

        var ancestorNames = $.map(ancestorsOf($(destination)), function(a) {
            return a.id;
        });

        // Conditions:
        // 1: +node+ should not be inserted in a location in a branch if this would
        //    result in +node+ being an ancestor of itself.
        // 2: +node+ should not have a parent OR the destination should not be the
        //    same as +node+'s current parent (this last condition prevents +node+
        //    from being moved to the same location where it already is).
        // 3: +node+ should not be inserted as a child of +node+ itself.
        if ($.inArray(node[0].id, ancestorNames) == -1 && (!parent || (destination.id != parent[0].id)) && destination.id != node[0].id) {
            indent(node, ancestorsOf(node).length * options.indent * -1); // Remove indentation

            if (parent) {
                node.removeClass(options.childPrefix + parent[0].id);
            }

            node.addClass(options.childPrefix + destination.id);
            move(node, destination); // Recursively move nodes to new location
            indent(node, ancestorsOf(node).length * options.indent);
        }

        return this;
    };

    // Add reverse() function from JS Arrays
    $.fn.reverse = function() {
        return this.pushStack(this.get().reverse(), arguments);
    };

    // Toggle an entire branch
    $.fn.toggleBranch = function() {
        if ($(this).hasClass("collapsed")) {
            $(this).expand();
        } else {
            $(this).removeClass("expanded").collapse();
        }

        return this;
    };

    // === Private functions

    function ancestorsOf(node) {
        var ancestors = [];
        while (node = parentOf(node)) {
            ancestors[ancestors.length] = node[0];
        }
        return ancestors;
    }

    ;

    function childrenOf(node) {
        return $("table.cui_treeTable tbody tr." + options.childPrefix + node[0].id);
    }

    ;

    function getPaddingLeft(node) {
        var paddingLeft = parseInt(node[0].style.paddingLeft, 10);
        return (isNaN(paddingLeft)) ? defaultPaddingLeft : paddingLeft;
    }

    function indent(node, value) {
        var cell = $(node.children("td")[options.treeColumn]);
        cell[0].style.paddingLeft = getPaddingLeft(cell) + value + "px";

        childrenOf(node).each(function() {
            indent($(this), value);
        });
    }

    ;

    function initialize(node) {
        if (!node.hasClass("initialized")) {
            node.addClass("initialized");

            var childNodes = childrenOf(node);

            if (!node.hasClass("parent") && childNodes.length > 0) {
                node.addClass("parent");
            }

            if (node.hasClass("parent")) {
                var cell = $(node.children("td")[options.treeColumn]);
                var padding = getPaddingLeft(cell) + options.indent;

                childNodes.each(function() {
                    $(this).children("td")[options.treeColumn].style.paddingLeft = padding + "px";
                });

                if (options.expandable) {
                    cell.prepend('<span style="margin-left: ' + options.indent + 'px; padding-left: ' + options.indent + 'px" class="expander"></span>');
                    $(cell[0].firstChild).click(function() {
                        node.toggleBranch();
                    });

                    if (options.clickableNodeNames) {
                        cell[0].style.cursor = "pointer";
                        $(cell).click(function(e) {
                            // Don't double-toggle if the click is on the existing expander icon
                            if (e.target.className != 'expander') {
                                node.toggleBranch();
                            }
                        });
                    }

                    // Check for a class set explicitly by the user, otherwise set the default class
                    if (!(node.hasClass("expanded") || node.hasClass("collapsed"))) {
                        node.addClass(options.initialState);
                    }

                    if (node.hasClass("expanded")) {
                        node.expand();
                    }
                }
            }
        }
    }

    ;

    function move(node, destination) {
        node.insertAfter(destination);
        childrenOf(node).reverse().each(function() {
            move($(this), node[0]);
        });
    }

    ;

    function parentOf(node) {
        var classNames = node[0].className.split(' ');

        for (key in classNames) {
            if (classNames[key].match("cui_child_")) {
                return $("#" + classNames[key].substring(9));
            }
        }
    }

    ;
})(jQuery);
