BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { _const: { perPage: 100 }, _defaultConfig: function () { return BI.extend(BI.AbstractTreeValueChooser.superclass._defaultConfig.apply(this, arguments), { items: null, itemsCreator: BI.emptyFn, open: false }); }, _valueFormatter: function (v) { var text = v; if (BI.isNotNull(this.items)) { BI.some(this.items, function (i, item) { if (item.value + "" === v) { text = item.text; return true; } }); } return text; }, _initData: function (items) { this.items = items; var nodes = BI.Tree.treeFormat(items); this.tree = new BI.Tree(); this.tree.initTree(nodes); }, _itemsCreator: function (options, callback) { var self = this, o = this.options; if (!this.items) { o.itemsCreator({}, function (items) { self._initData(items); call(); }); } else { call(); } function call() { switch (options.type) { case BI.TreeView.REQ_TYPE_INIT_DATA: self._reqInitTreeNode(options, callback); break; case BI.TreeView.REQ_TYPE_ADJUST_DATA: self._reqAdjustTreeNode(options, callback); break; case BI.TreeView.REQ_TYPE_SELECT_DATA: self._reqSelectedTreeNode(options, callback); break; case BI.TreeView.REQ_TYPE_GET_SELECTED_DATA: self._reqDisplayTreeNode(options, callback); break; default : self._reqTreeNode(options, callback); break; } } }, _reqDisplayTreeNode: function (op, callback) { var self = this; var result = []; var selectedValues = op.selectedValues; if (selectedValues == null || BI.isEmpty(selectedValues)) { callback({}); return; } doCheck([], this.tree.getRoot(), selectedValues); callback({ items: result }); function doCheck(parentValues, node, selected) { if (selected == null || BI.isEmpty(selected)) { BI.each(node.getChildren(), function (i, child) { var newParents = BI.clone(parentValues); newParents.push(child.value); var llen = self._getChildCount(newParents); createOneJson(child, node.id, llen); doCheck(newParents, child, {}); }); return; } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); // 找不到就是新增值 if(BI.isNull(node)) { createOneJson({ id: BI.UUID(), text: k, value: k }, BI.UUID(), 0); } else { var newParents = BI.clone(parentValues); newParents.push(node.value); createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); doCheck(newParents, node, selected[k]); } }); } function getCount(jo, parentValues) { if (jo == null) { return 0; } if (BI.isEmpty(jo)) { return self._getChildCount(parentValues); } return BI.size(jo); } function createOneJson(node, pId, llen) { result.push({ id: node.id, pId: pId, text: node.text + (llen > 0 ? ("(" + BI.i18nText("BI-Basic_Altogether") + llen + BI.i18nText("BI-Basic_Count") + ")") : ""), value: node.value, open: true }); } }, _reqSelectedTreeNode: function (op, callback) { var self = this; var selectedValues = BI.deepClone(op.selectedValues); var notSelectedValue = op.notSelectedValue || {}; var keyword = op.keyword || ""; var parentValues = op.parentValues || []; if (selectedValues == null || BI.isEmpty(selectedValues)) { callback({}); return; } dealWithSelectedValues(selectedValues); callback(selectedValues); function dealWithSelectedValues(selectedValues) { var p = parentValues.concat(notSelectedValue); // 存储的值中存在这个值就把它删掉 // 例如选中了中国-江苏-南京, 取消中国或江苏或南京 if (canFindKey(selectedValues, p)) { // 如果搜索的值在父亲链中 if (isSearchValueInParent(p)) { // 例如选中了 中国-江苏, 搜索江苏, 取消江苏 // 例如选中了 中国-江苏, 搜索江苏, 取消中国 self._deleteNode(selectedValues, p); } else { var searched = []; var find = search(parentValues, notSelectedValue, [], searched); if (find && BI.isNotEmptyArray(searched)) { BI.each(searched, function (i, arr) { var node = self._getNode(selectedValues, arr); if (node) { // 例如选中了 中国-江苏-南京,搜索南京,取消中国 self._deleteNode(selectedValues, arr); } else { // 例如选中了 中国-江苏,搜索南京,取消中国 expandSelectedValue(selectedValues, arr, BI.last(arr)); } }); } } } // 存储的值中不存在这个值,但父亲节点是全选的情况 // 例如选中了中国-江苏,取消南京 // important 选中了中国-江苏,取消了江苏,但是搜索的是南京 if (isChild(selectedValues, p)) { var result = [], find = false; // 如果parentValues中有匹配的值,说明搜索结果不在当前值下 if (isSearchValueInParent(p)) { find = true; } else { // 从当前值开始搜 find = search(parentValues, notSelectedValue, result); p = parentValues; } if (find === true) { // 去掉点击的节点之后的结果集 expandSelectedValue(selectedValues, p, notSelectedValue); // 添加去掉搜索的结果集 if (result.length > 0) { BI.each(result, function (i, strs) { self._buildTree(selectedValues, strs); }); } } } } function expandSelectedValue(selectedValues, parents, notSelectedValue) { var next = selectedValues; var childrenCount = []; var path = []; // 去掉点击的节点之后的结果集 BI.some(parents, function (i, v) { var t = next[v]; if (t == null) { if (i === 0) { return true; } if (BI.isEmpty(next)) { var split = parents.slice(0, i); var expanded = self._getChildren(split); path.push(split); childrenCount.push(expanded.length); // 如果只有一个值且取消的就是这个值 if (i === parents.length - 1 && expanded.length === 1 && expanded[0] === notSelectedValue) { for (var j = childrenCount.length - 1; j >= 0; j--) { if (childrenCount[j] === 1) { self._deleteNode(selectedValues, path[j]); } else { break; } } } else { BI.each(expanded, function (m, child) { if (i === parents.length - 1 && child.value === notSelectedValue) { return true; } next[child.value] = {}; }); } next = next[v]; } else { return true; // next = {}; // next[v] = {}; } } else { next = t; } }); } function search(parents, current, result, searched) { var newParents = BI.clone(parents); newParents.push(current); if (self._isMatch(parents, current, keyword)) { searched && searched.push(newParents); return true; } var children = self._getChildren(newParents); var notSearch = []; var can = false; BI.each(children, function (i, child) { if (search(newParents, child.value, result, searched)) { can = true; } else { notSearch.push(child.value); } }); if (can === true) { BI.each(notSearch, function (i, v) { var next = BI.clone(newParents); next.push(v); result.push(next); }); } return can; } function isSearchValueInParent(parentValues) { for (var i = 0, len = parentValues.length; i < len; i++) { if (self._isMatch(parentValues.slice(0, i), parentValues[i], keyword)) { return true; } } return false; } function canFindKey(selectedValues, parents) { var t = selectedValues; for (var i = 0; i < parents.length; i++) { var v = parents[i]; t = t[v]; if (t == null) { return false; } } return true; } function isChild(selectedValues, parents) { var t = selectedValues; for (var i = 0; i < parents.length; i++) { var v = parents[i]; if (!BI.has(t, v)) { return false; } t = t[v]; if (BI.isEmpty(t)) { return true; } } return false; } }, _reqAdjustTreeNode: function (op, callback) { var self = this; var result = []; var selectedValues = op.selectedValues; if (selectedValues == null || BI.isEmpty(selectedValues)) { callback({}); return; } BI.each(selectedValues, function (k, v) { result.push([k]); }); dealWithSelectedValues(selectedValues, []); var jo = {}; BI.each(result, function (i, strs) { self._buildTree(jo, strs); }); callback(jo); function dealWithSelectedValues(selected, parents) { if (selected == null || BI.isEmpty(selected)) { return true; } var can = true; BI.each(selected, function (k, v) { var p = BI.clone(parents); p.push(k); if (!dealWithSelectedValues(selected[k], p)) { BI.each(selected[k], function (nk, nv) { var t = BI.clone(p); t.push(nk); result.push(t); }); can = false; } }); return can && isAllSelected(selected, parents); } function isAllSelected(selected, parents) { return BI.isEmpty(selected) || self._getChildCount(parents) === BI.size(selected); } }, _reqInitTreeNode: function (op, callback) { var self = this; var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ hasNext: output.length > self._const.perPage, items: result, lastSearchValue: BI.last(output) }); }); function search() { var children = self._getChildren([]); var start = children.length; if (lastSearchValue !== "") { for (var j = 0, len = start; j < len; j++) { if (children[j].value === lastSearchValue) { start = j + 1; break; } } } else { start = 0; } var output = []; for (var i = start, len = children.length; i < len; i++) { if (output.length < self._const.perPage) { var find = nodeSearch(1, [], children[i].value, false, result); } else if (output.length === self._const.perPage) { var find = nodeSearch(1, [], children[i].value, false, []); } if (find[0] === true) { output.push(children[i].value); } if (output.length > self._const.perPage) { break; } } // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 if (op.times === 1) { var nodes = self._getAddedValueNode([], selectedValues); result = BI.concat(BI.filter(nodes, function (idx, node) { var find = BI.Func.getSearchResult([node.text || node.value], keyword); return find.find.length > 0 || find.match.length > 0; }), result); } return output; } function nodeSearch(deep, parentValues, current, isAllSelect, result) { if (self._isMatch(parentValues, current, keyword)) { var checked = isAllSelect || isSelected(parentValues, current); createOneJson(parentValues, current, false, checked, !isAllSelect && isHalf(parentValues, current), true, result); return [true, checked]; } var newParents = BI.clone(parentValues); newParents.push(current); var children = self._getChildren(newParents); var can = false, checked = false; var isCurAllSelected = isAllSelect || isAllSelected(parentValues, current); BI.each(children, function (i, child) { var state = nodeSearch(deep + 1, newParents, child.value, isCurAllSelected, result); if (state[1] === true) { checked = true; } if (state[0] === true) { can = true; } }); if (can === true) { checked = isCurAllSelected || (isSelected(parentValues, current) && checked); createOneJson(parentValues, current, true, checked, false, false, result); } return [can, checked]; } function createOneJson(parentValues, value, isOpen, checked, half, flag, result) { var node = self._getTreeNode(parentValues, value); result.push({ id: node.id, pId: node.pId, text: node.text, value: node.value, title: node.title, isParent: node.getChildrenLength() > 0, open: isOpen, checked: checked, halfCheck: half, flag: flag }); } function isHalf(parentValues, value) { var find = findSelectedObj(parentValues); if (find == null) { return null; } return BI.any(find, function (v, ob) { if (v === value) { if (ob != null && !BI.isEmpty(ob)) { return true; } } }); } function isAllSelected(parentValues, value) { var find = findSelectedObj(parentValues); if (find == null) { return null; } return BI.any(find, function (v, ob) { if (v === value) { if (ob != null && BI.isEmpty(ob)) { return true; } } }); } function isSelected(parentValues, value) { var find = findSelectedObj(parentValues); if (find == null) { return false; } return BI.any(find, function (v) { if (v === value) { return true; } }); } function findSelectedObj(parentValues) { var find = selectedValues; if (find == null) { return null; } BI.every(parentValues, function (i, v) { find = find[v]; if (find == null) { return false; } return true; }); return find; } }, _reqTreeNode: function (op, callback) { var self = this, o = this.options; var result = []; var times = op.times; var checkState = op.checkState || {}; var parentValues = op.parentValues || []; var selectedValues = op.selectedValues || {}; var valueMap = {}; // if (judgeState(parentValues, selectedValues, checkState)) { valueMap = dealWithSelectedValue(parentValues, selectedValues); // } var nodes = this._getChildren(parentValues); for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { var state = getCheckState(nodes[i].value, parentValues, valueMap, checkState); result.push({ id: nodes[i].id, pId: nodes[i].pId, value: nodes[i].value, text: nodes[i].text, times: 1, isParent: nodes[i].getChildrenLength() > 0, checked: state[0], halfCheck: state[1], open: o.open }); } // 如果指定节点全部打开 if (o.open) { var allNodes = []; // 获取所有节点 BI.each(nodes, function (idx, node) { allNodes = BI.concat(allNodes, self._getAllChildren(parentValues.concat([node.value]))); }); BI.each(allNodes, function (idx, node) { var valueMap = dealWithSelectedValue(node.parentValues, selectedValues); var state = getCheckState(node.value, node.parentValues, valueMap, checkState); result.push({ id: node.id, pId: node.pId, value: node.value, text: node.text, times: 1, isParent: node.getChildrenLength() > 0, checked: state[0], halfCheck: state[1], open: self.options.open }); }); } // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 if (parentValues.length === 0 && times === 1) { result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); } BI.nextTick(function () { callback({ items: result, hasNext: nodes.length > times * self._const.perPage }); }); function judgeState(parentValues, selected_value, checkState) { var checked = checkState.checked, half = checkState.half; if (parentValues.length > 0 && !checked) { return false; } return (parentValues.length === 0 || (checked && half) && !BI.isEmpty(selected_value)); } function dealWithSelectedValue(parentValues, selectedValues) { var valueMap = {}; BI.each(parentValues, function (i, v) { selectedValues = selectedValues[v] || {}; }); BI.each(selectedValues, function (value, obj) { if (BI.isNull(obj)) { valueMap[value] = [0, 0]; return; } if (BI.isEmpty(obj)) { valueMap[value] = [2, 0]; return; } var nextNames = {}; BI.each(obj, function (t, o) { if (BI.isNull(o) || BI.isEmpty(o)) { nextNames[t] = true; } }); // valueMap的数组第一个参数为不选: 0, 半选: 1, 全选:2, 第二个参数为改节点下选中的子节点个数(子节点全选或者不存在) valueMap[value] = [1, BI.size(nextNames)]; }); return valueMap; } function getCheckState(current, parentValues, valueMap, checkState) { // 节点本身的checked和half优先级最高 var checked = checkState.checked, half = checkState.half; var tempCheck = false, halfCheck = false; if (BI.has(valueMap, current)) { // 可能是半选 if (valueMap[current][0] === 1) { var values = BI.clone(parentValues); values.push(current); var childCount = self._getChildCount(values); if (childCount > 0 && childCount !== valueMap[current][1]) { halfCheck = true; } } else if (valueMap[current][0] === 2) { tempCheck = true; } } var check; if (!checked && !halfCheck && !tempCheck) { // 当节点自身是不选的,且通过selectedValues没有得到全选, 则check状态取决于valueMap check = BI.has(valueMap, current); } else { // 不是上面那种情况就先看在节点没有带有明确半选的时候,通过节点自身的checked和valueMap的状态能都得到选中信息 check = ((tempCheck || checked) && !half) || BI.has(valueMap, current); } return [check, halfCheck]; } }, _getAddedValueNode: function (parentValues, selectedValues) { var nodes = this._getChildren(parentValues); return BI.map(BI.difference(BI.keys(selectedValues), BI.map(nodes, "value")), function (idx, v) { return { id: BI.UUID(), pId: nodes.length > 0 ? nodes[0].pId : BI.UUID(), value: v, text: v, times: 1, isParent: false, checked: true, halfCheck: false }; }); }, _getNode: function (selectedValues, parentValues) { var pNode = selectedValues; for (var i = 0, len = parentValues.length; i < len; i++) { if (pNode == null) { return null; } pNode = pNode[parentValues[i]]; } return pNode; }, _deleteNode: function (selectedValues, values) { var name = values[values.length - 1]; var p = values.slice(0, values.length - 1); var pNode = this._getNode(selectedValues, p); if (pNode != null && pNode[name]) { delete pNode[name]; // 递归删掉空父节点 while (p.length > 0 && BI.isEmpty(pNode)) { name = p[p.length - 1]; p = p.slice(0, p.length - 1); pNode = this._getNode(selectedValues, p); if (pNode != null) { delete pNode[name]; } } } }, _buildTree: function (jo, values) { var t = jo; BI.each(values, function (i, v) { if (!BI.has(t, v)) { t[v] = {}; } t = t[v]; }); }, _isMatch: function (parentValues, value, keyword) { var o = this.options; var node = this._getTreeNode(parentValues, value); if (!node) { return false; } var find = BI.Func.getSearchResult([node.text || node.value], keyword); if(o.allowSearchValue && node.value) { var valueFind = BI.Func.getSearchResult([node.value], keyword); return valueFind.find.length > 0 || valueFind.match.length > 0 || find.find.length > 0 || find.match.length > 0; } return find.find.length > 0 || find.match.length > 0; }, _getTreeNode: function (parentValues, v) { var self = this; var findParentNode; var index = 0; this.tree.traverse(function (node) { if (self.tree.isRoot(node)) { return; } if (index > parentValues.length) { return false; } if (index === parentValues.length && node.value === v) { findParentNode = node; return false; } if (node.value === parentValues[index]) { index++; return; } return true; }); return findParentNode; }, _getChildren: function (parentValues) { if (parentValues.length > 0) { var value = BI.last(parentValues); var parent = this._getTreeNode(parentValues.slice(0, parentValues.length - 1), value); } else { var parent = this.tree.getRoot(); } return parent.getChildren(); }, _getAllChildren: function(parentValues) { var children = this._getChildren(parentValues); var nodes = [].concat(children); BI.each(nodes, function (idx, node) { node.parentValues = parentValues; }); var queue = BI.map(children, function (idx, node) { return { parentValues: parentValues, value: node.value }; }); while (BI.isNotEmptyArray(queue)) { var node = queue.shift(); var pValues = (node.parentValues).concat(node.value); var childNodes = this._getChildren(pValues); BI.each(childNodes, function (idx, node) { node.parentValues = pValues; }); queue = queue.concat(childNodes); nodes = nodes.concat(childNodes); } return nodes; }, _getChildCount: function (parentValues) { return this._getChildren(parentValues).length; } });