/** * guy * 异步树 * @class BI.TreeView * @extends BI.Pane */ BI.TreeView = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.TreeView.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-tree", paras: {}, itemsCreator: BI.emptyFn }); }, _init: function () { BI.TreeView.superclass._init.apply(this, arguments); this._stop = false; this._createTree(); this.tip = BI.createWidget({ type: "bi.loading_bar", invisible: true, handler: BI.bind(this._loadMore, this) }); BI.createWidget({ type: "bi.vertical", scrollable: true, scrolly: false, element: this, items: [this.tip] }); }, _createTree: function () { this.id = "bi-tree" + BI.UUID(); if (this.nodes) { this.nodes.destroy(); } if (this.tree) { this.tree.destroy(); } this.tree = BI.createWidget({ type: "bi.layout", element: "" }); BI.createWidget({ type: "bi.default", element: this.element, items: [this.tree] }); }, // 选择节点触发方法 _selectTreeNode: function (treeId, treeNode) { this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CLICK, treeNode, this); this.fireEvent(BI.TreeView.EVENT_CHANGE, treeNode, this); }, // 配置属性 _configSetting: function () { var paras = this.options.paras; var self = this; var setting = { async: { enable: true, url: getUrl, autoParam: ["id", "name"], otherParam: BI.cjkEncodeDO(paras) }, check: { enable: true }, data: { key: { title: "title", name: "text" }, simpleData: { enable: true } }, view: { showIcon: false, expandSpeed: "", nameIsHTML: true, dblClickExpand: false }, callback: { beforeExpand: beforeExpand, onAsyncSuccess: onAsyncSuccess, onAsyncError: onAsyncError, beforeCheck: beforeCheck, onCheck: onCheck, onExpand: onExpand, onCollapse: onCollapse, onClick: onClick } }; var className = "dark", perTime = 100; function onClick (event, treeId, treeNode) { self.nodes.checkNode(treeNode, !treeNode.checked, true, true); } function getUrl (treeId, treeNode) { var parentNode = self._getParentValues(treeNode); treeNode.times = treeNode.times || 1; var param = "id=" + treeNode.id + "×=" + (treeNode.times++) + "&parentValues= " + window.encodeURIComponent(BI.jsonEncode(parentNode)) + "&checkState=" + window.encodeURIComponent(BI.jsonEncode(treeNode.getCheckStatus())); return BI.servletURL + "?op=" + self.options.op + "&cmd=" + self.options.cmd + "&" + param; } function beforeExpand (treeId, treeNode) { if (!treeNode.isAjaxing) { if (!treeNode.children) { treeNode.times = 1; ajaxGetNodes(treeNode, "refresh"); } return true; } BI.Msg.toast("Please Wait。", "warning"); return false; } function onAsyncSuccess (event, treeId, treeNode, msg) { treeNode.halfCheck = false; if (!msg || msg.length === 0 || /^[\s,\S]*<\/html>$/gi.test(msg) || self._stop) { return; } var zTree = self.nodes; var totalCount = treeNode.count || 0; // 尝试去获取下一组节点,若获取值为空数组,表示获取完成 // TODO by GUY if (treeNode.children.length > totalCount) { treeNode.count = treeNode.children.length; BI.delay(function () { ajaxGetNodes(treeNode); }, perTime); } else { // treeNode.icon = ""; zTree.updateNode(treeNode); zTree.selectNode(treeNode.children[0]); // className = (className === "dark" ? "":"dark"); } } function onAsyncError (event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown) { var zTree = self.nodes; BI.Msg.toast("Error!", "warning"); // treeNode.icon = ""; // zTree.updateNode(treeNode); } function ajaxGetNodes (treeNode, reloadType) { var zTree = self.nodes; if (reloadType == "refresh") { // treeNode.icon = BI.servletURL +"?op=resource&resource=/com/fr/bi/web/css/base/third/ztree/img/loading.gif"; zTree.updateNode(treeNode); } zTree.reAsyncChildNodes(treeNode, reloadType, true); } function beforeCheck (treeId, treeNode) { treeNode.halfCheck = false; if (treeNode.checked === true) { // 将展开的节点halfCheck设为false,解决展开节点存在halfCheck=true的情况 guy // 所有的半选状态都需要取消halfCheck=true的情况 function track (children) { BI.each(children, function (i, ch) { if (ch.halfCheck === true) { ch.halfCheck = false; track(ch.children); } }); } track(treeNode.children); var treeObj = self.nodes; var nodes = treeObj.getSelectedNodes(); $.each(nodes, function (index, node) { node.halfCheck = false; }); } } function onCheck (event, treeId, treeNode) { self._selectTreeNode(treeId, treeNode); } function onExpand (event, treeId, treeNode) { treeNode.halfCheck = false; } function onCollapse (event, treeId, treeNode) { } return setting; }, _getParentValues: function (treeNode) { if (!treeNode.getParentNode()) { return []; } var parentNode = treeNode.getParentNode(); var result = this._getParentValues(parentNode); result = result.concat([this._getNodeValue(parentNode)]); return result; }, _getNodeValue: function (node) { // 去除标红 return node.value == null ? node.text.replace(/<[^>]+>/g, "").replaceAll(" ", " ") : node.value; }, // 获取半选框值 _getHalfSelectedValues: function (map, node) { var self = this; var checkState = node.getCheckStatus(); // 将未选的去掉 if (checkState.checked === false && checkState.half === false) { return; } // 如果节点已展开,并且是半选 if (BI.isNotEmptyArray(node.children) && checkState.half === true) { var children = node.children; BI.each(children, function (i, ch) { self._getHalfSelectedValues(map, ch); }); return; } var parent = node.parentValues || self._getParentValues(node); var path = parent.concat(this._getNodeValue(node)); if (BI.isNotEmptyArray(node.children) || checkState.half === false) { this._buildTree(map, path); return; } var storeValues = BI.deepClone(this.options.paras.selectedValues); var treeNode = this._getTree(storeValues, path); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); }, _getTree: function (map, values) { var cur = map; BI.any(values, function (i, value) { if (cur[value] == null) { return true; } cur = cur[value]; }); return cur; }, _addTreeNode: function (map, values, key, value) { var cur = map; BI.each(values, function (i, value) { if (cur[value] == null) { cur[value] = {}; } cur = cur[value]; }); cur[key] = value; }, // 构造树节点 _buildTree: function (map, values) { var cur = map; BI.each(values, function (i, value) { if (cur[value] == null) { cur[value] = {}; } cur = cur[value]; }); }, // 获取选中的值 _getSelectedValues: function () { var self = this; var hashMap = {}; var rootNoots = this.nodes.getNodes(); track(rootNoots); function track (nodes) { BI.each(nodes, function (i, node) { var checkState = node.getCheckStatus(); if (checkState.checked === true || checkState.half === true) { if (checkState.half === true) { self._getHalfSelectedValues(hashMap, node); } else { var parentValues = node.parentValues || self._getParentValues(node); var values = parentValues.concat([self._getNodeValue(node)]); self._buildTree(hashMap, values); } } }); } return hashMap; }, // 处理节点 _dealWidthNodes: function (nodes) { var self = this, o = this.options; var ns = BI.Tree.arrayFormat(nodes); BI.each(ns, function (i, n) { n.title = n.title || n.text || n.value; // 处理标红 if (BI.isKey(o.paras.keyword)) { n.text = $("
").__textKeywordMarked__(n.text, o.paras.keyword, n.py).html(); } else { n.text = (n.text + "").replaceAll(" ", " "); } }); return nodes; }, _loadMore: function () { var self = this, o = this.options; this.tip.setLoading(); var op = BI.extend({}, o.paras, { times: ++this.times }); o.itemsCreator(op, function (res) { if (self._stop === true) { return; } var hasNext = !!res.hasNext, nodes = res.items || []; if (!hasNext) { self.tip.setEnd(); } else { self.tip.setLoaded(); } if (nodes.length > 0) { self.nodes.addNodes(null, self._dealWidthNodes(nodes)); } }); }, // 生成树内部方法 _initTree: function (setting) { var self = this, o = this.options; self.fireEvent(BI.Events.INIT); this.times = 1; var tree = this.tree; tree.empty(); this.loading(); this.tip.setVisible(false); var callback = function (nodes) { if (self._stop === true) { return; } self.nodes = $.fn.zTree.init(tree.element, setting, nodes); }; var op = BI.extend({}, o.paras, { times: 1 }); o.itemsCreator(op, function (res) { if (self._stop === true) { return; } var hasNext = !!res.hasNext, nodes = res.items || []; if (nodes.length > 0) { callback(self._dealWidthNodes(nodes)); } self.setTipVisible(nodes.length <= 0); self.loaded(); if (!hasNext) { self.tip.invisible(); } else { self.tip.setLoaded(); } op.times === 1 && self.fireEvent(BI.Events.AFTERINIT); }); }, // 构造树结构, initTree: function (nodes, setting) { var setting = setting || { async: { enable: false }, check: { enable: false }, data: { key: { title: "title", name: "text" }, simpleData: { enable: true } }, view: { showIcon: false, expandSpeed: "", nameIsHTML: true }, callback: {} }; this.nodes = $.fn.zTree.init(this.tree.element, setting, nodes); }, start: function () { this._stop = false; }, stop: function () { this._stop = true; }, // 生成树方法 stroke: function (config) { delete this.options.keyword; BI.extend(this.options.paras, config); var setting = this._configSetting(); this._createTree(); this.start(); this._initTree(setting); }, populate: function () { this.stroke.apply(this, arguments); }, hasChecked: function () { var treeObj = this.nodes; return treeObj.getCheckedNodes(true).length > 0; }, checkAll: function (checked) { function setNode (children) { BI.each(children, function (i, child) { child.halfCheck = false; setNode(child.children); }); } if (!this.nodes) { return; } BI.each(this.nodes.getNodes(), function (i, node) { node.halfCheck = false; setNode(node.children); }); this.nodes.checkAllNodes(checked); }, expandAll: function (flag) { this.nodes && this.nodes.expandAll(flag); }, // 设置树节点的状态 setValue: function (value, param) { this.checkAll(false); this.updateValue(value, param); this.refresh(); }, setSelectedValue: function (value) { this.options.paras.selectedValues = BI.deepClone(value || {}); }, updateValue: function (values, param) { if (!this.nodes) { return; } param || (param = "value"); var treeObj = this.nodes; BI.each(values, function (v, op) { var nodes = treeObj.getNodesByParam(param, v, null); BI.each(nodes, function (j, node) { BI.extend(node, {checked: true}, op); treeObj.updateNode(node); }); }); }, refresh: function () { this.nodes && this.nodes.refresh(); }, getValue: function () { if (!this.nodes) { return null; } return this._getSelectedValues(); }, destroyed: function () { this.stop(); this.nodes && this.nodes.destroy(); } }); BI.extend(BI.TreeView, { REQ_TYPE_INIT_DATA: 1, REQ_TYPE_ADJUST_DATA: 2, REQ_TYPE_SELECT_DATA: 3, REQ_TYPE_GET_SELECTED_DATA: 4 }); BI.TreeView.EVENT_CHANGE = "EVENT_CHANGE"; BI.TreeView.EVENT_INIT = BI.Events.INIT; BI.TreeView.EVENT_AFTERINIT = BI.Events.AFTERINIT; BI.shortcut("bi.tree_view", BI.TreeView);