/** * jQuery ligerUI 1.1.9 * * http://ligerui.com * * Author daomi 2012 [ gd_star@163.com ] * */ (function ($) { $.fn.ligerTree = function (options) { return $.ligerui.run.call(this, "ligerTree", arguments); }; $.fn.ligerGetTreeManager = function () { return $.ligerui.run.call(this, "ligerGetTreeManager", arguments); }; $.ligerDefaults.Tree = { url: null, data: null, checkbox: true, autoCheckboxEven: true, parentIcon: 'folder', childIcon: 'leaf', textFieldName: 'text', attribute: ['id', 'url'], treeLine: true, //是否显示line nodeWidth: 90, statusName: '__status', isLeaf: null, //是否子节点的判断函数 single: false, //是否单选 onBeforeExpand: function () { }, onContextmenu: function () { }, onExpand: function () { }, onBeforeCollapse: function () { }, onCollapse: function () { }, onBeforeSelect: function () { }, onSelect: function () { }, onBeforeCancelSelect: function () { }, onCancelselect: function () { }, onCheck: function () { }, onSuccess: function () { }, onError: function () { }, onClick: function () { }, idFieldName: 'id', parentIDFieldName: null, topParentIDValue: 0, onBeforeAppend: function () { }, //加载数据前事件,可以通过return false取消操作 onAppend: function () { }, //加载数据时事件,对数据进行预处理以后 onAfterAppend: function () { }, //加载数据完事件 slide: true, //是否以动画的形式显示 iconFieldName: 'icon', nodeDraggable: false, //是否允许拖拽 nodeDraggingRender: null, btnClickToToggleOnly: true //是否点击展开/收缩 按钮时才有效 }; $.ligerui.controls.Tree = function (element, options) { $.ligerui.controls.Tree.base.constructor.call(this, element, options); }; $.ligerui.controls.Tree.ligerExtend($.ligerui.core.UIComponent, { _init: function () { $.ligerui.controls.Tree.base._init.call(this); var g = this, p = this.options; if (p.single) p.autoCheckboxEven = false; }, _render: function () { var g = this, p = this.options; g.set(p, true); g.tree = $(g.element); g.tree.addClass('l-tree'); g.sysAttribute = ['isexpand', 'ischecked', 'href', 'style']; g.loading = $("
"); g.tree.after(g.loading); g.data = []; g.maxOutlineLevel = 1; g.treedataindex = 0; g._applyTree(); g._setTreeEven(); g.set(p, false); }, _setTreeLine: function (value) { if (value) this.tree.removeClass("l-tree-noline"); else this.tree.addClass("l-tree-noline"); }, _setUrl: function (url) { if (url) this.loadData(null, url); }, _setData: function (data) { if (data) this.append(null, data); }, setData: function (data) { this.set('data', data); }, getData: function () { return this.data; }, //是否包含子节点 hasChildren: function (treenodedata) { if (this.options.isLeaf) return this.options.isLeaf(treenodedata); return treenodedata.children ? true : false; }, //获取父节点 数据 getParent: function (treenode, level) { var g = this; treenode = g.getNodeDom(treenode); var parentTreeNode = g.getParentTreeItem(treenode, level); if (!parentTreeNode) return null; var parentIndex = $(parentTreeNode).attr("treedataindex"); return g._getDataNodeByTreeDataIndex(parentIndex); }, //获取父节点 getParentTreeItem: function (treenode, level) { var g = this; treenode = g.getNodeDom(treenode); var treeitem = $(treenode); if (treeitem.parent().hasClass("l-tree")) return null; if (level == undefined) { if (treeitem.parent().parent("li").length == 0) return null; return treeitem.parent().parent("li")[0]; } var currentLevel = parseInt(treeitem.attr("outlinelevel")); var currenttreeitem = treeitem; for (var i = currentLevel - 1; i >= level; i--) { currenttreeitem = currenttreeitem.parent().parent("li"); } return currenttreeitem[0]; }, getChecked: function () { var g = this, p = this.options; if (!this.options.checkbox) return null; var nodes = []; $(".l-checkbox-checked", g.tree).parent().parent("li").each(function () { var treedataindex = parseInt($(this).attr("treedataindex")); nodes.push({ target: this, data: g._getDataNodeByTreeDataIndex(g.data, treedataindex) }); }); return nodes; }, getSelected: function () { var g = this, p = this.options; var node = {}; node.target = $(".l-selected", g.tree).parent("li")[0]; if (node.target) { var treedataindex = parseInt($(node.target).attr("treedataindex")); node.data = g._getDataNodeByTreeDataIndex(g.data, treedataindex); return node; } return null; }, //升级为父节点级别 upgrade: function (treeNode) { var g = this, p = this.options; $(".l-note", treeNode).each(function () { $(this).removeClass("l-note").addClass("l-expandable-open"); }); $(".l-note-last", treeNode).each(function () { $(this).removeClass("l-note-last").addClass("l-expandable-open"); }); $("." + g._getChildNodeClassName(), treeNode).each(function () { $(this) .removeClass(g._getChildNodeClassName()) .addClass(g._getParentNodeClassName(true)); }); }, //降级为叶节点级别 demotion: function (treeNode) { var g = this, p = this.options; if (!treeNode && treeNode[0].tagName.toLowerCase() != 'li') return; var islast = $(treeNode).hasClass("l-last"); $(".l-expandable-open", treeNode).each(function () { $(this).removeClass("l-expandable-open") .addClass(islast ? "l-note-last" : "l-note"); }); $(".l-expandable-close", treeNode).each(function () { $(this).removeClass("l-expandable-close") .addClass(islast ? "l-note-last" : "l-note"); }); $("." + g._getParentNodeClassName(true), treeNode).each(function () { $(this) .removeClass(g._getParentNodeClassName(true)) .addClass(g._getChildNodeClassName()); }); }, collapseAll: function () { var g = this, p = this.options; $(".l-expandable-open", g.tree).click(); }, expandAll: function () { var g = this, p = this.options; $(".l-expandable-close", g.tree).click(); }, loadData: function (node, url, param) { var g = this, p = this.options; g.loading.show(); var ajaxtype = param ? "post" : "get"; param = param || []; //请求服务器 $.ajax({ type: ajaxtype, url: url, data: param, dataType: 'json', success: function (data) { if (!data) return; g.loading.hide(); g.append(node, data); g.trigger('success', [data]); }, error: function (XMLHttpRequest, textStatus, errorThrown) { try { g.loading.hide(); g.trigger('error', [XMLHttpRequest, textStatus, errorThrown]); } catch (e) { } } }); }, //清空 clear: function () { var g = this, p = this.options; //g.tree.html(""); $("> li", g.tree).each(function () { g.remove(this); }); }, //@parm [treeNode] dom节点(li)、节点数据 或者节点 dataindex getNodeDom: function (nodeParm) { var g = this, p = this.options; if (nodeParm == null) return nodeParm; if (typeof (nodeParm) == "string" || typeof (nodeParm) == "number") { return $("li[treedataindex=" + nodeParm + "]", g.tree).get(0); } else if (typeof (nodeParm) == "object" && 'treedataindex' in nodeParm) //nodedata { return g.getNodeDom(nodeParm['treedataindex']); } return nodeParm; }, //@parm [treeNode] dom节点(li)、节点数据 或者节点 dataindex remove: function (treeNode) { var g = this, p = this.options; treeNode = g.getNodeDom(treeNode); var treedataindex = parseInt($(treeNode).attr("treedataindex")); var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex); if (treenodedata) g._setTreeDataStatus([treenodedata], 'delete'); var parentNode = g.getParentTreeItem(treeNode); //复选框处理 if (p.checkbox) { g._setParentCheckboxStatus($(treeNode)); } $(treeNode).remove(); g._updateStyle(parentNode ? $("ul:first", parentNode) : g.tree); }, _updateStyle: function (ul) { var g = this, p = this.options; var itmes = $(" > li", ul); var treeitemlength = itmes.length; if (!treeitemlength) return; //遍历设置子节点的样式 itmes.each(function (i, item) { if (i == 0 && !$(this).hasClass("l-first")) $(this).addClass("l-first"); if (i == treeitemlength - 1 && !$(this).hasClass("l-last")) $(this).addClass("l-last"); if (i == 0 && i == treeitemlength - 1) $(this).addClass("l-onlychild"); $("> div .l-note,> div .l-note-last", this) .removeClass("l-note l-note-last") .addClass(i == treeitemlength - 1 ? "l-note-last" : "l-note"); g._setTreeItem(this, { isLast: i == treeitemlength - 1 }); }); }, //@parm [domnode] dom节点(li)、节点数据 或者节点 dataindex update: function (domnode, newnodedata) { var g = this, p = this.options; domnode = g.getNodeDom(domnode); var treedataindex = parseInt($(domnode).attr("treedataindex")); nodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex); for (var attr in newnodedata) { nodedata[attr] = newnodedata[attr]; if (attr == p.textFieldName) { $("> .l-body > span", domnode).text(newnodedata[attr]); } } }, //增加节点集合 //@parm [newdata] 数据集合 Array //@parm [parentNode] dom节点(li)、节点数据 或者节点 dataindex //@parm [nearNode] 附加到节点的上方/下方(非必填) //@parm [isAfter] 附加到节点的下方(非必填) append: function (parentNode, newdata, nearNode, isAfter) { var g = this, p = this.options; parentNode = g.getNodeDom(parentNode); if (g.trigger('beforeAppend', [parentNode, newdata]) == false) return false; if (!newdata || !newdata.length) return false; if (p.idFieldName && p.parentIDFieldName) newdata = g.arrayToTree(newdata, p.idFieldName, p.parentIDFieldName); g._addTreeDataIndexToData(newdata); g._setTreeDataStatus(newdata, 'add'); if (nearNode != null) { nearNode = g.getNodeDom(nearNode); } g.trigger('append', [parentNode, newdata]) g._appendData(parentNode, newdata); if (parentNode == null)//增加到根节点 { var gridhtmlarr = g._getTreeHTMLByData(newdata, 1, [], true); gridhtmlarr[gridhtmlarr.length - 1] = gridhtmlarr[0] = ""; if (nearNode != null) { $(nearNode)[isAfter ? 'after' : 'before'](gridhtmlarr.join('')); g._updateStyle(parentNode ? $("ul:first", parentNode) : g.tree); } else { //remove last node class if ($("> li:last", g.tree).length > 0) g._setTreeItem($("> li:last", g.tree)[0], { isLast: false }); g.tree.append(gridhtmlarr.join('')); } $(".l-body", g.tree).hover(function () { $(this).addClass("l-over"); }, function () { $(this).removeClass("l-over"); }); g._upadteTreeWidth(); g.trigger('afterAppend', [parentNode, newdata]) return; } var treeitem = $(parentNode); var outlineLevel = parseInt(treeitem.attr("outlinelevel")); var hasChildren = $("> ul", treeitem).length > 0; if (!hasChildren) { treeitem.append(""); //设置为父节点 g.upgrade(parentNode); } var isLast = []; for (var i = 1; i <= outlineLevel - 1; i++) { var currentParentTreeItem = $(g.getParentTreeItem(parentNode, i)); isLast.push(currentParentTreeItem.hasClass("l-last")); } isLast.push(treeitem.hasClass("l-last")); var gridhtmlarr = g._getTreeHTMLByData(newdata, outlineLevel + 1, isLast, true); gridhtmlarr[gridhtmlarr.length - 1] = gridhtmlarr[0] = ""; if (nearNode != null) { $(nearNode)[isAfter ? 'after' : 'before'](gridhtmlarr.join('')); g._updateStyle(parentNode ? $("ul:first", parentNode) : g.tree); } else { //remove last node class if ($("> .l-children > li:last", treeitem).length > 0) g._setTreeItem($("> .l-children > li:last", treeitem)[0], { isLast: false }); $(">.l-children", parentNode).append(gridhtmlarr.join('')); } g._upadteTreeWidth(); $(">.l-children .l-body", parentNode).hover(function () { $(this).addClass("l-over"); }, function () { $(this).removeClass("l-over"); }); g.trigger('afterAppend', [parentNode, newdata]); }, //@parm [nodeParm] dom节点(li)、节点数据 或者节点 dataindex cancelSelect: function (nodeParm) { var g = this, p = this.options; var domNode = g.getNodeDom(nodeParm); var treeitem = $(domNode); var treedataindex = parseInt(treeitem.attr("treedataindex")); var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex); var treeitembody = $(">div:first", treeitem); if (p.checkbox) $(".l-checkbox", treeitembody).removeClass("l-checkbox-checked").addClass("l-checkbox-unchecked"); else treeitembody.removeClass("l-selected"); g.trigger('cancelSelect', [{ data: treenodedata, target: treeitem[0]}]); }, //选择节点(参数:条件函数、Dom节点或ID值) selectNode: function (selectNodeParm) { var g = this, p = this.options; var clause = null; if (typeof (selectNodeParm) == "function") { clause = selectNodeParm; } else if (typeof (selectNodeParm) == "object") { var treeitem = $(selectNodeParm); var treedataindex = parseInt(treeitem.attr("treedataindex")); var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex); var treeitembody = $(">div:first", treeitem); if (p.checkbox) $(".l-checkbox", treeitembody).removeClass("l-checkbox-unchecked").addClass("l-checkbox-checked"); else treeitembody.addClass("l-selected"); g.trigger('select', [{ data: treenodedata, target: treeitem[0]}]); return; } else { clause = function (data) { if (!data[p.idFieldName]) return false; return data[p.idFieldName].toString() == selectNodeParm.toString(); }; } $("li", g.tree).each(function () { var treeitem = $(this); var treedataindex = parseInt(treeitem.attr("treedataindex")); var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex); if (clause(treenodedata, treedataindex)) { g.selectNode(this); } else { g.cancelSelect(this); } }); }, getTextByID: function (id) { var g = this, p = this.options; var data = g.getDataByID(id); if (!data) return null; return data[p.textFieldName]; }, getDataByID: function (id) { var g = this, p = this.options; var data = null; $("li", g.tree).each(function () { if (data) return; var treeitem = $(this); var treedataindex = parseInt(treeitem.attr("treedataindex")); var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex); if (treenodedata[p.idFieldName].toString() == id.toString()) { data = treenodedata; } }); return data; }, arrayToTree: function (data, id, pid) //将ID、ParentID这种数据格式转换为树格式 { if (!data || !data.length) return []; var targetData = []; //存储数据的容器(返回) var records = {}; var itemLength = data.length; //数据集合的个数 for (var i = 0; i < itemLength; i++) { var o = data[i]; records[o[id]] = o; } for (var i = 0; i < itemLength; i++) { var currentData = data[i]; var parentData = records[currentData[pid]]; if (!parentData) { targetData.push(currentData); continue; } parentData.children = parentData.children || []; parentData.children.push(currentData); } return targetData; }, //根据数据索引获取数据 _getDataNodeByTreeDataIndex: function (data, treedataindex) { var g = this, p = this.options; for (var i = 0; i < data.length; i++) { if (data[i].treedataindex == treedataindex) return data[i]; if (data[i].children) { var targetData = g._getDataNodeByTreeDataIndex(data[i].children, treedataindex); if (targetData) return targetData; } } return null; }, //设置数据状态 _setTreeDataStatus: function (data, status) { var g = this, p = this.options; $(data).each(function () { this[p.statusName] = status; if (this.children) { g._setTreeDataStatus(this.children, status); } }); }, //设置data 索引 _addTreeDataIndexToData: function (data) { var g = this, p = this.options; $(data).each(function () { if (this.treedataindex != undefined) return; this.treedataindex = g.treedataindex++; if (this.children) { g._addTreeDataIndexToData(this.children); } }); }, _addToNodes: function (data) { var g = this, p = this.options; g.nodes = g.nodes || []; if ($.inArray(data, g.nodes) == -1) g.nodes.push(data); if (data.children) { $(data.children).each(function (i, item) { g._addToNodes(item); }); } }, //添加项到g.data _appendData: function (treeNode, data) { var g = this, p = this.options; var treedataindex = parseInt($(treeNode).attr("treedataindex")); var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex); if (g.treedataindex == undefined) g.treedataindex = 0; if (treenodedata && treenodedata.children == undefined) treenodedata.children = []; $(data).each(function (i, item) { if (treenodedata) treenodedata.children[treenodedata.children.length] = item; else g.data[g.data.length] = item; g._addToNodes(item); }); }, _setTreeItem: function (treeNode, options) { var g = this, p = this.options; if (!options) return; treeNode = g.getNodeDom(treeNode); var treeItem = $(treeNode); var outlineLevel = parseInt(treeItem.attr("outlinelevel")); if (options.isLast != undefined) { if (options.isLast == true) { treeItem.removeClass("l-last").addClass("l-last"); $("> div .l-note", treeItem).removeClass("l-note").addClass("l-note-last"); $(".l-children li", treeItem) .find(".l-box:eq(" + (outlineLevel - 1) + ")") .removeClass("l-line"); } else if (options.isLast == false) { treeItem.removeClass("l-last"); $("> div .l-note-last", treeItem).removeClass("l-note-last").addClass("l-note"); $(".l-children li", treeItem) .find(".l-box:eq(" + (outlineLevel - 1) + ")") .removeClass("l-line") .addClass("l-line"); } } }, _upadteTreeWidth: function () { var g = this, p = this.options; var treeWidth = g.maxOutlineLevel * 22; if (p.checkbox) treeWidth += 22; if (p.parentIcon || p.childIcon) treeWidth += 22; treeWidth += p.nodeWidth; g.tree.width(treeWidth); }, _getChildNodeClassName: function () { var g = this, p = this.options; return 'l-tree-icon-' + p.childIcon; }, _getParentNodeClassName: function (isOpen) { var g = this, p = this.options; var nodeclassname = 'l-tree-icon-' + p.parentIcon; if (isOpen) nodeclassname += '-open'; return nodeclassname; }, //根据data生成最终完整的tree html _getTreeHTMLByData: function (data, outlineLevel, isLast, isExpand) { var g = this, p = this.options; if (g.maxOutlineLevel < outlineLevel) g.maxOutlineLevel = outlineLevel; isLast = isLast || []; outlineLevel = outlineLevel || 1; var treehtmlarr = []; if (!isExpand) treehtmlarr.push('