easyui源码翻译1.32--TreeGrid(树形表格)

前言

扩展自$.fn.datagrid.defaults。使用$.fn.treegrid.defaults重写默认值对象。下载该插件翻译源码

树形表格用于显示分层数据表格。它是基于数据表格、组合树控件和可编辑表格。树形表格允许用户创建可定制的、异步展开行和显示在多列上的分层数据。

源码

/**
 * jQuery EasyUI 1.3.2
 * 
 *翻译:qq 1364386878 下拉树
 */
(function ($) {
    //获取行索引
    function getObjectIndex(rows,row) {
        for (var i = 0, _2 = rows.length; i < _2; i++) {
            if (rows[i] ==row) {
                return i;
            }
        }
        return -1;
    };
    //传递数据
    function transferData(rows,row) {
        var index = getObjectIndex(rows,row);
        if (index != -1) {
            rows.splice(index, 1);
        }
    };
    //初始化函数
    function initGrid(jq) {
        var options = $.data(jq, "treegrid").options;
        //初始化表格 具体参考datagrid属性、事件
        $(jq).datagrid($.extend({}, options, {
            url: null,
            data: null,
            loader: function () {
                return false;
            },
            onLoadSuccess: function () {
            },
            onResizeColumn: function (field, width) {
                _setRowHeight(jq);
                options.onResizeColumn.call(jq, field, width);
            },
            onSortColumn: function (sortName, sortName) {
                options.sortName = sortName;
                options.sortOrder = sortName;
                if (options.remoteSort) {
                    request(jq);
                } else {
                    var data = $(jq).treegrid("getData");
                    _loadData(jq, 0, data);
                }
                options.onSortColumn.call(jq, sortName, sortName);
            },

            onBeforeEdit: function (rowIndex, rowData) {
                if (options.onBeforeEdit.call(jq, rowData) == false) {
                    return false;
                }
            },
            onAfterEdit: function (rowIndex, row, newValues) {
                options.onAfterEdit.call(jq, row, newValues);
            },
            onCancelEdit: function (rowIndex, row) {
                options.onCancelEdit.call(jq, row);
            },
            onSelect: function (parm) {
                options.onSelect.call(jq, find(jq, parm));
            },
            onUnselect: function (parm) {
                options.onUnselect.call(jq, find(jq, parm));
            },
            onSelectAll: function () {
                options.onSelectAll.call(jq, $.data(jq, "treegrid").data);
            },
            onUnselectAll: function () {
                options.onUnselectAll.call(jq, $.data(jq, "treegrid").data);
            },
            onCheck: function (parm) {
                options.onCheck.call(jq, find(jq, parm));
            },
            onUncheck: function (parm) {
                options.onUncheck.call(jq, find(jq, parm));
            },
            onCheckAll: function () {
                options.onCheckAll.call(jq, $.data(jq, "treegrid").data);
            },
            onUncheckAll: function () {
                options.onUncheckAll.call(jq, $.data(jq, "treegrid").data);
            },
            onClickRow: function (parm) {
                options.onClickRow.call(jq, find(jq, parm));
            },
            onDblClickRow: function (parm) {
                options.onDblClickRow.call(jq, find(jq, parm));
            },
            onClickCell: function (id, field) {
                options.onClickCell.call(jq, field, find(jq, id));
            },
            onDblClickCell: function (id, parm) {
                options.onDblClickCell.call(jq, parm, find(jq, id));
            },
            onRowContextMenu: function (e, id) {
                options.onContextMenu.call(jq, e, find(jq, id));
            }
        }));
        if (options.pagination) {
            var getPager = $(jq).datagrid("getPager");
            getPager.pagination({
                pageNumber: options.pageNumber,
                pageSize: options.pageSize,
                pageList: options.pageList,
                onSelectPage: function (pageNumber, pageNumber) {
                    options.pageNumber = pageNumber;
                    options.pageSize = pageNumber;
                    request(jq);
                }
            });
            options.pageSize = getPager.pagination("options").pageSize;
        }
    };
    //修正指定的行高
    function _setRowHeight(jq, id) {
        var options = $.data(jq, "datagrid").options;
        var dc = $.data(jq, "datagrid").dc;
        if (!dc.body1.is(":empty") && (!options.nowrap || options.autoRowHeight)) {
            if (id != undefined) {
                var children = _getChildren(jq, id);
                for (var i = 0; i < children.length; i++) {
                    setRowHeight(children[i][options.idField]);
                }
            }
        }
        $(jq).datagrid("fixRowHeight", id);

        function setRowHeight(_28) {
            var tr1 = options.finder.getTr(jq, _28, "body", 1);
            var tr2 = options.finder.getTr(jq, _28, "body", 2);
            tr1.css("height", "");
            tr2.css("height", "");
            var maxheight = Math.max(tr1.height(), tr2.height());
            tr1.css("height", maxheight);
            tr2.css("height", maxheight);
        };
    };
    //设置行序号
    function fixRowNumbers(jq) {
        var dc = $.data(jq, "datagrid").dc;
        var options = $.data(jq, "treegrid").options;
        if (!options.rownumbers) {
            return;
        }
        dc.body1.find("div.datagrid-cell-rownumber").each(function (i) {
            $(this).html(i + 1);
        });
    };
    //绑定事件
    function bindEvents(jq) {
        var dc = $.data(jq, "datagrid").dc;
        var body = dc.body1.add(dc.body2);
        var handler = ($.data(body[0], "events") || $._data(body[0], "events")).click[0].handler;
        dc.body1.add(dc.body2).bind("mouseover", function (e) {//当鼠标移上时
            var tt = $(e.target);
            var tr = tt.closest("tr.datagrid-row");
            if (!tr.length) {
                return;
            }
            if (tt.hasClass("tree-hit")) {
                tt.hasClass("tree-expanded") ? tt.addClass("tree-expanded-hover") : tt.addClass("tree-collapsed-hover");
            }
            e.stopPropagation();
        }).bind("mouseout", function (e) {//dang鼠标离开时
            var tt = $(e.target);
            var tr = tt.closest("tr.datagrid-row");
            if (!tr.length) {
                return;
            }
            if (tt.hasClass("tree-hit")) {
                tt.hasClass("tree-expanded") ? tt.removeClass("tree-expanded-hover") : tt.removeClass("tree-collapsed-hover");
            }
            e.stopPropagation();
        }).unbind("click").bind("click", function (e) {//触发点击事件
            var tt = $(e.target);
            var tr = tt.closest("tr.datagrid-row");
            if (!tr.length) {
                return;
            }
            if (tt.hasClass("tree-hit")) {
                _toggle(jq, tr.attr("node-id"));
            } else {
                handler(e);
            }
            e.stopPropagation();
        });
    };

    function initSubTree(jq, nodeId) {
        var options = $.data(jq, "treegrid").options;
        var tr1 = options.finder.getTr(jq, nodeId, "body", 1);
        var tr2 = options.finder.getTr(jq, nodeId, "body", 2);
        //getColumnFields返回列字段。如果设置了frozen属性为true,将返回固定列的字段名
        var colspan1 = $(jq).datagrid("getColumnFields", true).length + (options.rownumbers ? 1 : 0);
        var colspan2 = $(jq).datagrid("getColumnFields", false).length;
        createSubTree(tr1, colspan1);
        createSubTree(tr2, colspan2);
        function createSubTree(tr, colspan) {
            $("<tr class=\"treegrid-tr-tree\">" + "<td style=\"border:0px\" colspan=\"" + colspan + "\">" + "<div></div>" + "</td>" + "</tr>").insertAfter(tr);
        };
    };
    //读取树形表格数据
    function _loadData(jq, nodeId, param, param) {
        var options = $.data(jq, "treegrid").options;
        var dc = $.data(jq, "datagrid").dc;
        param = options.loadFilter.call(jq, param, nodeId);
        var row = find(jq, nodeId);
        if (row) {
            var tr1 = options.finder.getTr(jq, nodeId, "body", 1);
            var tr2 = options.finder.getTr(jq, nodeId, "body", 2);
            var cc1 = tr1.next("tr.treegrid-tr-tree").children("td").children("div");
            var cc2 = tr2.next("tr.treegrid-tr-tree").children("td").children("div");
        } else {
            var cc1 = dc.body1;
            var cc2 = dc.body2;
        }
        if (!param) {
            $.data(jq, "treegrid").data = [];
            cc1.empty();
            cc2.empty();
        }
        if (options.view.onBeforeRender) {
            options.view.onBeforeRender.call(options.view, jq, nodeId, param);
        }
        options.view.render.call(options.view, jq, cc1, true);
        options.view.render.call(options.view, jq, cc2, false);
        if (options.showFooter) {
            options.view.renderFooter.call(options.view, jq, dc.footer1, true);
            options.view.renderFooter.call(options.view, jq, dc.footer2, false);
        }
        if (options.view.onAfterRender) {
            options.view.onAfterRender.call(options.view, jq);
        }
        options.onLoadSuccess.call(jq, row, param);
        if (!nodeId && options.pagination) {
            var total = $.data(jq, "treegrid").total;
            var getPager = $(jq).datagrid("getPager");
            if (getPager.pagination("options").total != total) {
                getPager.pagination({ total: total });
            }
        }
        _setRowHeight(jq);
        fixRowNumbers(jq);
        $(jq).treegrid("autoSizeColumn");
    };

    function request(jq, parentId, param, isAppend, callBack) {
        var options = $.data(jq, "treegrid").options;
        var body = $(jq).datagrid("getPanel").find("div.datagrid-body");
        if (param) {
            options.queryParams = param;
        }
        var queryParams = $.extend({}, options.queryParams);
        if (options.pagination) {
            $.extend(queryParams, { page: options.pageNumber, rows: options.pageSize });
        }
        if (options.sortName) {
            $.extend(queryParams, { sort: options.sortName, order: options.sortOrder });
        }
        var row = find(jq, parentId);
        if (options.onBeforeLoad.call(jq, row, queryParams) == false) {
            return;
        }
        var folder = body.find("tr[node-id=" + parentId + "] span.tree-folder");
        folder.addClass("tree-loading");
        $(jq).treegrid("loading");
        var loaded = options.loader.call(jq, queryParams, function (parm) {
            folder.removeClass("tree-loading");
            $(jq).treegrid("loaded");
            _loadData(jq, parentId, parm, isAppend);
            if (callBack) {
                callBack();
            }
        }, function () {
            folder.removeClass("tree-loading");
            $(jq).treegrid("loaded");
            options.onLoadError.apply(jq, arguments);
            if (callBack) {
                callBack();
            }
        });
        if (loaded == false) {
            folder.removeClass("tree-loading");
            $(jq).treegrid("loaded");
        }
    };
    //获取根节点,返回节点对象
    function _getRoot(target) {
        var roots = _getRoots(target);
        if (roots.length) {
            return roots[0];
        } else {
            return null;
        }
    };
    //获取所有根节点,返回节点对象
    function _getRoots(target) {
        return $.data(target, "treegrid").data;
    };
    //获取父节点。
    function _getParent(jq, id) {
        var row = find(jq, id);
        if (row._parentId) {
            return find(jq, row._parentId);
        } else {
            return null;
        }
    };
    //获取子节点
    function _getChildren(jq, id) {
        var options = $.data(jq, "treegrid").options;
        var body = $(jq).datagrid("getPanel").find("div.datagrid-view2 div.datagrid-body");
        var children = [];
        if (id) {
            findChildren(id);
        } else {
            var roots = _getRoots(jq);
            for (var i = 0; i < roots.length; i++) {
                children.push(roots[i]);
                findChildren(roots[i][options.idField]);
            }
        }
        function findChildren(id) {
            var node = find(jq, id);
            if (node && node.children) {
                for (var i = 0, len = node.children.length; i < len; i++) {
                    var child = node.children[i];
                    children.push(child);
                    findChildren(child[options.idField]);
                }
            }
        };
        return children;
    };
    //获取选择的节点并返回它,如果没有节点被选中则返回null
    function _getSelected(jq) {
        var target = _getSelections(jq);
        if (target.length) {
            return target[0];
        } else {
            return null;
        }
    };
    //获取所有选择的节点。
    function _getSelections(jq) {
        var selectedRows = [];
        var panel = $(jq).datagrid("getPanel");
        panel.find("div.datagrid-view2 div.datagrid-body tr.datagrid-row-selected").each(function () {
            var id = $(this).attr("node-id");
            selectedRows.push(find(jq, id));
        });
        return selectedRows;
    };
    //获取指定节点等级。
    function _getLevel(jq, id) {
        if (!id) {
            return 0;
        }
        var options = $.data(jq, "treegrid").options;
        var gridView = $(jq).datagrid("getPanel").children("div.datagrid-view");
        var treeNode = gridView.find("div.datagrid-body tr[node-id=" + id + "]").children("td[field=" + options.treeField + "]");
        return treeNode.find("span.tree-indent,span.tree-hit").length;
    };
    //查找指定节点并返回节点数据。
    function find(jq, id) {
        var options = $.data(jq, "treegrid").options;
        var data = $.data(jq, "treegrid").data;
        var cc = [data];
        while (cc.length) {
            var c = cc.shift();
            for (var i = 0; i < c.length; i++) {
                var rowData = c[i];
                if (rowData[options.idField] == id) {
                    return rowData;
                } else {
                    if (rowData["children"]) {
                        cc.push(rowData["children"]);
                    }
                }
            }
        }
        return null;
    };
    //折叠一个节点。
    function _collapse(jq, id) {
        var options = $.data(jq, "treegrid").options;
        var row = find(jq, id);
        var tr = options.finder.getTr(jq, id);
        var hit = tr.find("span.tree-hit");
        if (hit.length == 0) {
            return;
        }
        if (hit.hasClass("tree-collapsed")) {
            return;
        }
        if (options.onBeforeCollapse.call(jq, row) == false) {
            return;
        }
        hit.removeClass("tree-expanded tree-expanded-hover").addClass("tree-collapsed");
        hit.next().removeClass("tree-folder-open");
        row.state = "closed";
        tr = tr.next("tr.treegrid-tr-tree");
        var cc = tr.children("td").children("div");
        if (options.animate) {
            cc.slideUp("normal", function () {
                $(jq).treegrid("autoSizeColumn");
                _setRowHeight(jq, id);
                options.onCollapse.call(jq, row);
            });
        } else {
            cc.hide();
            $(jq).treegrid("autoSizeColumn");
            _setRowHeight(jq, id);
            options.onCollapse.call(jq, row);
        }
    };
    //展开一个节点。
    function expand(jq, id) {
        var options = $.data(jq, "treegrid").options;
        var tr = options.finder.getTr(jq, id);
        var hit = tr.find("span.tree-hit");
        var row = find(jq, id);
        if (hit.length == 0) {
            return;
        }
        if (hit.hasClass("tree-expanded")) {
            return;
        }
        if (options.onBeforeExpand.call(jq, row) == false) {
            return;
        }
        hit.removeClass("tree-collapsed tree-collapsed-hover").addClass("tree-expanded");
        hit.next().addClass("tree-folder-open");
        var subtree = tr.next("tr.treegrid-tr-tree");
        if (subtree.length) {
            var cc = subtree.children("td").children("div");
            expandSubtree(cc);
        } else {
            initSubTree(jq, row[options.idField]);
            var subtree = tr.next("tr.treegrid-tr-tree");
            var cc = subtree.children("td").children("div");
            cc.hide();
            request(jq, row[options.idField], { id: row[options.idField] }, true, function () {
                if (cc.is(":empty")) {
                    subtree.remove();
                } else {
                    expandSubtree(cc);
                }
            });
        }
        function expandSubtree(cc) {
            row.state = "open";
            if (options.animate) {
                cc.slideDown("normal", function () {
                    $(jq).treegrid("autoSizeColumn");
                    _setRowHeight(jq, id);
                    options.onExpand.call(jq, row);
                });
            } else {
                cc.show();
                $(jq).treegrid("autoSizeColumn");
                _setRowHeight(jq, id);
                options.onExpand.call(jq, row);
            }
        };
    };
    //节点展开/折叠状态触发器
    function _toggle(jq, id) {
        var options = $.data(jq, "treegrid").options;
        var tr = options.finder.getTr(jq, id);
        var hit = tr.find("span.tree-hit");
        if (hit.hasClass("tree-expanded")) {
            _collapse(jq, id);
        } else {
            expand(jq, id);
        }
    };
    //折叠所有节点。
    function _collapseAll(jq, id) {
        var options = $.data(jq, "treegrid").options;
        var children = _getChildren(jq, id);
        if (id) {
            children.unshift(find(jq, id));
        }
        for (var i = 0; i < children.length; i++) {
            _collapse(jq, children[i][options.idField]);
        }
    };
    //展开所有节点。
    function _expandAll(jq, jq) {
        var options = $.data(jq, "treegrid").options;
        var children = _getChildren(jq, jq);
        if (jq) {
            children.unshift(find(jq, jq));
        }
        for (var i = 0; i < children.length; i++) {
            expand(jq, children[i][options.idField]);
        }
    };
    //打开从根节点到指定节点之间的所有节点。
    function _expandTo(jq, id) {
        var options = $.data(jq, "treegrid").options;
        var ids = [];
        var p = _getParent(jq, id);
        while (p) {
            var id = p[options.idField];
            ids.unshift(id);
            p = _getParent(jq, id);
        }
        for (var i = 0; i < ids.length; i++) {
            expand(jq, ids[i]);
        }
    };
    //追加节点到一个父节点,'param'参数包含如下属性:
    //parent:父节点ID,如果未指定则追加到根节点。
    //data:数组,节点数据。
    function _append(jq, param) {
        var options = $.data(jq, "treegrid").options;
        if (param.parent) {
            var tr = options.finder.getTr(jq, param.parent);
            if (tr.next("tr.treegrid-tr-tree").length == 0) {
                initSubTree(jq, param.parent);
            }
            var cell = tr.children("td[field=" + options.treeField + "]").children("div.datagrid-cell");
            var icon = cell.children("span.tree-icon");
            if (icon.hasClass("tree-file")) {
                icon.removeClass("tree-file").addClass("tree-folder");
                var hit = $("<span class=\"tree-hit tree-expanded\"></span>").insertBefore(icon);
                if (hit.prev().length) {
                    hit.prev().remove();
                }
            }
        }
        _loadData(jq, param.parent, param.data, true);
    };
    //插入一个新节点到指定节点。'param'参数包含一下参数:
    //before:插入指定节点ID值之前。
    //after:插入指定节点ID值之后。
    //data:新节点数据。 
    function insert(jq, param) {
        var ref = param.before || param.after;
        var options = $.data(jq, "treegrid").options;
        var parentn = _getParent(jq, ref);
        _append(jq, { parent: (parentn ? parentn[options.idField] : null), data: [param.data] });
        _insert(true);
        _insert(false);
        fixRowNumbers(jq);
        //插入数据
        function _insert(before) {
            var step = before ? 1 : 2;
            var tr = options.finder.getTr(jq, param.data[options.idField], "body", step);
            var btable = tr.closest("table.datagrid-btable");//序号列
            tr = tr.parent().children();
            var tr = options.finder.getTr(jq, ref, "body", step);
            if (param.before) {
                tr.insertBefore(tr);
            } else {
                var sub = tr.next("tr.treegrid-tr-tree");
                tr.insertAfter(sub.length ? sub : tr);
            }
            btable.remove();
        };
    };
    //移除一个节点和他的所有子节点。
    function _remove(jq, nodeId) {
        var options = $.data(jq, "treegrid").options;
        var tr = options.finder.getTr(jq, nodeId);
        tr.next("tr.treegrid-tr-tree").remove();
        tr.remove();
        var parent = del(nodeId);
        if (parent) {
            if (parent.children.length == 0) {
                tr = options.finder.getTr(jq, parent[options.idField]);
                tr.next("tr.treegrid-tr-tree").remove();
                var cell = tr.children("td[field=" + options.treeField + "]").children("div.datagrid-cell");
                cell.find(".tree-icon").removeClass("tree-folder").addClass("tree-file");
                cell.find(".tree-hit").remove();
                $("<span class=\"tree-indent\"></span>").prependTo(cell);
            }
        }
        fixRowNumbers(jq);
        function del(id) {
            var cc;
            var parent = _getParent(jq, nodeId);
            if (parent) {
                cc = parent.children;
            } else {
                cc = $(jq).treegrid("getData");
            }
            for (var i = 0; i < cc.length; i++) {
                if (cc[i][options.idField] == id) {
                    cc.splice(i, 1);
                    break;
                }
            }
            return parent;
        };
    };
    //实例化组建
    $.fn.treegrid = function (target, parm) {
        if (typeof target == "string") {
            var method = $.fn.treegrid.methods[target];
            if (method) {
                return method(this, parm);
            } else {
                return this.datagrid(target, parm);
            }
        }
        target = target || {};
        return this.each(function () {
            var treegrid = $.data(this, "treegrid");
            if (treegrid) {
                $.extend(treegrid.options, target);
            } else {
                treegrid = $.data(this, "treegrid", { options: $.extend({}, $.fn.treegrid.defaults, $.fn.treegrid.parseOptions(this), target), data: [] });
            }
            initGrid(this);
            if (treegrid.options.data) {
                $(this).treegrid("loadData", treegrid.options.data);
            }
            request(this);
            bindEvents(this);
        });
    };
    //默认方法
    $.fn.treegrid.methods = {
        //返回树形表格的属性
        options: function (jq) {
            return $.data(jq[0], "treegrid").options;
        },
        //设置树形表格大小,options包含2个属性:
        //width:树形表格的新宽度。
        //height:树形表格的新高度。
        resize: function (jq, options) {
            return jq.each(function () {
                $(this).datagrid("resize", options);
            });
        },
        //修正指定的行高
        fixRowHeight: function (jq, id) {
            return jq.each(function () {
                _setRowHeight(this, id);
            });
        },
        //读取树形表格数据
        loadData: function (jq, data) {
            return jq.each(function () {
                _loadData(this, null, data);
            });
        },
        //重新加载树形表格数据。如果'id'属性有值,将重新载入指定树形行,否则重新载入所有行
        reload: function (jq, id) {
            return jq.each(function () {
                if (id) {
                    var record = $(this).treegrid("find", id);
                    if (record.children) {
                        record.children.splice(0, record.children.length);
                    }
                    var gridBody = $(this).datagrid("getPanel").find("div.datagrid-body");
                    var tr = gridBody.find("tr[node-id=" + id + "]");
                    tr.next("tr.treegrid-tr-tree").remove();
                    var hit = tr.find("span.tree-hit");
                    hit.removeClass("tree-expanded tree-expanded-hover").addClass("tree-collapsed");
                    expand(this, id);
                } else {
                    request(this, null, {});
                }
            });
        },
        //重新载入页脚数据
        reloadFooter: function (jq, footer) {
            return jq.each(function () {
                var options = $.data(this, "treegrid").options;
                var dc = $.data(this, "datagrid").dc;
                if (footer) {
                    $.data(this, "treegrid").footer = footer;
                }
                if (options.showFooter) {
                    options.view.renderFooter.call(options.view, this, dc.footer1, true);
                    options.view.renderFooter.call(options.view, this, dc.footer2, false);
                    if (options.view.onAfterRender) {
                        options.view.onAfterRender.call(options.view, this);
                    }
                    $(this).treegrid("fixRowHeight");
                }
            });
        },
        //获取载入数据
        getData: function (jq) {
            return $.data(jq[0], "treegrid").data;
        },
        //获取页脚数据
        getFooterRows: function (jq) {
            return $.data(jq[0], "treegrid").footer;
        },
        //获取根节点,返回节点对象
        getRoot: function (jq) {
            return _getRoot(jq[0]);
        },
        //获取所有根节点,返回节点数组
        getRoots: function (jq) {
            return _getRoots(jq[0]);
        },
        //获取父节点。
        getParent: function (jq, id) {
            return _getParent(jq[0], id);
        },
        //获取子节点
        getChildren: function (jq, id) {
            return _getChildren(jq[0], id);
        },
        //获取选择的节点并返回它,如果没有节点被选中则返回null。
        getSelected: function (jq) {
            return _getSelected(jq[0]);
        },
        //获取所有选择的节点。
        getSelections: function (jq) {
            return _getSelections(jq[0]);
        },
        //获取指定节点等级
        getLevel: function (jq, id) {
            return _getLevel(jq[0], id);
        },
        //查找指定节点并返回节点数据
        find: function (jq, id) {
            return find(jq[0], id);
        },
        //判断是否是子节点
        isLeaf: function (jq, id) {
            var options = $.data(jq[0], "treegrid").options;
            var tr = options.finder.getTr(jq[0], id);
            var hit = tr.find("span.tree-hit");
            return hit.length == 0;
        },
        //选择一个节点。
        select: function (jq, id) {
            return jq.each(function () {
                $(this).datagrid("selectRow", id);
            });
        },
        //反选一个节点。
        unselect: function (jq, id) {
            return jq.each(function () {
                $(this).datagrid("unselectRow", id);
            });
        },
        //折叠一个节点。
        collapse: function (jq, id) {
            return jq.each(function () {
                _collapse(this, id);
            });
        },
        //展开一个节点。
        expand: function (jq, id) {
            return jq.each(function () {
                expand(this, id);
            });
        },
        //节点展开/折叠状态触发器。
        toggle: function (jq, id) {
            return jq.each(function () {
                _toggle(this, id);
            });
        },
        //折叠所有节点。
        collapseAll: function (jq, id) {
            return jq.each(function () {
                _collapseAll(this, id);
            });
        },
        //展开所有节点。
        expandAll: function (jq, id) {
            return jq.each(function () {
                _expandAll(this, id);
            });
        },
        //打开从根节点到指定节点之间的所有节点
        expandTo: function (jq, id) {
            return jq.each(function () {
                _expandTo(this, id);
            });
        },
        //追加节点到一个父节点,'param'参数包含如下属性:
        //parent:父节点ID,如果未指定则追加到根节点。
        //data:数组,节点数据。
        append: function (jq, param) {
            return jq.each(function () {
                _append(this, param);
            });
        },
        //插入一个新节点到指定节点。'param'参数包含一下参数:
        //before:插入指定节点ID值之前。
        //after:插入指定节点ID值之后。
        //data:新节点数据       
        insert: function (jq, param) {
            return jq.each(function () {
                insert(this, param);
            });
        }, 
        //移除一个节点和他的所有子节点。
        remove: function (jq, id) {
            return jq.each(function () {
                _remove(this, id);
            });
        },
        //弹出并返回节点数据以及它的子节点之后删除
        pop: function (jq, id) {
            var row = jq.treegrid("find", id);
            jq.treegrid("remove", id);
            return row;
        },
        //刷新指定节点
        refresh: function (jq, id) {
            return jq.each(function () {
                var options = $.data(this, "treegrid").options;
                options.view.refreshRow.call(options.view, this, id);
            });
        },
        //options更新指定节点。'param'参数包含以下属性:
        //id:要更新的节点的ID。
        //row:新的行数据
        update: function (jq, param) {
            return jq.each(function () {
                var options = $.data(this, "treegrid").options;
                options.view.updateRow.call(options.view, this, param.id, param.row);
            });
        },
        //开始编辑一个节点
        beginEdit: function (jq, id) {
            return jq.each(function () {
                $(this).datagrid("beginEdit", id);
                $(this).treegrid("fixRowHeight", id);
            });
        },
        //结束编辑一个节点
        endEdit: function (jq, id) {
            return jq.each(function () {
                $(this).datagrid("endEdit", id);
            });
        },
        //取消编辑一个节点。
        cancelEdit: function (jq, id) {
            return jq.each(function () {
                $(this).datagrid("cancelEdit", id);
            });
        }
    };
    //解析器配置
    $.fn.treegrid.parseOptions = function (target) {
        return $.extend({}, $.fn.datagrid.parseOptions(target),
            $.parser.parseOptions(target, ["treeField", { animate: "boolean" }]));
    };
    //定义数据表格的视图 该视图是一个对象,将告诉数据表格如何渲染行。该对象必须定义下列函
    var _view = $.extend({}, $.fn.datagrid.defaults.view, {
        //    数据加载时调用。
        //jq:DOM对象,数据表格对象。
        //container:行容器。
        //frozen:指明如何渲染冻结容器。
        render: function (jq, container, frozen) {
            var options = $.data(jq, "treegrid").options;
            var fields = $(jq).datagrid("getColumnFields", frozen);
            var rowIdPrefix = $.data(jq, "datagrid").rowIdPrefix;
            if (frozen) {
                if (!(options.rownumbers || (options.frozenColumns && options.frozenColumns.length))) {
                    return;
                }
            }
            var grid = this;
            var nodes = buildTreeNodes(frozen, this.treeLevel, this.treeNodes);
            $(container).append(nodes.join(""));
            //创建树节点
            function buildTreeNodes(frozen, treeLevel, rows) {
                var html = ["<table class=\"datagrid-btable\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tbody>"];
                for (var i = 0; i < rows.length; i++) {
                    var row = rows[i];
                    if (row.state != "open" && row.state != "closed") {
                        row.state = "open";
                    }
                    var style = options.rowStyler ? options.rowStyler.call(jq, row) : "";
                    var attr = style ? "style=\"" + style + "\"" : "";
                    var rowid = rowIdPrefix + "-" + (frozen ? 1 : 2) + "-" + row[options.idField];
                    html.push("<tr id=\"" + rowid + "\" class=\"datagrid-row\" node-id=" + row[options.idField] + " " + attr + ">");
                    html = html.concat(grid.renderRow.call(grid, jq, fields, frozen, treeLevel, row));
                    html.push("</tr>");
                    if (row.children && row.children.length) {
                        var tt = buildTreeNodes(frozen, treeLevel + 1, row.children);
                        var v = row.state == "closed" ? "none" : "block";
                        html.push("<tr class=\"treegrid-tr-tree\"><td style=\"border:0px\" colspan="
                            + (fields.length + (options.rownumbers ? 1 : 0))
                            + "><div style=\"display:"
                            + v + "\">");
                        html = html.concat(tt);
                        html.push("</div></td></tr>");
                    }
                }
                html.push("</tbody></table>");
                return html;
            };
        },
        //渲染底部
        renderFooter: function (jq, grid, frozen) {
            var options = $.data(jq, "treegrid").options;
            var footer = $.data(jq, "treegrid").footer || [];
            var fields = $(jq).datagrid("getColumnFields", frozen);
            var html = ["<table class=\"datagrid-ftable\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tbody>"];
            for (var i = 0; i < footer.length; i++) {
                var row = footer[i];
                row[options.idField] = row[options.idField] || ("foot-row-id" + i);
                html.push("<tr class=\"datagrid-row\" node-id=" + row[options.idField] + ">");
                html.push(this.renderRow.call(this, jq, fields, frozen, 0, row));
                html.push("</tr>");
            }
            html.push("</tbody></table>");
            $(grid).html(html.join(""));
        },
        //渲染行
        renderRow: function (jq, fields, frozen, deepth, row) {
            var opts = $.data(jq, "treegrid").options;
            var cc = [];
            if (frozen && opts.rownumbers) {
                cc.push("<td class=\"datagrid-td-rownumber\"><div class=\"datagrid-cell-rownumber\">0</div></td>");
            }
            for (var i = 0; i < fields.length; i++) {
                var field = fields[i];
                var col = $(jq).datagrid("getColumnOption", field);
                if (col) {
                    var style = col.styler ? (col.styler(row[field], row) || "") : "";
                    var style2 = col.hidden ? "style=\"display:none;" + style + "\"" : (style ? "style=\"" + style + "\"" : "");
                    cc.push("<td field=\"" + field + "\" " + style2 + ">");
                    if (col.checkbox) {
                        var style2 = "";
                    } else {
                        var style2 = "";
                        if (col.align) {
                            style2 += "text-align:" + col.align + ";";
                        }
                        if (!opts.nowrap) {
                            style2 += "white-space:normal;height:auto;";
                        } else {
                            if (opts.autoRowHeight) {
                                style2 += "height:auto;";
                            }
                        }
                    }
                    cc.push("<div style=\"" + style2 + "\" ");
                    if (col.checkbox) {
                        cc.push("class=\"datagrid-cell-check ");
                    } else {
                        cc.push("class=\"datagrid-cell " + col.cellClass);
                    }
                    cc.push("\">");
                    if (col.checkbox) {
                        if (row.checked) {
                            cc.push("<input type=\"checkbox\" checked=\"checked\"");
                        } else {
                            cc.push("<input type=\"checkbox\"");
                        }
                        cc.push(" name=\"" + field + "\" value=\"" + (row[field] != undefined ? row[field] : "") + "\"/>");
                    } else {
                        var val = null;
                        if (col.formatter) {
                            val = col.formatter(row[field], row);
                        } else {
                            val = row[field];
                        }
                        if (field == opts.treeField) {
                            for (var j = 0; j < deepth; j++) {
                                cc.push("<span class=\"tree-indent\"></span>");
                            }
                            if (row.state == "closed") {
                                cc.push("<span class=\"tree-hit tree-collapsed\"></span>");
                                cc.push("<span class=\"tree-icon tree-folder " + (row.iconCls ? row.iconCls : "") + "\"></span>");
                            } else {
                                if (row.children && row.children.length) {
                                    cc.push("<span class=\"tree-hit tree-expanded\"></span>");
                                    cc.push("<span class=\"tree-icon tree-folder tree-folder-open " + (row.iconCls ? row.iconCls : "") + "\"></span>");
                                } else {
                                    cc.push("<span class=\"tree-indent\"></span>");
                                    cc.push("<span class=\"tree-icon tree-file " + (row.iconCls ? row.iconCls : "") + "\"></span>");
                                }
                            }
                            cc.push("<span class=\"tree-title\">" + val + "</span>");
                        } else {
                            cc.push(val);
                        }
                    }
                    cc.push("</div>");
                    cc.push("</td>");
                }
            }
            return cc.join("");
        },
        //刷新行
        refreshRow: function (target, id) {
            this.updateRow.call(this, target, id, {});
        },
        //更新行
        updateRow: function (jq, id, row) {
            var options = $.data(jq, "treegrid").options;
            var row2 = $(jq).treegrid("find", id);
            $.extend(row2, row);
            var Level = $(jq).treegrid("getLevel", id) - 1;//获取指定节点等级。
            var style2 = options.rowStyler ? options.rowStyler.call(jq, row2) : "";
            function setFieldsCheck(frozen) { //设置字段选中
                var _e1 = $(jq).treegrid("getColumnFields", frozen);
                var tr = options.finder.getTr(jq, id, "body", (frozen ? 1 : 2));
                var rownumber = tr.find("div.datagrid-cell-rownumber").html();
                var checkb = tr.find("div.datagrid-cell-check input[type=checkbox]").is(":checked");
                tr.html(this.renderRow(jq, _e1, frozen, Level, row2));
                tr.attr("style", style2 || "");
                tr.find("div.datagrid-cell-rownumber").html(rownumber);
                if (checkb) {
                    tr.find("div.datagrid-cell-check input[type=checkbox]")._propAttr("checked", true);//设置选择
                }
            };
            setFieldsCheck.call(this, true);
            setFieldsCheck.call(this, false);
            $(jq).treegrid("fixRowHeight", id);
        },
        //在视图被呈现之前触发
        onBeforeRender: function (jq, nodeId, nodeId) {
            if (!nodeId) {
                return false;
            }
            var options = $.data(jq, "treegrid").options;
            if (nodeId.length == undefined) {
                if (nodeId.footer) {
                    $.data(jq, "treegrid").footer = nodeId.footer;
                }
                if (nodeId.total) {
                    $.data(jq, "treegrid").total = nodeId.total;
                }
                nodeId = this.transfer(jq, nodeId, nodeId.rows);
            } else {
                function setParent(param, nodeId) {
                    for (var i = 0; i < param.length; i++) {
                        var row = param[i];
                        row._parentId = nodeId;
                        if (row.children && row.children.length) {
                            setParent(row.children, row[options.idField]);
                        }
                    }
                };
                setParent(nodeId, nodeId);
            }
            var node = find(jq, nodeId);
            if (node) {
                if (node.children) {
                    node.children = node.children.concat(nodeId);
                } else {
                    node.children = nodeId;
                }
            } else {
                $.data(jq, "treegrid").data = $.data(jq, "treegrid").data.concat(nodeId);
            }
            if (!options.remoteSort) {
                this.sort(jq, nodeId);
            }
            this.treeNodes = nodeId;
            this.treeLevel = $(jq).treegrid("getLevel", nodeId);
        },
        //排序
        sort: function (jq, param) {
            var options = $.data(jq, "treegrid").options;
            var opt = $(jq).treegrid("getColumnOption", options.sortName);
            if (opt) {
                var sorter = opt.sorter || function (rows, b) {
                    return (rows > b ? 1 : -1);
                };
                _sorter(param);
            }
            function _sorter(param) {
                param.sort(function (r1, r2) {
                    return sorter(r1[options.sortName], r2[options.sortName]) * (options.sortOrder == "asc" ? 1 : -1);
                });
                for (var i = 0; i < param.length; i++) {
                    var children = param[i].children;
                    if (children && children.length) {
                        _sorter(children);
                    }
                }
            };
        },

        transfer: function (jq, nodeId, data) {
            var options = $.data(jq, "treegrid").options;
            var rows = [];
            for (var i = 0; i < data.length; i++) {
                rows.push(data[i]);
            }
            var children = [];
            for (var i = 0; i < rows.length; i++) {
                var row = rows[i];
                if (!nodeId) {
                    if (!row._parentId) {
                        children.push(row);
                        transferData(rows, row);
                        i--;
                    }
                } else {
                    if (row._parentId == nodeId) {
                        children.push(row);
                        transferData(rows, row);
                        i--;
                    }
                }
            }
            var toDo = [];
            for (var i = 0; i < children.length; i++) {
                toDo.push(children[i]);
            }
            while (toDo.length) {
                var node = toDo.shift();
                for (var i = 0; i < rows.length; i++) {
                    var row = rows[i];
                    if (row._parentId == node[options.idField]) {
                        if (node.children) {
                            node.children.push(row);
                        } else {
                            node.children = [row];
                        }
                        toDo.push(row);
                        transferData(rows, row);
                        i--;
                    }
                }
            }
            return children;
        }
    });
    //默认属性和事件 继承datagrid
    $.fn.treegrid.defaults = $.extend({}, $.fn.datagrid.defaults, {
        treeField: null,//定义树节点字段。
        animate: false,//定义在节点展开或折叠的时候是否显示动画效果
        singleSelect: true,//单选
        view: _view,//定义数据表格的视图
        //定义以何种方式从远程服务器读取数据。返回false可以忽略该动作。该函数具有一下参数:
        //param:传递到远程服务器的参数对象。
        //success(data):当检索数据成功的时候调用的回调函数。
        //error():当检索数据失败的时候调用的回调函数。
        loader: function (param, success, error) {
            var options = $(this).treegrid("options");
            if (!options.url) {
                return false;
            }
            $.ajax({
                type: options.method,
                url: options.url,
                data: param,
                dataType: "json",
                success: function (data) {
                    success(data);
                }, error: function () {
                    error.apply(this, arguments);
                }
            });
        },
        //返回过滤后的数据进行展示
        loadFilter: function (data, parentId) {
            return data;
        },

        finder: {

            getTr: function (jq, id, type, step) {
                type = type || "body";
                step = step || 0;
                var dc = $.data(jq, "datagrid").dc;
                if (step == 0) {
                    var opts = $.data(jq, "treegrid").options;
                    var tr1 = opts.finder.getTr(jq, id, type, 1);
                    var tr2 = opts.finder.getTr(jq, id, type, 2);
                    return tr1.add(tr2);
                } else {
                    if (type == "body") {
                        var tr = $("#" + $.data(jq, "datagrid").rowIdPrefix + "-" + step + "-" + id);
                        if (!tr.length) {
                            tr = (step == 1 ? dc.body1 : dc.body2).find("tr[node-id=" + id + "]");
                        }
                        return tr;
                    } else {
                        if (type == "footer") {
                            return (step == 1 ? dc.footer1 : dc.footer2).find("tr[node-id=" + id + "]");
                        } else {
                            if (type == "selected") {
                                return (step == 1 ? dc.body1 : dc.body2).find("tr.datagrid-row-selected");
                            } else {
                                if (type == "last") {
                                    return (step == 1 ? dc.body1 : dc.body2).find("tr:last[node-id]");
                                } else {
                                    if (type == "allbody") {
                                        return (step == 1 ? dc.body1 : dc.body2).find("tr[node-id]");
                                    } else {
                                        if (type == "allfooter") {
                                            return (step == 1 ? dc.footer1 : dc.footer2).find("tr[node-id]");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            //获取行
            getRow: function (target, p) {
                var id = (typeof p == "object") ? p.attr("node-id") : p;
                return $(target).treegrid("find", id);
            }
        },
        //在载入请求数据数据之前触发,如果返回false可终止载入数据操作
        onBeforeLoad: function (row, param) {
        },
        //在数据加载成功的时候触发
        onLoadSuccess: function (row, data) {
        },
        //在数据加载成功的时候触发
        onLoadError: function () {
        },
        //在数据加载成功的时候触发
        onBeforeCollapse: function (row) {
        },
        //在节点被折叠的时候触发
        onCollapse: function (row) {
        },
        //在节点展开之前触发,返回false可以取消展开节点的动作
        onBeforeExpand: function (row) {
        },
        //在节点被展开的时候触发
        onExpand: function (row) {
        },
        //在用户点击节点的时候触发
        onClickRow: function (row) {
        },
        //在用户双击节点的时候触发
        onDblClickRow: function (row) {
        },
        //在用户点击一个单元格的时候触发
        onClickCell: function (field, row) {
        },
        //在用户双击一个单元格的时候触发
        onDblClickCell: function (field, row) {
        },
        //在右键点击节点的时候触发。
        onContextMenu: function (e, row) {
        },
        //在用户开始编辑节点的时候触发
        onBeforeEdit: function (row) {
        },
        //在用户完成编辑的时候触发
        onAfterEdit: function (row, changes) {
        },
        //在用户取消编辑节点的时候触发。
        onCancelEdit: function (row) {
        }
    });
})(jQuery);
View Code

 

示例代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Basic TreeGrid - jQuery EasyUI Demo</title>
    <link rel="stylesheet" type="text/css" href="../../themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="../../themes/icon.css">
    <link rel="stylesheet" type="text/css" href="../demo.css">
    <script type="text/javascript" src="../../jquery-1.8.0.min.js"></script>
    <script src="../../plugins2/jquery.parser.js"></script>
    <script src="../../plugins2/jquery.panel.js"></script>
    <script src="../../plugins2/jquery.resizable.js"></script>
    <script src="../../plugins2/jquery.linkbutton.js"></script>
    <script src="../../plugins2/jquery.pagination.js"></script>
    <script src="../../plugins2/jquery.datagrid.js"></script>
    <script src="../../plugins2/jquery.treegrid.js"></script>
</head>
<body>
    <h2>Basic TreeGrid</h2>
    <div class="demo-info">
        <div class="demo-tip icon-tip"></div>
        <div>TreeGrid allows you to expand or collapse group rows.</div>
    </div>
    <div style="margin:10px 0;"></div>
    <table title="Folder Browser" class="easyui-treegrid" style="width:700px;height:250px"
            data-options="
                url: '../treegrid/treegrid_data1.json',
                rownumbers: true,
                idField: 'id',
                treeField: 'name'
            ">
        <thead>
            <tr>
                <th data-options="field:'name'" width="220">Name</th>
                <th data-options="field:'size'" width="100" align="right">Size</th>
                <th data-options="field:'date'" width="150">Modified Date</th>
            </tr>
        </thead>
    </table>

</body>
</html>
View Code

 

插件效果

posted @ 2014-01-01 23:09  Jimmy-Lee  阅读(1707)  评论(2编辑  收藏  举报