前言
使用$.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>