前言
扩展自$.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);
示例代码
<!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="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>