前言
使用$.fn.tree.defaults重写默认值对象。下载该插件翻译源码
树控件在web页面中一个将分层数据以树形结构进行显示。它提供用户展开、折叠、拖拽、编辑和异步加载等功能。
源码
/** * jQuery EasyUI 1.3.2 * *翻译:qq 1364386878 */ (function ($) { //渲染样式 function wrapTree(jq) { var tree = $(jq); tree.addClass("tree"); return tree; }; // 获取树数据 function _getTreeData(jq) { var data = []; collectTreeData(data, $(jq)); //递归获取节点 function collectTreeData(nodes, ul) { ul.children("li").each(function () { var li = $(this); var node = $.extend({}, $.parser.parseOptions(this, ["id", "iconCls", "state"]), { checked: (li.attr("checked") ? true : undefined) }); node.text = li.children("span").html(); if (!node.text) { node.text = li.html(); } var uls = li.children("ul"); if (uls.length) { node.children = []; collectTreeData(node.children, uls);//递归本事 } nodes.push(node); }); }; return data; }; //事件绑定 function bindEvent(jq) { var options = $.data(jq, "tree").options; $(jq).unbind().bind("mouseover", function (e) { //鼠标移上事件 var tt = $(e.target); var nodes = tt.closest("div.tree-node"); if (!nodes.length) { return; } nodes.addClass("tree-node-hover"); if (tt.hasClass("tree-hit")) { if (tt.hasClass("tree-expanded")) { tt.addClass("tree-expanded-hover"); } else { tt.addClass("tree-collapsed-hover"); } } e.stopPropagation(); }).bind("mouseout", function (e) {//鼠标离开事件 var tt = $(e.target); var nodes = tt.closest("div.tree-node"); if (!nodes.length) { return; } nodes.removeClass("tree-node-hover"); if (tt.hasClass("tree-hit")) { if (tt.hasClass("tree-expanded")) { tt.removeClass("tree-expanded-hover"); } else { tt.removeClass("tree-collapsed-hover"); } } e.stopPropagation(); }).bind("click", function (e) {//单击节点事件 var tt = $(e.target); var nodes = tt.closest("div.tree-node"); if (!nodes.length) { return; } if (tt.hasClass("tree-hit")) { _toggle(jq, nodes[0]); return false; } else { if (tt.hasClass("tree-checkbox")) { _check(jq, nodes[0], !tt.hasClass("tree-checkbox1")); return false; } else { select(jq, nodes[0]); options.onClick.call(jq, _getNode(jq, nodes[0])); } } e.stopPropagation(); }).bind("dblclick", function (e) {//双击结点事件 var nodes = $(e.target).closest("div.tree-node"); if (!nodes.length) { return; } select(jq, nodes[0]); options.onDblClick.call(jq, _getNode(jq, nodes[0])); e.stopPropagation(); }).bind("contextmenu", function (e) {//右键菜单 var nodes = $(e.target).closest("div.tree-node"); if (!nodes.length) { return; } options.onContextMenu.call(jq, e, _getNode(jq, nodes[0])); e.stopPropagation(); }); }; //禁用拖放功能 function _disableDnd(jq) { var node = $(jq).find("div.tree-node"); node.draggable("disable"); node.css("cursor", "pointer"); }; //启用拖放功能 function _enableDnd(jq) { var Tree = $.data(jq, "tree"); var options = Tree.options; var tree = Tree.tree; Tree.disabledNodes = []; //拖动功能 设置 tree.find("div.tree-node").draggable({ disabled: false, revert: true, cursor: "pointer", proxy: function (_1d) { var p = $("<div class=\"tree-node-proxy\"></div>").appendTo("body"); p.html("<span class=\"tree-dnd-icon tree-dnd-no\"> </span>" + $(_1d).find(".tree-title").html()); p.hide(); return p; }, deltaX: 15, deltaY: 15, onBeforeDrag: function (e) { if (options.onBeforeDrag.call(jq, _getNode(jq, this)) == false) { return false; } if ($(e.target).hasClass("tree-hit") || $(e.target).hasClass("tree-checkbox")) { return false; } if (e.which != 1) { return false; } $(this).next("ul").find("div.tree-node").droppable({ accept: "no-accept" }); var indent = $(this).find("span.tree-indent"); if (indent.length) { e.data.offsetWidth -= indent.length * indent.width(); } }, onStartDrag: function () { $(this).draggable("proxy").css({ left: -10000, top: -10000 }); options.onStartDrag.call(jq, _getNode(jq, this)); var node = _getNode(jq, this); if (node.id == undefined) { node.id = "easyui_tree_node_id_temp"; _update(jq, node); } Tree.draggingNodeId = node.id; }, onDrag: function (e) { var x1 = e.pageX, y1 = e.pageY, x2 = e.data.startX, y2 = e.data.startY; var d = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); if (d > 3) { $(this).draggable("proxy").show(); } this.pageY = e.pageY; }, onStopDrag: function () { $(this).next("ul").find("div.tree-node").droppable({ accept: "div.tree-node" }); for (var i = 0; i < Tree.disabledNodes.length; i++) { $(Tree.disabledNodes[i]).droppable("enable"); } Tree.disabledNodes = []; var _20 = _find(jq, Tree.draggingNodeId); if (_20.id == "easyui_tree_node_id_temp") { _20.id = ""; _update(jq, _20); } options.onStopDrag.call(jq, _20); } }).droppable({//拉伸插件设置 accept: "div.tree-node", onDragEnter: function (e, source) { if (options.onDragEnter.call(jq, this, _getNode(jq, source)) == false) { setdndClass(source, false); $(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); $(this).droppable("disable"); Tree.disabledNodes.push(this); } }, onDragOver: function (e, source) { if ($(this).droppable("options").disabled) { return; } var pageY = source.pageY; var top = $(this).offset().top; var height = top + $(this).outerHeight(); setdndClass(source, true); $(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); if (pageY > top + (height - top) / 2) { if (height - pageY < 5) { $(this).addClass("tree-node-bottom"); } else { $(this).addClass("tree-node-append"); } } else { if (pageY - top < 5) { $(this).addClass("tree-node-top"); } else { $(this).addClass("tree-node-append"); } } if (options.onDragOver.call(jq, this, _getNode(jq, source)) == false) { setdndClass(source, false); $(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); $(this).droppable("disable"); Tree.disabledNodes.push(this); } }, onDragLeave: function (e, source) { setdndClass(source, false); $(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); options.onDragLeave.call(jq, this, _getNode(jq, source)); }, onDrop: function (e, source) { var target = this; var action, point; if ($(this).hasClass("tree-node-append")) { action = moveNode; } else { action = insertNode; point = $(this).hasClass("tree-node-top") ? "top" : "bottom"; } action(source, target, point); $(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); } }); //设置拖动样式 function setdndClass(source, dnd) { var dndicon = $(source).draggable("proxy").find("span.tree-dnd-icon"); dndicon.removeClass("tree-dnd-yes tree-dnd-no").addClass(dnd ? "tree-dnd-yes" : "tree-dnd-no"); }; function moveNode(nodeEl, parent) { if (_getNode(jq, parent).state == "closed") { expand(jq, parent, function () { doMoveNode(); }); } else { doMoveNode(); } function doMoveNode() { var nodeData = $(jq).tree("pop", nodeEl); $(jq).tree("append", { parent: parent, data: [nodeData] }); options.onDrop.call(jq, parent, nodeData, "append"); }; }; function insertNode(nodeEl, parent, point) { var param = {}; if (point == "top") { param.before = parent; } else { param.after = parent; } var nodeData = $(jq).tree("pop", nodeEl); param.data = nodeData; $(jq).tree("insert", param); options.onDrop.call(jq, parent, nodeData, point); }; }; //将节点设置为勾选或不勾选 function _check(jq, target, isCheck) { var options = $.data(jq, "tree").options; if (!options.checkbox) { return; } var node2 = _getNode(jq, target); if (options.onBeforeCheck.call(jq, node2, isCheck) == false) { return; } var node = $(target); var ck = node.find(".tree-checkbox"); ck.removeClass("tree-checkbox0 tree-checkbox1 tree-checkbox2");//清空样式 if (isCheck) { ck.addClass("tree-checkbox1");//勾选样式 } else { ck.addClass("tree-checkbox0");//不勾选样式 } //设置级联选中 if (options.cascadeCheck) { setParentsChecked(node); setChildrenChecked(node); } options.onCheck.call(jq, node2, isCheck); //勾选子结点 function setChildrenChecked(node) { var ck = node.next().find(".tree-checkbox"); ck.removeClass("tree-checkbox0 tree-checkbox1 tree-checkbox2"); if (node.find(".tree-checkbox").hasClass("tree-checkbox1")) { ck.addClass("tree-checkbox1");//勾选样式(非级联) } else { ck.addClass("tree-checkbox0");//不勾选样式 } }; //级联勾选父结点 function setParentsChecked(node) { var parentNode = _getParent(jq, node[0]); if (parentNode) { var ck = $(parentNode.target).find(".tree-checkbox"); ck.removeClass("tree-checkbox0 tree-checkbox1 tree-checkbox2"); if (isAllSelected(node)) { ck.addClass("tree-checkbox1"); } else { if (isAllNull(node)) { ck.addClass("tree-checkbox0"); } else { ck.addClass("tree-checkbox2"); } } setParentsChecked($(parentNode.target)); } //是否全选(非级联勾选) function isAllSelected(node) { var ck = node.find(".tree-checkbox"); //判断当前勾选框的样式状态 if (ck.hasClass("tree-checkbox0") || ck.hasClass("tree-checkbox2")) { return false; } var b = true; node.parent().siblings().each(function () { if (!$(this).children("div.tree-node").children(".tree-checkbox").hasClass("tree-checkbox1")) { b = false; } }); return b; }; //是否全未勾选 function isAllNull(node) { var ck = node.find(".tree-checkbox"); if (ck.hasClass("tree-checkbox1") || ck.hasClass("tree-checkbox2")) { return false; } var b = true; node.parent().siblings().each(function () { if (!$(this).children("div.tree-node").children(".tree-checkbox").hasClass("tree-checkbox0")) { b = false; } }); return b; }; }; }; // 设置勾选框的值 function setCheckBoxValue(jq, target) { var options = $.data(jq, "tree").options; var node = $(target); if (_isLeaf(jq, target)) {//叶子结点 var ck = node.find(".tree-checkbox"); if (ck.length) { if (ck.hasClass("tree-checkbox1")) { _check(jq, target, true); } else { _check(jq, target, false); } } else { if (options.onlyLeafCheck) {////只显示叶子节点前的复选框 $("<span class=\"tree-checkbox tree-checkbox0\"></span>").insertBefore(node.find(".tree-title")); } } } else {////非叶子结点 var ck = node.find(".tree-checkbox"); if (options.onlyLeafCheck) { ck.remove(); } else { if (ck.hasClass("tree-checkbox1")) { _check(jq, target, true); } else { if (ck.hasClass("tree-checkbox2")) { var checked = true; var unchecked = true; var children = _getChildren(jq, target); for (var i = 0; i < children.length; i++) { if (children[i].checked) { unchecked = false; } else { checked = false; } } if (checked) { _check(jq, target, true); } if (unchecked) { _check(jq, target, false); } } } } } }; //加载树数据 function _loadData(jq, ul, data, isAppend) { var options = $.data(jq, "tree").options; data = options.loadFilter.call(jq, data, $(ul).prev("div.tree-node")[0]); if (!isAppend) { $(ul).empty(); } var checkedNodes = []; var depth = $(ul).prev("div.tree-node").find("span.tree-indent, span.tree-hit").length; appendNodes(ul, data, depth); if (options.dnd) { _enableDnd(jq); } else { _disableDnd(jq); } for (var i = 0; i < checkedNodes.length; i++) { _check(jq, checkedNodes[i], true); } setTimeout(function () { _61(jq, jq); }, 0); var node = null; if (jq != ul) { var _5b = $(ul).prev(); node = _getNode(jq, _5b[0]); } options.onLoadSuccess.call(jq, node, data); function appendNodes(ul, children, depth) { for (var i = 0; i < children.length; i++) { var li = $("<li></li>").appendTo(ul); var item = children[i]; if (item.state != "open" && item.state != "closed") { item.state = "open"; } var node = $("<div class=\"tree-node\"></div>").appendTo(li); node.attr("node-id", item.id); $.data(node[0], "tree-node", { id: item.id, text: item.text, iconCls: item.iconCls, attributes: item.attributes }); $("<span class=\"tree-title\"></span>").html(item.text).appendTo(node); if (options.checkbox) { if (options.onlyLeafCheck) { if (item.state == "open" && (!item.children || !item.children.length)) { if (item.checked) { $("<span class=\"tree-checkbox tree-checkbox1\"></span>").prependTo(node); } else { $("<span class=\"tree-checkbox tree-checkbox0\"></span>").prependTo(node); } } } else { if (item.checked) { $("<span class=\"tree-checkbox tree-checkbox1\"></span>").prependTo(node); checkedNodes.push(node[0]); } else { $("<span class=\"tree-checkbox tree-checkbox0\"></span>").prependTo(node); } } } if (item.children && item.children.length) { var subul = $("<ul></ul>").appendTo(li); if (item.state == "open") { $("<span class=\"tree-icon tree-folder tree-folder-open\"></span>").addClass(item.iconCls).prependTo(node); $("<span class=\"tree-hit tree-expanded\"></span>").prependTo(node); } else { $("<span class=\"tree-icon tree-folder\"></span>").addClass(item.iconCls).prependTo(node); $("<span class=\"tree-hit tree-collapsed\"></span>").prependTo(node); subul.css("display", "none"); } appendNodes(subul, item.children, depth + 1); } else { if (item.state == "closed") { $("<span class=\"tree-icon tree-folder\"></span>").addClass(item.iconCls).prependTo(node); $("<span class=\"tree-hit tree-collapsed\"></span>").prependTo(node); } else { $("<span class=\"tree-icon tree-file\"></span>").addClass(item.iconCls).prependTo(node); $("<span class=\"tree-indent\"></span>").prependTo(node); } } for (var j = 0; j < depth; j++) { $("<span class=\"tree-indent\"></span>").prependTo(node); } } }; }; function _61(jq, ul, _63) { var options = $.data(jq, "tree").options; if (!options.lines) { return; } if (!_63) { _63 = true; $(jq).find("span.tree-indent").removeClass("tree-line tree-join tree-joinbottom"); $(jq).find("div.tree-node").removeClass("tree-node-last tree-root-first tree-root-one"); var _65 = $(jq).tree("getRoots"); if (_65.length > 1) { $(_65[0].target).addClass("tree-root-first"); } else { if (_65.length == 1) { $(_65[0].target).addClass("tree-root-one"); } } } $(ul).children("li").each(function () { var _66 = $(this).children("div.tree-node"); var ul = _66.next("ul"); if (ul.length) { if ($(this).next().length) { _67(_66); } _61(jq, ul, _63); } else { _68(_66); } }); var _69 = $(ul).children("li:last").children("div.tree-node").addClass("tree-node-last"); _69.children("span.tree-join").removeClass("tree-join").addClass("tree-joinbottom"); function _68(_6a, _6b) { var _6c = _6a.find("span.tree-icon"); _6c.prev("span.tree-indent").addClass("tree-join"); }; function _67(_6d) { var _6e = _6d.find("span.tree-indent, span.tree-hit").length; _6d.next().find("div.tree-node").each(function () { $(this).children("span:eq(" + (_6e - 1) + ")").addClass("tree-line"); }); }; }; function request(_70, ul, _71, _72) { var _73 = $.data(_70, "tree").options; _71 = _71 || {}; var _74 = null; if (_70 != ul) { var _75 = $(ul).prev(); _74 = _getNode(_70, _75[0]); } if (_73.onBeforeLoad.call(_70, _74, _71) == false) { return; } var _76 = $(ul).prev().children("span.tree-folder"); _76.addClass("tree-loading"); var _77 = _73.loader.call(_70, _71, function (_78) { _76.removeClass("tree-loading"); _loadData(_70, ul, _78); if (_72) { _72(); } }, function () { _76.removeClass("tree-loading"); _73.onLoadError.apply(_70, arguments); if (_72) { _72(); } }); if (_77 == false) { _76.removeClass("tree-loading"); } }; function expand(_7a, _7b, _7c) { var _7d = $.data(_7a, "tree").options; var hit = $(_7b).children("span.tree-hit"); if (hit.length == 0) { return; } if (hit.hasClass("tree-expanded")) { return; } var _7e = _getNode(_7a, _7b); if (_7d.onBeforeExpand.call(_7a, _7e) == false) { return; } hit.removeClass("tree-collapsed tree-collapsed-hover").addClass("tree-expanded"); hit.next().addClass("tree-folder-open"); var ul = $(_7b).next(); if (ul.length) { if (_7d.animate) { ul.slideDown("normal", function () { _7d.onExpand.call(_7a, _7e); if (_7c) { _7c(); } }); } else { ul.css("display", "block"); _7d.onExpand.call(_7a, _7e); if (_7c) { _7c(); } } } else { var _7f = $("<ul style=\"display:none\"></ul>").insertAfter(_7b); request(_7a, _7f[0], { id: _7e.id }, function () { if (_7f.is(":empty")) { _7f.remove(); } if (_7d.animate) { _7f.slideDown("normal", function () { _7d.onExpand.call(_7a, _7e); if (_7c) { _7c(); } }); } else { _7f.css("display", "block"); _7d.onExpand.call(_7a, _7e); if (_7c) { _7c(); } } }); } }; function _collapse(_81, _82) { var _83 = $.data(_81, "tree").options; var hit = $(_82).children("span.tree-hit"); if (hit.length == 0) { return; } if (hit.hasClass("tree-collapsed")) { return; } var _84 = _getNode(_81, _82); if (_83.onBeforeCollapse.call(_81, _84) == false) { return; } hit.removeClass("tree-expanded tree-expanded-hover").addClass("tree-collapsed"); hit.next().removeClass("tree-folder-open"); var ul = $(_82).next(); if (_83.animate) { ul.slideUp("normal", function () { _83.onCollapse.call(_81, _84); }); } else { ul.css("display", "none"); _83.onCollapse.call(_81, _84); } }; function _toggle(_86, _87) { var hit = $(_87).children("span.tree-hit"); if (hit.length == 0) { return; } if (hit.hasClass("tree-expanded")) { _collapse(_86, _87); } else { expand(_86, _87); } }; function _expandAll(_89, _8a) { var _8b = _getChildren(_89, _8a); if (_8a) { _8b.unshift(_getNode(_89, _8a)); } for (var i = 0; i < _8b.length; i++) { expand(_89, _8b[i].target); } }; function _expandTo(_8d, _8e) { var _8f = []; var p = _getParent(_8d, _8e); while (p) { _8f.unshift(p); p = _getParent(_8d, p.target); } for (var i = 0; i < _8f.length; i++) { expand(_8d, _8f[i].target); } }; function _collapseAll(_92, _93) { var _94 = _getChildren(_92, _93); if (_93) { _94.unshift(_getNode(_92, _93)); } for (var i = 0; i < _94.length; i++) { _collapse(_92, _94[i].target); } }; // 获取根结点 function _getRoot(jq) { var rootNodes = _getRoots(jq); if (rootNodes.length) { return rootNodes[0]; } else { return null; } }; // 获取所有根结点 function _getRoots(jq) { var roots = []; $(jq).children("li").each(function () { var nodes = $(this).children("div.tree-node"); roots.push(_getNode(jq, nodes[0])); }); return roots; }; //获取所有子结点 function _getChildren(jq, target) { var ndoes = []; if (target) { findChildren($(target)); } else { var rootNodes = _getRoots(jq); for (var i = 0; i < rootNodes.length; i++) { ndoes.push(rootNodes[i]); findChildren($(rootNodes[i].target)); } } function findChildren(target) { target.next().find("div.tree-node").each(function () { ndoes.push(_getNode(jq, this)); }); }; return ndoes; }; //获取父结点 function _getParent(jq, target) { var ul = $(target).parent().parent(); if (ul[0] == jq) { return null; } else { return _getNode(jq, ul.prev()[0]); } }; //获取所有被勾选的结点 function _getChecked(jq, state) { state = state || "checked"; var stateClass = ""; if (state == "checked") { stateClass = "span.tree-checkbox1"; } else { if (state == "unchecked") { stateClass = "span.tree-checkbox0"; } else { if (state == "indeterminate") { stateClass = "span.tree-checkbox2"; } } } var node = []; $(jq).find(stateClass).each(function () { var _a9 = $(this).parent(); node.push(_getNode(jq, _a9[0])); }); return node; }; //获取被选中的结点 function _getSelected(jq) { var nodes = $(jq).find("div.tree-node-selected"); if (nodes.length) { return _getNode(jq, nodes[0]); } else { return null; } }; //追加若干子节点到一个父节点 function _append(jq, param) { var parent = $(param.parent); var ul; if (parent.length == 0) { ul = $(jq); } else { ul = parent.next(); if (ul.length == 0) { ul = $("<ul></ul>").insertAfter(parent); } } if (param.data && param.data.length) { var icon = parent.find("span.tree-icon"); if (icon.hasClass("tree-file")) { icon.removeClass("tree-file").addClass("tree-folder tree-folder-open"); var hit = $("<span class=\"tree-hit tree-expanded\"></span>").insertBefore(icon); if (hit.prev().length) { hit.prev().remove(); } } } _loadData(jq, ul[0], param.data, true); setCheckBoxValue(jq, ul.prev()); }; //在一个指定节点之前或之后插入节点 function _insert(jq, target) { var ref = target.before || target.after; var parentNode = _getParent(jq, ref); var li; if (parentNode) { _append(jq, { parent: parentNode.target, data: [target.data] }); li = $(parentNode.target).next().children("li:last"); } else { _append(jq, { parent: null, data: [target.data] }); li = $(jq).children("li:last"); } if (target.before) { li.insertBefore($(ref).parent()); } else { li.insertAfter($(ref).parent()); } }; //删除一个节点和它的子节点 function _remove(jq, target) { var parentNode = _getParent(jq, target); var node = $(target); var li = node.parent(); var ul = li.parent(); li.remove(); if (ul.children("li").length == 0) { var node = ul.prev(); node.find(".tree-icon").removeClass("tree-folder").addClass("tree-file"); node.find(".tree-hit").remove(); $("<span class=\"tree-indent\"></span>").prependTo(node); if (ul[0] != jq) { ul.remove(); } } if (parentNode) { setCheckBoxValue(jq, parentNode.target); } _61(jq, jq); }; //递归获取某结点数据(包括子结点) function _getData(jq, target) { // 获取下一结点的子结点 function getChildrenOfNextNode(node, ul) { ul.children("li").each(function () { var nodes = $(this).children("div.tree-node"); var node = _getNode(jq, nodes[0]); var sub = $(this).children("ul"); if (sub.length) { node.children = []; getChildrenOfNextNode(node.children, sub); } node.push(node); }); }; if (target) { var node = _getNode(jq, target); node.children = []; getChildrenOfNextNode(node.children, $(target).next()); return node; } else { return null; } }; //更新指定的节点 function _update(jq, param) { var target = $(param.target); var node = _getNode(jq, param.target); if (node.iconCls) { target.find(".tree-icon").removeClass(node.iconCls); } var options = $.extend({}, node, param); $.data(param.target, "tree-node", options); target.attr("node-id", options.id); target.find(".tree-title").html(options.text); if (options.iconCls) { target.find(".tree-icon").addClass(options.iconCls); } if (node.checked != options.checked) { _check(jq, param.target, options.checked); } }; //获取结点 function _getNode(jq, target) { var node = $.extend({}, $.data(target, "tree-node"), { target: target, checked: $(target).find(".tree-checkbox").hasClass("tree-checkbox1") }); if (!_isLeaf(jq, target)) { node.state = $(target).find(".tree-hit").hasClass("tree-expanded") ? "open" : "closed"; } return node; }; //根据ID查找结点 function _find(jq, id) { // var nodes = $(jq).find("div.tree-node[node-id=" + id + "]"); if (nodes.length) { return _getNode(jq, nodes[0]); } else { return null; } }; // 选择结点 function select(jq, target) { var options = $.data(jq, "tree").options; var node = _getNode(jq, target); if (options.onBeforeSelect.call(jq, node) == false) { return; } $("div.tree-node-selected", jq).removeClass("tree-node-selected"); $(target).addClass("tree-node-selected"); options.onSelect.call(jq, node); }; //是否叶子结点 function _isLeaf(jq, target) { var node = $(target); var hit = node.children("span.tree-hit"); return hit.length == 0; }; //开始编辑结点 function _beginEdit(jq, target) { var options = $.data(jq, "tree").options; var node = _getNode(jq, target); if (options.onBeforeEdit.call(jq, node) == false) { return; } $(target).css("position", "relative"); var nt = $(target).find(".tree-title"); var outerWidth = nt.outerWidth(); nt.empty(); var editor = $("<input class=\"tree-editor\">").appendTo(nt);//编辑器 editor.val(node.text).focus(); editor.width(outerWidth + 20); editor.height(document.compatMode == "CSS1Compat" ? (18 - (editor.outerHeight() - editor.height())) : 18); //设置编辑器事件 editor.bind("click", function (e) { return false; }).bind("mousedown", function (e) { e.stopPropagation(); }).bind("mousemove", function (e) { e.stopPropagation(); }).bind("keydown", function (e) { if (e.keyCode == 13) { _endEdit(jq, target); return false; } else { if (e.keyCode == 27) { _cancelEdit(jq, target); return false; } } }).bind("blur", function (e) { e.stopPropagation(); _endEdit(jq, target); }); }; //结束编辑 function _endEdit(jq, target) { var options = $.data(jq, "tree").options; $(target).css("position", ""); var editor = $(target).find("input.tree-editor"); var val = editor.val(); editor.remove(); var node = _getNode(jq, target); node.text = val; _update(jq, node); options.onAfterEdit.call(jq, node); }; // 取消编辑 function _cancelEdit(jq, target) { var options = $.data(jq, "tree").options; $(target).css("position", ""); $(target).find("input.tree-editor").remove(); var node = _getNode(jq, target); _update(jq, node); options.onCancelEdit.call(jq, node); }; //实例化树 $.fn.tree = function (options, param) { if (typeof options == "string") { return $.fn.tree.methods[options](this, param); } var options = options || {}; return this.each(function () { var data = $.data(this, "tree"); var options; if (data) { options = $.extend(data.options, options); data.options = options; } else { options = $.extend({}, $.fn.tree.defaults, $.fn.tree.parseOptions(this), options); $.data(this, "tree", { options: options, tree: wrapTree(this) }); var jsonData = _getTreeData(this); if (jsonData.length && !options.data) { options.data = jsonData; } } bindEvent(this); if (options.lines) { $(this).addClass("tree-lines"); } if (options.data) { _loadData(this, this, options.data); } else { if (options.dnd) { _enableDnd(this); } else { _disableDnd(this); } } request(this, this); }); }; //树 方法 $.fn.tree.methods = { //返回树控件属性 options: function (jq) { return $.data(jq[0], "tree").options; }, //读取树控件数据 loadData: function (jq, data) { return jq.each(function () { _loadData(this, this, data); }); }, //获取指定节点对象 getNode: function (jq, target) { return _getNode(jq[0], target); }, //获取指定节点数据,包含它的子节点 getData: function (jq, target) { return _getData(jq[0], target); }, //重新载入树控件数据 reload: function (jq, target) { return jq.each(function () { if (target) { var node = $(target); var hit = node.children("span.tree-hit");//获取结点前的展开/折叠对象 hit.removeClass("tree-expanded tree-expanded-hover").addClass("tree-collapsed"); node.next().remove();//删除子结点 expand(this, target);//调用展开方法,重新加载树 } else { $(this).empty(); request(this, this); } }); }, //获取根节点,返回节点对象 getRoot: function (jq) { return _getRoot(jq[0]); }, //获取所有根节点,返回节点数组 getRoots: function (jq) { return _getRoots(jq[0]); }, //获取父节点,'target'参数代表节点的DOM对象 getParent: function (jq, target) { return _getParent(jq[0], target); }, //获取所有子节点,'target'参数代表节点的DOM对象 getChildren: function (jq, target) { return _getChildren(jq[0], target); }, //获取所有选中的节点。'state'可用值有:'checked','unchecked','indeterminate'。如果'state'未指定,将返回'checked'节点 getChecked: function (jq, state) { return _getChecked(jq[0], state); }, //获取选择节点并返回它,如果未选择则返回null getSelected: function (jq) { return _getSelected(jq[0]); }, //判断指定的节点是否是叶子节点,target参数是一个节点DOM对象 isLeaf: function (jq, target) { return _isLeaf(jq[0], target); }, //查找指定节点并返回节点对象 find: function (jq, id) { return _find(jq[0], id); }, //选择一个节点,'target'参数表示节点的DOM对象 select: function (jq, target) { return jq.each(function () { select(this, target); }); }, //选中指定节点 check: function (jq, target) { return jq.each(function () { _check(this, target, true); }); }, //取消选中指定节点 uncheck: function (jq, target) { return jq.each(function () { _check(this, target, false); }); }, //折叠一个节点,'target'参数表示节点的DOM对象 collapse: function (jq, target) { return jq.each(function () { _collapse(this, target); }); }, //展开一个节点,'target'参数表示节点的DOM对象。在节点关闭或没有子节点的时候,节点ID的值(名为'id'的参数)将会发送给服务器 请求子节点的数据。 expand: function (jq, target) { return jq.each(function () { expand(this, target); }); }, //折叠所有节点 collapseAll: function (jq, target) { return jq.each(function () { _collapseAll(this, target); }); }, //展开所有节点 expandAll: function (jq, target) { return jq.each(function () { _expandAll(this, target); }); }, //打开从根节点到指定节点之间的所有节点 expandTo: function (jq, target) { return jq.each(function () { _expandTo(this, target); }); }, //打开或关闭节点的触发器,target参数是一个节点DOM对象 toggle: function (jq, target) { return jq.each(function () { _toggle(this, target); }); }, //追加若干子节点到一个父节点,param参数有2个属性 append: function (jq, param) { return jq.each(function () { _append(this, param); }); }, //在一个指定节点之前或之后插入节点,'param'参数包含如下属性: //before:DOM对象,在某个节点之前插入。 //after:DOM对象,在某个节点之后插入。 //data:对象,节点数据 insert: function (jq, param) { return jq.each(function () { _insert(this, param); }); }, //移除一个节点和它的子节点,'target'参数是该节点的DOM对象 remove: function (jq, target) { return jq.each(function () { _remove(this, target); }); }, //移除一个节点和它的子节点,该方法跟remove方法一样,不同的是它将返回被移除的节点数据 pop: function (jq, target) { var node = jq.tree("getData", target); jq.tree("remove", target); return node; }, //更新指定节点。'param'参数包含以下属性: //target(DOM对象,将被更新的目标节点),id,text,iconCls,checked等 update: function (jq, target) { return jq.each(function () { _update(this, target); }); }, //启用拖拽功能 enableDnd: function (jq) { return jq.each(function () { _enableDnd(this); }); }, //禁用拖拽功能 disableDnd: function (jq) { return jq.each(function () { _disableDnd(this); }); }, //开始编辑一个节点 beginEdit: function (jq, target) { return jq.each(function () { _beginEdit(this, target); }); }, //结束编辑一个节点 endEdit: function (jq, target) { return jq.each(function () { _endEdit(this, target); }); }, //取消编辑一个节点 cancelEdit: function (jq, target) { return jq.each(function () { _cancelEdit(this, target); }); } }; //解析器 $.fn.tree.parseOptions = function (target) { var t = $(target); return $.extend({}, $.parser.parseOptions(target, ["url", "method", { checkbox: "boolean", cascadeCheck: "boolean", onlyLeafCheck: "boolean" }, { animate: "boolean", lines: "boolean", dnd: "boolean" }])); }; //树-默认属性+事件 $.fn.tree.defaults = { url: null,//检索远程数据的URL地址 method: "post",//检索数据的HTTP方法。(POST / GET) animate: false,//定义节点在展开或折叠的时候是否显示动画效果 checkbox: false,//定义是否在每一个借点之前都显示复选框 cascadeCheck: true,//定义是否层叠选中状态 onlyLeafCheck: false,//定义是否只在末级节点之前显示复选框 lines: false,//定义是否显示树控件上的虚线 dnd: false,//定义是否启用拖拽功能 data: null,//节点数据加载 //定义如何从远程服务器加载数据。返回false可以忽略本操作 loader: function (param, _success, _error) { var opts = $(this).tree("options"); if (!opts.url) { return false; } $.ajax({ type: opts.method, url: opts.url, data: param, dataType: "json", success: function (data) { _success(data); }, error: function () { _error.apply(this, arguments); } }); }, //返回过滤过的数据进行展示。返回数据是标准树格式 loadFilter: function (data, parent) { return data; }, //事件-- //在请求加载远程数据之前触发,返回false可以取消加载操作 onBeforeLoad: function (node, param) { }, //在数据加载成功以后触发 onLoadSuccess: function (node, data) { }, //在数据加载失败的时候触发,arguments参数和jQuery的$.ajax()函数里面的'error'回调函数的参数相同 onLoadError: function () { }, //在用户点击一个节点的时候触发 onClick: function (node) { }, //在用户双击一个节点的时候触发 onDblClick: function (node) { }, //在节点展开之前触发,返回false可以取消展开操作 onBeforeExpand: function (node) { }, //在节点展开的时候触发 onExpand: function (node) { }, //在节点折叠之前触发,返回false可以取消折叠操作 onBeforeCollapse: function (node) { }, //在节点折叠的时候触发 onCollapse: function (node) { }, //在用户点击勾选复选框之前触发,返回false可以取消选择动作 onBeforeCheck: function (node, checked) { }, //在用户点击勾选复选框的时候触发 onCheck: function (node, checked) { }, //在用户选择一个节点之前触发,返回false可以取消选择动作 onBeforeSelect: function (node) { }, //在用户选择节点的时候触发 onSelect: function (node) { }, //在右键点击节点的时候触发 onContextMenu: function (e, node) { }, //在开始拖动节点之前触发,返回false可以拒绝拖动 onBeforeDrag: function (node) { }, //在开始拖动节点的时候触发 onStartDrag: function (node) { }, //在停止拖动节点的时候触发 onStopDrag: function (node) { }, //在拖动一个节点进入到某个目标节点并释放的时候触发,返回false可以拒绝拖动 onDragEnter: function (target, source) { }, //在拖动一个节点经过某个目标节点并释放的时候触发,返回false可以拒绝拖动 onDragOver: function (target, source) { }, //在拖动一个节点离开某个目标节点并释放的时候触发,返回false可以拒绝拖动 onDragLeave: function (target, source) { }, //当节点位置被拖动时触发 onDrop: function (target, source, point) { }, //在编辑节点之前触发 onBeforeEdit: function (node) { }, //在编辑节点之后触发 onAfterEdit: function (node) { }, //在取消编辑操作的时候触发 onCancelEdit: function (node) { } }; })(jQuery);
示例代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Basic Tree - 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.draggable.js"></script> <script src="../../plugins2/jquery.droppable.js"></script> <script src="../../plugins2/jquery.tree.js"></script> </head> <body> <h2>Basic Tree</h2> <div class="demo-info"> <div class="demo-tip icon-tip"></div> <div>Click the arrow on the left to expand or collapse nodes.</div> </div> <div style="margin:10px 0;"></div> <ul class="easyui-tree"> <li> <span>My Documents</span> <ul> <li data-options="state:'closed'"> <span>Photos</span> <ul> <li> <span>Friend</span> </li> <li> <span>Wife</span> </li> <li> <span>Company</span> </li> </ul> </li> <li> <span>Program Files</span> <ul> <li>Intel</li> <li>Java</li> <li>Microsoft Office</li> <li>Games</li> </ul> </li> <li>index.html</li> <li>about.html</li> <li>welcome.html</li> </ul> </li> </ul> </body> </html>