From 19c248cd78bf2858f3d26782ad14e4aa3e069f18 Mon Sep 17 00:00:00 2001 From: windy <1374721899@qq.com> Date: Mon, 29 Apr 2019 15:27:20 +0800 Subject: [PATCH 1/5] =?UTF-8?q?BI-44287=20feat:=20=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=80=BC=E7=9A=84=E6=A0=91=E6=8E=A7=E4=BB=B6?= =?UTF-8?q?=E4=B8=80=E8=B5=B7demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/demo.treevaluechoosercombo.js | 2 +- dist/2.0/fineui.css | 12 +- dist/2.0/fineui.ie.js | 532 +++++++++++++++++- dist/2.0/fineui.js | 532 +++++++++++++++++- dist/base.css | 12 +- dist/base.js | 49 +- dist/bundle.css | 12 +- dist/bundle.ie.js | 532 +++++++++++++++++- dist/bundle.js | 532 +++++++++++++++++- dist/core.js | 16 +- dist/demo.js | 2 +- dist/fineui.css | 16 +- dist/fineui.ie.js | 532 +++++++++++++++++- dist/fineui.js | 532 +++++++++++++++++- dist/fineui_without_jquery_polyfill.js | 502 ++++++++++++++++- dist/widget.js | 491 +++++++++++++++- src/base/tree/ztree/asynctree.js | 8 +- src/base/tree/ztree/parttree.js | 7 +- src/base/tree/ztree/treeview.js | 23 +- .../abstract.treevaluechooser.js | 48 +- .../combo.treevaluechooser.insert.js | 54 ++ .../multitree/multi.tree.insert.combo.js | 286 ++++++++++ .../trigger/multi.tree.search.insert.pane.js | 106 ++++ 23 files changed, 4655 insertions(+), 183 deletions(-) create mode 100644 src/component/treevaluechooser/combo.treevaluechooser.insert.js create mode 100644 src/widget/multitree/multi.tree.insert.combo.js create mode 100644 src/widget/multitree/trigger/multi.tree.search.insert.pane.js diff --git a/demo/js/component/demo.treevaluechoosercombo.js b/demo/js/component/demo.treevaluechoosercombo.js index 8fa557ee1..91e11a72c 100644 --- a/demo/js/component/demo.treevaluechoosercombo.js +++ b/demo/js/component/demo.treevaluechoosercombo.js @@ -5,7 +5,7 @@ Demo.TreeValueChooser = BI.inherit(BI.Widget, { render: function () { var widget = BI.createWidget({ - type: "bi.tree_value_chooser_combo", + type: "bi.tree_value_chooser_insert_combo", width: 300, // items: BI.deepClone(Demo.CONSTANTS.TREEITEMS), itemsCreator: function (op, callback) { diff --git a/dist/2.0/fineui.css b/dist/2.0/fineui.css index 214c1b104..d03531953 100644 --- a/dist/2.0/fineui.css +++ b/dist/2.0/fineui.css @@ -3579,7 +3579,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, opacity: 0; } .bi-checkbox.disabled.active .checkbox-content { - border-color: #e8eaed; + border-color: #d0d4da; } .bi-checkbox.disabled.active .checkbox-content:after { opacity: 1; @@ -3587,6 +3587,16 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-checkbox .checkbox-content { border-color: #9EA6B2; } +.bi-theme-dark .bi-checkbox.active .checkbox-content, +.bi-theme-dark .bi-checkbox:active .checkbox-content { + border-color: #3685f2; +} +.bi-theme-dark .bi-checkbox.disabled .checkbox-content { + background-color: #606479; +} +.bi-theme-dark .bi-checkbox.disabled.active .checkbox-content { + border-color: #606479; +} .bi-file { opacity: 0; filter: alpha(opacity=0); diff --git a/dist/2.0/fineui.ie.js b/dist/2.0/fineui.ie.js index 19230dd03..4ec7479be 100644 --- a/dist/2.0/fineui.ie.js +++ b/dist/2.0/fineui.ie.js @@ -37190,8 +37190,8 @@ BI.TreeView = BI.inherit(BI.Pane, { async: { enable: true, url: getUrl, - autoParam: ["id", "name"], - otherParam: BI.cjkEncodeDO(paras) + autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name + otherParam: BI.cjkEncodeDO(paras) // 静态参数 }, check: { enable: true @@ -37199,16 +37199,16 @@ BI.TreeView = BI.inherit(BI.Pane, { data: { key: { title: "title", - name: "text" + name: "text" // 节点的name属性替换成text }, simpleData: { - enable: true + enable: true // 可以穿id,pid属性的对象数组 } }, view: { showIcon: false, expandSpeed: "", - nameIsHTML: true, + nameIsHTML: true, // 节点可以用html标签代替 dblClickExpand: false }, callback: { @@ -37231,6 +37231,7 @@ BI.TreeView = BI.inherit(BI.Pane, { if(status.half === true && status.checked === true) { checked = false; } + // 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调 self.nodes.checkNode(treeNode, !checked, true, true); } @@ -37253,7 +37254,7 @@ BI.TreeView = BI.inherit(BI.Pane, { } return true; } - BI.Msg.toast("Please Wait。", "warning"); + BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件 return false; } @@ -37291,9 +37292,9 @@ BI.TreeView = BI.inherit(BI.Pane, { function ajaxGetNodes (treeNode, reloadType) { var zTree = self.nodes; if (reloadType == "refresh") { - zTree.updateNode(treeNode); + zTree.updateNode(treeNode); // 刷新一下当前节点,如果treeNode.xxx被改了的话 } - zTree.reAsyncChildNodes(treeNode, reloadType, true); + zTree.reAsyncChildNodes(treeNode, reloadType, true); // 强制加载子节点,reloadType === refresh为先清空再加载,否则为追加到现有子节点之后 } function beforeCheck (treeId, treeNode) { @@ -37371,15 +37372,18 @@ BI.TreeView = BI.inherit(BI.Pane, { } 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; } + // 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况) var storeValues = BI.deepClone(this.options.paras.selectedValues); var treeNode = this._getTree(storeValues, path); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); }, + // 获取的是以values最后一个节点为根的子树 _getTree: function (map, values) { var cur = map; BI.any(values, function (i, value) { @@ -37391,6 +37395,7 @@ BI.TreeView = BI.inherit(BI.Pane, { return cur; }, + // 以values为path一路向里补充map, 并在末尾节点添加key: value节点 _addTreeNode: function (map, values, key, value) { var cur = map; BI.each(values, function (i, value) { @@ -37418,7 +37423,7 @@ BI.TreeView = BI.inherit(BI.Pane, { var self = this; var hashMap = {}; var rootNoots = this.nodes.getNodes(); - track(rootNoots); + track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点 function track (nodes) { BI.each(nodes, function (i, node) { var checkState = node.getCheckStatus(); @@ -37666,7 +37671,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { var self = this; var setting = { async: { - enable: false, + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 otherParam: BI.cjkEncodeDO(paras) }, check: { @@ -37756,6 +37761,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { return setting; }, + // 用来更新this.options.paras.selectedValues, 和ztree内部无关 _selectTreeNode: function (treeId, treeNode) { var self = this, o = this.options; var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); @@ -37801,7 +37807,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { function callback (nodes, hasNext) { self.nodes.addNodes(treeNode, nodes); - + // 展开节点是没有分页的 if (hasNext === true) { BI.delay(function () { times++; @@ -37818,6 +37824,9 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { } }, + // a,b 两棵树 + // a->b b->a 做两次校验, 构造一个校验后的map + // e.g. 以a为基准,如果b没有此节点,则在map中添加。 如b有,且是全选的, 则在map中构造全选(为什么不添加a的值呢? 因为这次是取并集), 如果b中也有和a一样的存值,就递归 _join: function (valueA, valueB) { var self = this; var map = {}; @@ -37912,6 +37921,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); } else { // 如果选中的值中不存在该值不处理 + // 因为反正是不选中,没必要管 var t = this.options.paras.selectedValues; var p = parentValues.concat(name); for (var i = 0, len = p.length; i < len; i++) { @@ -37919,6 +37929,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { if (t == null) { return; } + // 选中中国-江苏, 搜索南京,取消勾选 if (BI.isEmpty(t)) { break; } @@ -37982,9 +37993,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } var hasNext = !!d.hasNext, nodes = d.items || []; o.paras.lastSearchValue = d.lastSearchValue; - if (nodes.length > 0) { - callback(self._dealWidthNodes(nodes)); - } + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); self.setTipVisible(nodes.length <= 0); self.loaded(); if (!hasNext) { @@ -38890,7 +38900,8 @@ BI.Combo = BI.inherit(BI.Widget, { }, showView: function (e) { - if (this.isEnabled() && this.combo.isEnabled()) { + // 减少popup 调整宽高的次数 + if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) { this._popupView(e); } }, @@ -72488,6 +72499,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeInsertCombo + * @extends BI.Single + */ + +BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-insert-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || {}}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : {} + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: {}}; + } + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || {}; + this.combo.setValue({ + value: v || {} + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -72724,6 +73020,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, { BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchInsertPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { + + constants: { + height: 24, + }, + + props: { + baseCls: "bi-multi-tree-search-insert-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }, + + render: function () { + var self = this, opts = this.options; + + return { + type: "bi.vertical", + items: [{ + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + hgap: 5, + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } + }, { + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }] + }; + }, + + setKeyword: function (keyword, nodes) { + var isAddTipVisible = BI.isEmptyArray(nodes); + this.addTip.setVisible(isAddTipVisible); + this.partTree.setVisible(!isAddTipVisible); + isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; + +BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -82600,10 +83001,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); - 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]); + // 找不到就是新增值 + 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]); + } }); } @@ -82863,7 +83273,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; - var lastSearchValue = op.lastSearchValue || ""; + var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ @@ -82900,6 +83310,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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; } @@ -83029,6 +83448,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: state[1] }); } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + if (parentValues.length === 0 && times === 1) { + result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); + } BI.nextTick(function () { callback({ items: result, @@ -83095,6 +83518,22 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }, + _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++) { @@ -83181,6 +83620,59 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return this._getChildren(parentValues).length; } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.TreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_insert_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "TreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况 * * Created by GUY on 2015/10/29. diff --git a/dist/2.0/fineui.js b/dist/2.0/fineui.js index 73e1d82c0..f75e83c0c 100644 --- a/dist/2.0/fineui.js +++ b/dist/2.0/fineui.js @@ -37594,8 +37594,8 @@ BI.TreeView = BI.inherit(BI.Pane, { async: { enable: true, url: getUrl, - autoParam: ["id", "name"], - otherParam: BI.cjkEncodeDO(paras) + autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name + otherParam: BI.cjkEncodeDO(paras) // 静态参数 }, check: { enable: true @@ -37603,16 +37603,16 @@ BI.TreeView = BI.inherit(BI.Pane, { data: { key: { title: "title", - name: "text" + name: "text" // 节点的name属性替换成text }, simpleData: { - enable: true + enable: true // 可以穿id,pid属性的对象数组 } }, view: { showIcon: false, expandSpeed: "", - nameIsHTML: true, + nameIsHTML: true, // 节点可以用html标签代替 dblClickExpand: false }, callback: { @@ -37635,6 +37635,7 @@ BI.TreeView = BI.inherit(BI.Pane, { if(status.half === true && status.checked === true) { checked = false; } + // 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调 self.nodes.checkNode(treeNode, !checked, true, true); } @@ -37657,7 +37658,7 @@ BI.TreeView = BI.inherit(BI.Pane, { } return true; } - BI.Msg.toast("Please Wait。", "warning"); + BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件 return false; } @@ -37695,9 +37696,9 @@ BI.TreeView = BI.inherit(BI.Pane, { function ajaxGetNodes (treeNode, reloadType) { var zTree = self.nodes; if (reloadType == "refresh") { - zTree.updateNode(treeNode); + zTree.updateNode(treeNode); // 刷新一下当前节点,如果treeNode.xxx被改了的话 } - zTree.reAsyncChildNodes(treeNode, reloadType, true); + zTree.reAsyncChildNodes(treeNode, reloadType, true); // 强制加载子节点,reloadType === refresh为先清空再加载,否则为追加到现有子节点之后 } function beforeCheck (treeId, treeNode) { @@ -37775,15 +37776,18 @@ BI.TreeView = BI.inherit(BI.Pane, { } 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; } + // 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况) var storeValues = BI.deepClone(this.options.paras.selectedValues); var treeNode = this._getTree(storeValues, path); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); }, + // 获取的是以values最后一个节点为根的子树 _getTree: function (map, values) { var cur = map; BI.any(values, function (i, value) { @@ -37795,6 +37799,7 @@ BI.TreeView = BI.inherit(BI.Pane, { return cur; }, + // 以values为path一路向里补充map, 并在末尾节点添加key: value节点 _addTreeNode: function (map, values, key, value) { var cur = map; BI.each(values, function (i, value) { @@ -37822,7 +37827,7 @@ BI.TreeView = BI.inherit(BI.Pane, { var self = this; var hashMap = {}; var rootNoots = this.nodes.getNodes(); - track(rootNoots); + track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点 function track (nodes) { BI.each(nodes, function (i, node) { var checkState = node.getCheckStatus(); @@ -38070,7 +38075,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { var self = this; var setting = { async: { - enable: false, + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 otherParam: BI.cjkEncodeDO(paras) }, check: { @@ -38160,6 +38165,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { return setting; }, + // 用来更新this.options.paras.selectedValues, 和ztree内部无关 _selectTreeNode: function (treeId, treeNode) { var self = this, o = this.options; var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); @@ -38205,7 +38211,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { function callback (nodes, hasNext) { self.nodes.addNodes(treeNode, nodes); - + // 展开节点是没有分页的 if (hasNext === true) { BI.delay(function () { times++; @@ -38222,6 +38228,9 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { } }, + // a,b 两棵树 + // a->b b->a 做两次校验, 构造一个校验后的map + // e.g. 以a为基准,如果b没有此节点,则在map中添加。 如b有,且是全选的, 则在map中构造全选(为什么不添加a的值呢? 因为这次是取并集), 如果b中也有和a一样的存值,就递归 _join: function (valueA, valueB) { var self = this; var map = {}; @@ -38316,6 +38325,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); } else { // 如果选中的值中不存在该值不处理 + // 因为反正是不选中,没必要管 var t = this.options.paras.selectedValues; var p = parentValues.concat(name); for (var i = 0, len = p.length; i < len; i++) { @@ -38323,6 +38333,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { if (t == null) { return; } + // 选中中国-江苏, 搜索南京,取消勾选 if (BI.isEmpty(t)) { break; } @@ -38386,9 +38397,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } var hasNext = !!d.hasNext, nodes = d.items || []; o.paras.lastSearchValue = d.lastSearchValue; - if (nodes.length > 0) { - callback(self._dealWidthNodes(nodes)); - } + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); self.setTipVisible(nodes.length <= 0); self.loaded(); if (!hasNext) { @@ -39294,7 +39304,8 @@ BI.Combo = BI.inherit(BI.Widget, { }, showView: function (e) { - if (this.isEnabled() && this.combo.isEnabled()) { + // 减少popup 调整宽高的次数 + if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) { this._popupView(e); } }, @@ -72892,6 +72903,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeInsertCombo + * @extends BI.Single + */ + +BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-insert-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || {}}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : {} + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: {}}; + } + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || {}; + this.combo.setValue({ + value: v || {} + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -73128,6 +73424,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, { BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchInsertPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { + + constants: { + height: 24, + }, + + props: { + baseCls: "bi-multi-tree-search-insert-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }, + + render: function () { + var self = this, opts = this.options; + + return { + type: "bi.vertical", + items: [{ + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + hgap: 5, + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } + }, { + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }] + }; + }, + + setKeyword: function (keyword, nodes) { + var isAddTipVisible = BI.isEmptyArray(nodes); + this.addTip.setVisible(isAddTipVisible); + this.partTree.setVisible(!isAddTipVisible); + isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; + +BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -83004,10 +83405,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); - 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]); + // 找不到就是新增值 + 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]); + } }); } @@ -83267,7 +83677,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; - var lastSearchValue = op.lastSearchValue || ""; + var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ @@ -83304,6 +83714,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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; } @@ -83433,6 +83852,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: state[1] }); } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + if (parentValues.length === 0 && times === 1) { + result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); + } BI.nextTick(function () { callback({ items: result, @@ -83499,6 +83922,22 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }, + _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++) { @@ -83585,6 +84024,59 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return this._getChildren(parentValues).length; } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.TreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_insert_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "TreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况 * * Created by GUY on 2015/10/29. diff --git a/dist/base.css b/dist/base.css index 5091d3fc2..edecdcf44 100644 --- a/dist/base.css +++ b/dist/base.css @@ -1423,7 +1423,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, opacity: 0; } .bi-checkbox.disabled.active .checkbox-content { - border-color: #e8eaed; + border-color: #d0d4da; } .bi-checkbox.disabled.active .checkbox-content:after { opacity: 1; @@ -1431,6 +1431,16 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-checkbox .checkbox-content { border-color: #9EA6B2; } +.bi-theme-dark .bi-checkbox.active .checkbox-content, +.bi-theme-dark .bi-checkbox:active .checkbox-content { + border-color: #3685f2; +} +.bi-theme-dark .bi-checkbox.disabled .checkbox-content { + background-color: #606479; +} +.bi-theme-dark .bi-checkbox.disabled.active .checkbox-content { + border-color: #606479; +} .bi-file { opacity: 0; filter: alpha(opacity=0); diff --git a/dist/base.js b/dist/base.js index a225544fc..d92486f83 100644 --- a/dist/base.js +++ b/dist/base.js @@ -1727,8 +1727,8 @@ BI.TreeView = BI.inherit(BI.Pane, { async: { enable: true, url: getUrl, - autoParam: ["id", "name"], - otherParam: BI.cjkEncodeDO(paras) + autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name + otherParam: BI.cjkEncodeDO(paras) // 静态参数 }, check: { enable: true @@ -1736,16 +1736,16 @@ BI.TreeView = BI.inherit(BI.Pane, { data: { key: { title: "title", - name: "text" + name: "text" // 节点的name属性替换成text }, simpleData: { - enable: true + enable: true // 可以穿id,pid属性的对象数组 } }, view: { showIcon: false, expandSpeed: "", - nameIsHTML: true, + nameIsHTML: true, // 节点可以用html标签代替 dblClickExpand: false }, callback: { @@ -1768,6 +1768,7 @@ BI.TreeView = BI.inherit(BI.Pane, { if(status.half === true && status.checked === true) { checked = false; } + // 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调 self.nodes.checkNode(treeNode, !checked, true, true); } @@ -1790,7 +1791,7 @@ BI.TreeView = BI.inherit(BI.Pane, { } return true; } - BI.Msg.toast("Please Wait。", "warning"); + BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件 return false; } @@ -1828,9 +1829,9 @@ BI.TreeView = BI.inherit(BI.Pane, { function ajaxGetNodes (treeNode, reloadType) { var zTree = self.nodes; if (reloadType == "refresh") { - zTree.updateNode(treeNode); + zTree.updateNode(treeNode); // 刷新一下当前节点,如果treeNode.xxx被改了的话 } - zTree.reAsyncChildNodes(treeNode, reloadType, true); + zTree.reAsyncChildNodes(treeNode, reloadType, true); // 强制加载子节点,reloadType === refresh为先清空再加载,否则为追加到现有子节点之后 } function beforeCheck (treeId, treeNode) { @@ -1908,15 +1909,18 @@ BI.TreeView = BI.inherit(BI.Pane, { } 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; } + // 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况) var storeValues = BI.deepClone(this.options.paras.selectedValues); var treeNode = this._getTree(storeValues, path); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); }, + // 获取的是以values最后一个节点为根的子树 _getTree: function (map, values) { var cur = map; BI.any(values, function (i, value) { @@ -1928,6 +1932,7 @@ BI.TreeView = BI.inherit(BI.Pane, { return cur; }, + // 以values为path一路向里补充map, 并在末尾节点添加key: value节点 _addTreeNode: function (map, values, key, value) { var cur = map; BI.each(values, function (i, value) { @@ -1955,7 +1960,7 @@ BI.TreeView = BI.inherit(BI.Pane, { var self = this; var hashMap = {}; var rootNoots = this.nodes.getNodes(); - track(rootNoots); + track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点 function track (nodes) { BI.each(nodes, function (i, node) { var checkState = node.getCheckStatus(); @@ -2203,7 +2208,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { var self = this; var setting = { async: { - enable: false, + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 otherParam: BI.cjkEncodeDO(paras) }, check: { @@ -2293,6 +2298,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { return setting; }, + // 用来更新this.options.paras.selectedValues, 和ztree内部无关 _selectTreeNode: function (treeId, treeNode) { var self = this, o = this.options; var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); @@ -2338,7 +2344,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { function callback (nodes, hasNext) { self.nodes.addNodes(treeNode, nodes); - + // 展开节点是没有分页的 if (hasNext === true) { BI.delay(function () { times++; @@ -2355,6 +2361,9 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { } }, + // a,b 两棵树 + // a->b b->a 做两次校验, 构造一个校验后的map + // e.g. 以a为基准,如果b没有此节点,则在map中添加。 如b有,且是全选的, 则在map中构造全选(为什么不添加a的值呢? 因为这次是取并集), 如果b中也有和a一样的存值,就递归 _join: function (valueA, valueB) { var self = this; var map = {}; @@ -2449,6 +2458,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); } else { // 如果选中的值中不存在该值不处理 + // 因为反正是不选中,没必要管 var t = this.options.paras.selectedValues; var p = parentValues.concat(name); for (var i = 0, len = p.length; i < len; i++) { @@ -2456,6 +2466,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { if (t == null) { return; } + // 选中中国-江苏, 搜索南京,取消勾选 if (BI.isEmpty(t)) { break; } @@ -2519,9 +2530,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } var hasNext = !!d.hasNext, nodes = d.items || []; o.paras.lastSearchValue = d.lastSearchValue; - if (nodes.length > 0) { - callback(self._dealWidthNodes(nodes)); - } + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); self.setTipVisible(nodes.length <= 0); self.loaded(); if (!hasNext) { @@ -3427,7 +3437,8 @@ BI.Combo = BI.inherit(BI.Widget, { }, showView: function (e) { - if (this.isEnabled() && this.combo.isEnabled()) { + // 减少popup 调整宽高的次数 + if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) { this._popupView(e); } }, @@ -6149,7 +6160,7 @@ BI.PopupView = BI.inherit(BI.Widget, { var tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0, tabHeight = this.tab ? (this.tab.attr("height") || 24) : 0, toolHeight = ((this.tool && this.tool.attr("height")) || 24) * ((this.tool && this.tool.isVisible()) ? 1 : 0); - var resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVGap - 2; + var resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVGap; this.view.resetHeight ? this.view.resetHeight(resetHeight) : this.view.element.css({"max-height": resetHeight + "px"}); }, @@ -10067,8 +10078,10 @@ BI.Input = BI.inherit(BI.Single, { }) .on("input propertychange", function (e) { // 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了 - // 这个事件在input的属性发生改变的时候就会触发(class的变化也算) - if (BI.isNotNull(keyCode)) { + // 其中propertychange在元素属性发生改变的时候就会触发 是为了兼容IE8 + // 通过keyCode判断会漏掉输入法点击输入(右键粘贴暂缓) + var originalEvent = e.originalEvent; + if (BI.isNull(originalEvent.propertyName) || originalEvent.propertyName === "value") { keyCode = null; inputEventValid = true; self._keydown_ = true; diff --git a/dist/bundle.css b/dist/bundle.css index 214c1b104..d03531953 100644 --- a/dist/bundle.css +++ b/dist/bundle.css @@ -3579,7 +3579,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, opacity: 0; } .bi-checkbox.disabled.active .checkbox-content { - border-color: #e8eaed; + border-color: #d0d4da; } .bi-checkbox.disabled.active .checkbox-content:after { opacity: 1; @@ -3587,6 +3587,16 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-checkbox .checkbox-content { border-color: #9EA6B2; } +.bi-theme-dark .bi-checkbox.active .checkbox-content, +.bi-theme-dark .bi-checkbox:active .checkbox-content { + border-color: #3685f2; +} +.bi-theme-dark .bi-checkbox.disabled .checkbox-content { + background-color: #606479; +} +.bi-theme-dark .bi-checkbox.disabled.active .checkbox-content { + border-color: #606479; +} .bi-file { opacity: 0; filter: alpha(opacity=0); diff --git a/dist/bundle.ie.js b/dist/bundle.ie.js index 19230dd03..4ec7479be 100644 --- a/dist/bundle.ie.js +++ b/dist/bundle.ie.js @@ -37190,8 +37190,8 @@ BI.TreeView = BI.inherit(BI.Pane, { async: { enable: true, url: getUrl, - autoParam: ["id", "name"], - otherParam: BI.cjkEncodeDO(paras) + autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name + otherParam: BI.cjkEncodeDO(paras) // 静态参数 }, check: { enable: true @@ -37199,16 +37199,16 @@ BI.TreeView = BI.inherit(BI.Pane, { data: { key: { title: "title", - name: "text" + name: "text" // 节点的name属性替换成text }, simpleData: { - enable: true + enable: true // 可以穿id,pid属性的对象数组 } }, view: { showIcon: false, expandSpeed: "", - nameIsHTML: true, + nameIsHTML: true, // 节点可以用html标签代替 dblClickExpand: false }, callback: { @@ -37231,6 +37231,7 @@ BI.TreeView = BI.inherit(BI.Pane, { if(status.half === true && status.checked === true) { checked = false; } + // 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调 self.nodes.checkNode(treeNode, !checked, true, true); } @@ -37253,7 +37254,7 @@ BI.TreeView = BI.inherit(BI.Pane, { } return true; } - BI.Msg.toast("Please Wait。", "warning"); + BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件 return false; } @@ -37291,9 +37292,9 @@ BI.TreeView = BI.inherit(BI.Pane, { function ajaxGetNodes (treeNode, reloadType) { var zTree = self.nodes; if (reloadType == "refresh") { - zTree.updateNode(treeNode); + zTree.updateNode(treeNode); // 刷新一下当前节点,如果treeNode.xxx被改了的话 } - zTree.reAsyncChildNodes(treeNode, reloadType, true); + zTree.reAsyncChildNodes(treeNode, reloadType, true); // 强制加载子节点,reloadType === refresh为先清空再加载,否则为追加到现有子节点之后 } function beforeCheck (treeId, treeNode) { @@ -37371,15 +37372,18 @@ BI.TreeView = BI.inherit(BI.Pane, { } 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; } + // 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况) var storeValues = BI.deepClone(this.options.paras.selectedValues); var treeNode = this._getTree(storeValues, path); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); }, + // 获取的是以values最后一个节点为根的子树 _getTree: function (map, values) { var cur = map; BI.any(values, function (i, value) { @@ -37391,6 +37395,7 @@ BI.TreeView = BI.inherit(BI.Pane, { return cur; }, + // 以values为path一路向里补充map, 并在末尾节点添加key: value节点 _addTreeNode: function (map, values, key, value) { var cur = map; BI.each(values, function (i, value) { @@ -37418,7 +37423,7 @@ BI.TreeView = BI.inherit(BI.Pane, { var self = this; var hashMap = {}; var rootNoots = this.nodes.getNodes(); - track(rootNoots); + track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点 function track (nodes) { BI.each(nodes, function (i, node) { var checkState = node.getCheckStatus(); @@ -37666,7 +37671,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { var self = this; var setting = { async: { - enable: false, + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 otherParam: BI.cjkEncodeDO(paras) }, check: { @@ -37756,6 +37761,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { return setting; }, + // 用来更新this.options.paras.selectedValues, 和ztree内部无关 _selectTreeNode: function (treeId, treeNode) { var self = this, o = this.options; var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); @@ -37801,7 +37807,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { function callback (nodes, hasNext) { self.nodes.addNodes(treeNode, nodes); - + // 展开节点是没有分页的 if (hasNext === true) { BI.delay(function () { times++; @@ -37818,6 +37824,9 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { } }, + // a,b 两棵树 + // a->b b->a 做两次校验, 构造一个校验后的map + // e.g. 以a为基准,如果b没有此节点,则在map中添加。 如b有,且是全选的, 则在map中构造全选(为什么不添加a的值呢? 因为这次是取并集), 如果b中也有和a一样的存值,就递归 _join: function (valueA, valueB) { var self = this; var map = {}; @@ -37912,6 +37921,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); } else { // 如果选中的值中不存在该值不处理 + // 因为反正是不选中,没必要管 var t = this.options.paras.selectedValues; var p = parentValues.concat(name); for (var i = 0, len = p.length; i < len; i++) { @@ -37919,6 +37929,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { if (t == null) { return; } + // 选中中国-江苏, 搜索南京,取消勾选 if (BI.isEmpty(t)) { break; } @@ -37982,9 +37993,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } var hasNext = !!d.hasNext, nodes = d.items || []; o.paras.lastSearchValue = d.lastSearchValue; - if (nodes.length > 0) { - callback(self._dealWidthNodes(nodes)); - } + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); self.setTipVisible(nodes.length <= 0); self.loaded(); if (!hasNext) { @@ -38890,7 +38900,8 @@ BI.Combo = BI.inherit(BI.Widget, { }, showView: function (e) { - if (this.isEnabled() && this.combo.isEnabled()) { + // 减少popup 调整宽高的次数 + if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) { this._popupView(e); } }, @@ -72488,6 +72499,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeInsertCombo + * @extends BI.Single + */ + +BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-insert-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || {}}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : {} + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: {}}; + } + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || {}; + this.combo.setValue({ + value: v || {} + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -72724,6 +73020,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, { BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchInsertPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { + + constants: { + height: 24, + }, + + props: { + baseCls: "bi-multi-tree-search-insert-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }, + + render: function () { + var self = this, opts = this.options; + + return { + type: "bi.vertical", + items: [{ + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + hgap: 5, + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } + }, { + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }] + }; + }, + + setKeyword: function (keyword, nodes) { + var isAddTipVisible = BI.isEmptyArray(nodes); + this.addTip.setVisible(isAddTipVisible); + this.partTree.setVisible(!isAddTipVisible); + isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; + +BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -82600,10 +83001,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); - 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]); + // 找不到就是新增值 + 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]); + } }); } @@ -82863,7 +83273,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; - var lastSearchValue = op.lastSearchValue || ""; + var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ @@ -82900,6 +83310,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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; } @@ -83029,6 +83448,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: state[1] }); } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + if (parentValues.length === 0 && times === 1) { + result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); + } BI.nextTick(function () { callback({ items: result, @@ -83095,6 +83518,22 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }, + _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++) { @@ -83181,6 +83620,59 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return this._getChildren(parentValues).length; } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.TreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_insert_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "TreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况 * * Created by GUY on 2015/10/29. diff --git a/dist/bundle.js b/dist/bundle.js index 73e1d82c0..f75e83c0c 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -37594,8 +37594,8 @@ BI.TreeView = BI.inherit(BI.Pane, { async: { enable: true, url: getUrl, - autoParam: ["id", "name"], - otherParam: BI.cjkEncodeDO(paras) + autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name + otherParam: BI.cjkEncodeDO(paras) // 静态参数 }, check: { enable: true @@ -37603,16 +37603,16 @@ BI.TreeView = BI.inherit(BI.Pane, { data: { key: { title: "title", - name: "text" + name: "text" // 节点的name属性替换成text }, simpleData: { - enable: true + enable: true // 可以穿id,pid属性的对象数组 } }, view: { showIcon: false, expandSpeed: "", - nameIsHTML: true, + nameIsHTML: true, // 节点可以用html标签代替 dblClickExpand: false }, callback: { @@ -37635,6 +37635,7 @@ BI.TreeView = BI.inherit(BI.Pane, { if(status.half === true && status.checked === true) { checked = false; } + // 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调 self.nodes.checkNode(treeNode, !checked, true, true); } @@ -37657,7 +37658,7 @@ BI.TreeView = BI.inherit(BI.Pane, { } return true; } - BI.Msg.toast("Please Wait。", "warning"); + BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件 return false; } @@ -37695,9 +37696,9 @@ BI.TreeView = BI.inherit(BI.Pane, { function ajaxGetNodes (treeNode, reloadType) { var zTree = self.nodes; if (reloadType == "refresh") { - zTree.updateNode(treeNode); + zTree.updateNode(treeNode); // 刷新一下当前节点,如果treeNode.xxx被改了的话 } - zTree.reAsyncChildNodes(treeNode, reloadType, true); + zTree.reAsyncChildNodes(treeNode, reloadType, true); // 强制加载子节点,reloadType === refresh为先清空再加载,否则为追加到现有子节点之后 } function beforeCheck (treeId, treeNode) { @@ -37775,15 +37776,18 @@ BI.TreeView = BI.inherit(BI.Pane, { } 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; } + // 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况) var storeValues = BI.deepClone(this.options.paras.selectedValues); var treeNode = this._getTree(storeValues, path); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); }, + // 获取的是以values最后一个节点为根的子树 _getTree: function (map, values) { var cur = map; BI.any(values, function (i, value) { @@ -37795,6 +37799,7 @@ BI.TreeView = BI.inherit(BI.Pane, { return cur; }, + // 以values为path一路向里补充map, 并在末尾节点添加key: value节点 _addTreeNode: function (map, values, key, value) { var cur = map; BI.each(values, function (i, value) { @@ -37822,7 +37827,7 @@ BI.TreeView = BI.inherit(BI.Pane, { var self = this; var hashMap = {}; var rootNoots = this.nodes.getNodes(); - track(rootNoots); + track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点 function track (nodes) { BI.each(nodes, function (i, node) { var checkState = node.getCheckStatus(); @@ -38070,7 +38075,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { var self = this; var setting = { async: { - enable: false, + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 otherParam: BI.cjkEncodeDO(paras) }, check: { @@ -38160,6 +38165,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { return setting; }, + // 用来更新this.options.paras.selectedValues, 和ztree内部无关 _selectTreeNode: function (treeId, treeNode) { var self = this, o = this.options; var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); @@ -38205,7 +38211,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { function callback (nodes, hasNext) { self.nodes.addNodes(treeNode, nodes); - + // 展开节点是没有分页的 if (hasNext === true) { BI.delay(function () { times++; @@ -38222,6 +38228,9 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { } }, + // a,b 两棵树 + // a->b b->a 做两次校验, 构造一个校验后的map + // e.g. 以a为基准,如果b没有此节点,则在map中添加。 如b有,且是全选的, 则在map中构造全选(为什么不添加a的值呢? 因为这次是取并集), 如果b中也有和a一样的存值,就递归 _join: function (valueA, valueB) { var self = this; var map = {}; @@ -38316,6 +38325,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); } else { // 如果选中的值中不存在该值不处理 + // 因为反正是不选中,没必要管 var t = this.options.paras.selectedValues; var p = parentValues.concat(name); for (var i = 0, len = p.length; i < len; i++) { @@ -38323,6 +38333,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { if (t == null) { return; } + // 选中中国-江苏, 搜索南京,取消勾选 if (BI.isEmpty(t)) { break; } @@ -38386,9 +38397,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } var hasNext = !!d.hasNext, nodes = d.items || []; o.paras.lastSearchValue = d.lastSearchValue; - if (nodes.length > 0) { - callback(self._dealWidthNodes(nodes)); - } + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); self.setTipVisible(nodes.length <= 0); self.loaded(); if (!hasNext) { @@ -39294,7 +39304,8 @@ BI.Combo = BI.inherit(BI.Widget, { }, showView: function (e) { - if (this.isEnabled() && this.combo.isEnabled()) { + // 减少popup 调整宽高的次数 + if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) { this._popupView(e); } }, @@ -72892,6 +72903,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeInsertCombo + * @extends BI.Single + */ + +BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-insert-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || {}}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : {} + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: {}}; + } + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || {}; + this.combo.setValue({ + value: v || {} + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -73128,6 +73424,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, { BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchInsertPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { + + constants: { + height: 24, + }, + + props: { + baseCls: "bi-multi-tree-search-insert-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }, + + render: function () { + var self = this, opts = this.options; + + return { + type: "bi.vertical", + items: [{ + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + hgap: 5, + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } + }, { + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }] + }; + }, + + setKeyword: function (keyword, nodes) { + var isAddTipVisible = BI.isEmptyArray(nodes); + this.addTip.setVisible(isAddTipVisible); + this.partTree.setVisible(!isAddTipVisible); + isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; + +BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -83004,10 +83405,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); - 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]); + // 找不到就是新增值 + 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]); + } }); } @@ -83267,7 +83677,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; - var lastSearchValue = op.lastSearchValue || ""; + var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ @@ -83304,6 +83714,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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; } @@ -83433,6 +83852,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: state[1] }); } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + if (parentValues.length === 0 && times === 1) { + result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); + } BI.nextTick(function () { callback({ items: result, @@ -83499,6 +83922,22 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }, + _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++) { @@ -83585,6 +84024,59 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return this._getChildren(parentValues).length; } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.TreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_insert_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "TreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况 * * Created by GUY on 2015/10/29. diff --git a/dist/core.js b/dist/core.js index 180ca9565..233b3cd61 100644 --- a/dist/core.js +++ b/dist/core.js @@ -19976,7 +19976,7 @@ BI.prepares.push(function () { var i, direct; var leftRight = [], topBottom = []; var isNeedAdaptHeight = false, tbFirst = false, lrFirst = false; - var left, top, pos; + var left, top, pos, firstDir = directions[0]; for (i = 0; i < directions.length; i++) { direct = directions[i]; switch (direct) { @@ -20086,39 +20086,45 @@ BI.prepares.push(function () { } } + // 此处为四个方向放不下时挑空间最大的方向去放置, 也就是说我设置了弹出方向为"bottom,left", + // 最后发现实际弹出方向可能是"top,left",那么此时外界获取popup的方向应该是"top,left" switch (directions[0]) { case "left": case "right": if (BI.DOM.isRightSpaceLarger(combo)) { left = BI.DOM.getRightAdaptPosition(combo, popup, extraWidth).left; + firstDir = "right"; } else { left = BI.DOM.getLeftAdaptPosition(combo, popup, extraWidth).left; + firstDir = "left"; } if (topBottom[0] === "bottom") { pos = BI.DOM.getTopAlignPosition(combo, popup, extraHeight, needAdaptHeight); pos.left = left; - pos.dir = directions[0] + ",bottom"; + pos.dir = firstDir + ",bottom"; return pos; } pos = BI.DOM.getBottomAlignPosition(combo, popup, extraHeight, needAdaptHeight); pos.left = left; - pos.dir = directions[0] + ",top"; + pos.dir = firstDir + ",top"; return pos; default : if (BI.DOM.isBottomSpaceLarger(combo)) { pos = BI.DOM.getBottomAdaptPosition(combo, popup, extraHeight, needAdaptHeight); + firstDir = "bottom"; } else { pos = BI.DOM.getTopAdaptPosition(combo, popup, extraHeight, needAdaptHeight); + firstDir = "top"; } if (leftRight[0] === "right") { left = BI.DOM.getLeftAlignPosition(combo, popup, extraWidth, needAdaptHeight).left; pos.left = left; - pos.dir = directions[0] + ",right"; + pos.dir = firstDir + ",right"; return pos; } left = BI.DOM.getRightAlignPosition(combo, popup, extraWidth).left; pos.left = left; - pos.dir = directions[0] + ",left"; + pos.dir = firstDir + ",left"; return pos; } }, diff --git a/dist/demo.js b/dist/demo.js index 3e07f8eac..910eb5bcc 100644 --- a/dist/demo.js +++ b/dist/demo.js @@ -2700,7 +2700,7 @@ BI.shortcut("demo.center", Demo.Center);Demo.TreeValueChooser = BI.inherit(BI.Wi render: function () { var widget = BI.createWidget({ - type: "bi.tree_value_chooser_combo", + type: "bi.tree_value_chooser_insert_combo", width: 300, // items: BI.deepClone(Demo.CONSTANTS.TREEITEMS), itemsCreator: function (op, callback) { diff --git a/dist/fineui.css b/dist/fineui.css index 8f968e822..1c296a696 100644 --- a/dist/fineui.css +++ b/dist/fineui.css @@ -3572,12 +3572,14 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, border-color: #ffffff; opacity: 1; } +.bi-checkbox.disabled .checkbox-content { + background-color: #d0d4da; +} .bi-checkbox.disabled .checkbox-content:after { opacity: 0; } .bi-checkbox.disabled.active .checkbox-content { - border-color: #e8eaed; - background-color: #d0d4da; + border-color: #d0d4da; } .bi-checkbox.disabled.active .checkbox-content:after { opacity: 1; @@ -3585,6 +3587,16 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-checkbox .checkbox-content { border-color: #9EA6B2; } +.bi-theme-dark .bi-checkbox.active .checkbox-content, +.bi-theme-dark .bi-checkbox:active .checkbox-content { + border-color: #3685f2; +} +.bi-theme-dark .bi-checkbox.disabled .checkbox-content { + background-color: #606479; +} +.bi-theme-dark .bi-checkbox.disabled.active .checkbox-content { + border-color: #606479; +} .bi-file { opacity: 0; filter: alpha(opacity=0); diff --git a/dist/fineui.ie.js b/dist/fineui.ie.js index e9fee8755..af5c350f2 100644 --- a/dist/fineui.ie.js +++ b/dist/fineui.ie.js @@ -37435,8 +37435,8 @@ BI.TreeView = BI.inherit(BI.Pane, { async: { enable: true, url: getUrl, - autoParam: ["id", "name"], - otherParam: BI.cjkEncodeDO(paras) + autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name + otherParam: BI.cjkEncodeDO(paras) // 静态参数 }, check: { enable: true @@ -37444,16 +37444,16 @@ BI.TreeView = BI.inherit(BI.Pane, { data: { key: { title: "title", - name: "text" + name: "text" // 节点的name属性替换成text }, simpleData: { - enable: true + enable: true // 可以穿id,pid属性的对象数组 } }, view: { showIcon: false, expandSpeed: "", - nameIsHTML: true, + nameIsHTML: true, // 节点可以用html标签代替 dblClickExpand: false }, callback: { @@ -37476,6 +37476,7 @@ BI.TreeView = BI.inherit(BI.Pane, { if(status.half === true && status.checked === true) { checked = false; } + // 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调 self.nodes.checkNode(treeNode, !checked, true, true); } @@ -37498,7 +37499,7 @@ BI.TreeView = BI.inherit(BI.Pane, { } return true; } - BI.Msg.toast("Please Wait。", "warning"); + BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件 return false; } @@ -37536,9 +37537,9 @@ BI.TreeView = BI.inherit(BI.Pane, { function ajaxGetNodes (treeNode, reloadType) { var zTree = self.nodes; if (reloadType == "refresh") { - zTree.updateNode(treeNode); + zTree.updateNode(treeNode); // 刷新一下当前节点,如果treeNode.xxx被改了的话 } - zTree.reAsyncChildNodes(treeNode, reloadType, true); + zTree.reAsyncChildNodes(treeNode, reloadType, true); // 强制加载子节点,reloadType === refresh为先清空再加载,否则为追加到现有子节点之后 } function beforeCheck (treeId, treeNode) { @@ -37616,15 +37617,18 @@ BI.TreeView = BI.inherit(BI.Pane, { } 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; } + // 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况) var storeValues = BI.deepClone(this.options.paras.selectedValues); var treeNode = this._getTree(storeValues, path); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); }, + // 获取的是以values最后一个节点为根的子树 _getTree: function (map, values) { var cur = map; BI.any(values, function (i, value) { @@ -37636,6 +37640,7 @@ BI.TreeView = BI.inherit(BI.Pane, { return cur; }, + // 以values为path一路向里补充map, 并在末尾节点添加key: value节点 _addTreeNode: function (map, values, key, value) { var cur = map; BI.each(values, function (i, value) { @@ -37663,7 +37668,7 @@ BI.TreeView = BI.inherit(BI.Pane, { var self = this; var hashMap = {}; var rootNoots = this.nodes.getNodes(); - track(rootNoots); + track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点 function track (nodes) { BI.each(nodes, function (i, node) { var checkState = node.getCheckStatus(); @@ -37911,7 +37916,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { var self = this; var setting = { async: { - enable: false, + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 otherParam: BI.cjkEncodeDO(paras) }, check: { @@ -38001,6 +38006,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { return setting; }, + // 用来更新this.options.paras.selectedValues, 和ztree内部无关 _selectTreeNode: function (treeId, treeNode) { var self = this, o = this.options; var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); @@ -38046,7 +38052,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { function callback (nodes, hasNext) { self.nodes.addNodes(treeNode, nodes); - + // 展开节点是没有分页的 if (hasNext === true) { BI.delay(function () { times++; @@ -38063,6 +38069,9 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { } }, + // a,b 两棵树 + // a->b b->a 做两次校验, 构造一个校验后的map + // e.g. 以a为基准,如果b没有此节点,则在map中添加。 如b有,且是全选的, 则在map中构造全选(为什么不添加a的值呢? 因为这次是取并集), 如果b中也有和a一样的存值,就递归 _join: function (valueA, valueB) { var self = this; var map = {}; @@ -38157,6 +38166,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); } else { // 如果选中的值中不存在该值不处理 + // 因为反正是不选中,没必要管 var t = this.options.paras.selectedValues; var p = parentValues.concat(name); for (var i = 0, len = p.length; i < len; i++) { @@ -38164,6 +38174,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { if (t == null) { return; } + // 选中中国-江苏, 搜索南京,取消勾选 if (BI.isEmpty(t)) { break; } @@ -38227,9 +38238,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } var hasNext = !!d.hasNext, nodes = d.items || []; o.paras.lastSearchValue = d.lastSearchValue; - if (nodes.length > 0) { - callback(self._dealWidthNodes(nodes)); - } + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); self.setTipVisible(nodes.length <= 0); self.loaded(); if (!hasNext) { @@ -39135,7 +39145,8 @@ BI.Combo = BI.inherit(BI.Widget, { }, showView: function (e) { - if (this.isEnabled() && this.combo.isEnabled()) { + // 减少popup 调整宽高的次数 + if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) { this._popupView(e); } }, @@ -72733,6 +72744,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeInsertCombo + * @extends BI.Single + */ + +BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-insert-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || {}}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : {} + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: {}}; + } + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || {}; + this.combo.setValue({ + value: v || {} + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -72969,6 +73265,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, { BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchInsertPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { + + constants: { + height: 24, + }, + + props: { + baseCls: "bi-multi-tree-search-insert-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }, + + render: function () { + var self = this, opts = this.options; + + return { + type: "bi.vertical", + items: [{ + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + hgap: 5, + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } + }, { + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }] + }; + }, + + setKeyword: function (keyword, nodes) { + var isAddTipVisible = BI.isEmptyArray(nodes); + this.addTip.setVisible(isAddTipVisible); + this.partTree.setVisible(!isAddTipVisible); + isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; + +BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -82845,10 +83246,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); - 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]); + // 找不到就是新增值 + 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]); + } }); } @@ -83108,7 +83518,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; - var lastSearchValue = op.lastSearchValue || ""; + var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ @@ -83145,6 +83555,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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; } @@ -83274,6 +83693,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: state[1] }); } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + if (parentValues.length === 0 && times === 1) { + result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); + } BI.nextTick(function () { callback({ items: result, @@ -83340,6 +83763,22 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }, + _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++) { @@ -83426,6 +83865,59 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return this._getChildren(parentValues).length; } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.TreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_insert_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "TreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况 * * Created by GUY on 2015/10/29. diff --git a/dist/fineui.js b/dist/fineui.js index a3981e4d9..e49d3e252 100644 --- a/dist/fineui.js +++ b/dist/fineui.js @@ -37839,8 +37839,8 @@ BI.TreeView = BI.inherit(BI.Pane, { async: { enable: true, url: getUrl, - autoParam: ["id", "name"], - otherParam: BI.cjkEncodeDO(paras) + autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name + otherParam: BI.cjkEncodeDO(paras) // 静态参数 }, check: { enable: true @@ -37848,16 +37848,16 @@ BI.TreeView = BI.inherit(BI.Pane, { data: { key: { title: "title", - name: "text" + name: "text" // 节点的name属性替换成text }, simpleData: { - enable: true + enable: true // 可以穿id,pid属性的对象数组 } }, view: { showIcon: false, expandSpeed: "", - nameIsHTML: true, + nameIsHTML: true, // 节点可以用html标签代替 dblClickExpand: false }, callback: { @@ -37880,6 +37880,7 @@ BI.TreeView = BI.inherit(BI.Pane, { if(status.half === true && status.checked === true) { checked = false; } + // 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调 self.nodes.checkNode(treeNode, !checked, true, true); } @@ -37902,7 +37903,7 @@ BI.TreeView = BI.inherit(BI.Pane, { } return true; } - BI.Msg.toast("Please Wait。", "warning"); + BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件 return false; } @@ -37940,9 +37941,9 @@ BI.TreeView = BI.inherit(BI.Pane, { function ajaxGetNodes (treeNode, reloadType) { var zTree = self.nodes; if (reloadType == "refresh") { - zTree.updateNode(treeNode); + zTree.updateNode(treeNode); // 刷新一下当前节点,如果treeNode.xxx被改了的话 } - zTree.reAsyncChildNodes(treeNode, reloadType, true); + zTree.reAsyncChildNodes(treeNode, reloadType, true); // 强制加载子节点,reloadType === refresh为先清空再加载,否则为追加到现有子节点之后 } function beforeCheck (treeId, treeNode) { @@ -38020,15 +38021,18 @@ BI.TreeView = BI.inherit(BI.Pane, { } 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; } + // 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况) var storeValues = BI.deepClone(this.options.paras.selectedValues); var treeNode = this._getTree(storeValues, path); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); }, + // 获取的是以values最后一个节点为根的子树 _getTree: function (map, values) { var cur = map; BI.any(values, function (i, value) { @@ -38040,6 +38044,7 @@ BI.TreeView = BI.inherit(BI.Pane, { return cur; }, + // 以values为path一路向里补充map, 并在末尾节点添加key: value节点 _addTreeNode: function (map, values, key, value) { var cur = map; BI.each(values, function (i, value) { @@ -38067,7 +38072,7 @@ BI.TreeView = BI.inherit(BI.Pane, { var self = this; var hashMap = {}; var rootNoots = this.nodes.getNodes(); - track(rootNoots); + track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点 function track (nodes) { BI.each(nodes, function (i, node) { var checkState = node.getCheckStatus(); @@ -38315,7 +38320,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { var self = this; var setting = { async: { - enable: false, + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 otherParam: BI.cjkEncodeDO(paras) }, check: { @@ -38405,6 +38410,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { return setting; }, + // 用来更新this.options.paras.selectedValues, 和ztree内部无关 _selectTreeNode: function (treeId, treeNode) { var self = this, o = this.options; var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); @@ -38450,7 +38456,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { function callback (nodes, hasNext) { self.nodes.addNodes(treeNode, nodes); - + // 展开节点是没有分页的 if (hasNext === true) { BI.delay(function () { times++; @@ -38467,6 +38473,9 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { } }, + // a,b 两棵树 + // a->b b->a 做两次校验, 构造一个校验后的map + // e.g. 以a为基准,如果b没有此节点,则在map中添加。 如b有,且是全选的, 则在map中构造全选(为什么不添加a的值呢? 因为这次是取并集), 如果b中也有和a一样的存值,就递归 _join: function (valueA, valueB) { var self = this; var map = {}; @@ -38561,6 +38570,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); } else { // 如果选中的值中不存在该值不处理 + // 因为反正是不选中,没必要管 var t = this.options.paras.selectedValues; var p = parentValues.concat(name); for (var i = 0, len = p.length; i < len; i++) { @@ -38568,6 +38578,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { if (t == null) { return; } + // 选中中国-江苏, 搜索南京,取消勾选 if (BI.isEmpty(t)) { break; } @@ -38631,9 +38642,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } var hasNext = !!d.hasNext, nodes = d.items || []; o.paras.lastSearchValue = d.lastSearchValue; - if (nodes.length > 0) { - callback(self._dealWidthNodes(nodes)); - } + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); self.setTipVisible(nodes.length <= 0); self.loaded(); if (!hasNext) { @@ -39539,7 +39549,8 @@ BI.Combo = BI.inherit(BI.Widget, { }, showView: function (e) { - if (this.isEnabled() && this.combo.isEnabled()) { + // 减少popup 调整宽高的次数 + if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) { this._popupView(e); } }, @@ -73137,6 +73148,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeInsertCombo + * @extends BI.Single + */ + +BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-insert-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || {}}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : {} + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: {}}; + } + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || {}; + this.combo.setValue({ + value: v || {} + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -73373,6 +73669,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, { BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchInsertPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { + + constants: { + height: 24, + }, + + props: { + baseCls: "bi-multi-tree-search-insert-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }, + + render: function () { + var self = this, opts = this.options; + + return { + type: "bi.vertical", + items: [{ + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + hgap: 5, + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } + }, { + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }] + }; + }, + + setKeyword: function (keyword, nodes) { + var isAddTipVisible = BI.isEmptyArray(nodes); + this.addTip.setVisible(isAddTipVisible); + this.partTree.setVisible(!isAddTipVisible); + isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; + +BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -83249,10 +83650,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); - 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]); + // 找不到就是新增值 + 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]); + } }); } @@ -83512,7 +83922,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; - var lastSearchValue = op.lastSearchValue || ""; + var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ @@ -83549,6 +83959,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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; } @@ -83678,6 +84097,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: state[1] }); } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + if (parentValues.length === 0 && times === 1) { + result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); + } BI.nextTick(function () { callback({ items: result, @@ -83744,6 +84167,22 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }, + _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++) { @@ -83830,6 +84269,59 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return this._getChildren(parentValues).length; } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.TreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_insert_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "TreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况 * * Created by GUY on 2015/10/29. diff --git a/dist/fineui_without_jquery_polyfill.js b/dist/fineui_without_jquery_polyfill.js index c7a9f4297..12a530339 100644 --- a/dist/fineui_without_jquery_polyfill.js +++ b/dist/fineui_without_jquery_polyfill.js @@ -27057,7 +27057,8 @@ BI.Combo = BI.inherit(BI.Widget, { }, showView: function (e) { - if (this.isEnabled() && this.combo.isEnabled()) { + // 减少popup 调整宽高的次数 + if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) { this._popupView(e); } }, @@ -29779,7 +29780,7 @@ BI.PopupView = BI.inherit(BI.Widget, { var tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0, tabHeight = this.tab ? (this.tab.attr("height") || 24) : 0, toolHeight = ((this.tool && this.tool.attr("height")) || 24) * ((this.tool && this.tool.isVisible()) ? 1 : 0); - var resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVGap - 2; + var resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVGap; this.view.resetHeight ? this.view.resetHeight(resetHeight) : this.view.element.css({"max-height": resetHeight + "px"}); }, @@ -33072,8 +33073,10 @@ BI.Input = BI.inherit(BI.Single, { }) .on("input propertychange", function (e) { // 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了 - // 这个事件在input的属性发生改变的时候就会触发(class的变化也算) - if (BI.isNotNull(keyCode)) { + // 其中propertychange在元素属性发生改变的时候就会触发 是为了兼容IE8 + // 通过keyCode判断会漏掉输入法点击输入(右键粘贴暂缓) + var originalEvent = e.originalEvent; + if (BI.isNull(originalEvent.propertyName) || originalEvent.propertyName === "value") { keyCode = null; inputEventValid = true; self._keydown_ = true; @@ -55945,6 +55948,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeInsertCombo + * @extends BI.Single + */ + +BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-insert-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || {}}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : {} + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: {}}; + } + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || {}; + this.combo.setValue({ + value: v || {} + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -56181,6 +56469,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, { BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchInsertPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { + + constants: { + height: 24, + }, + + props: { + baseCls: "bi-multi-tree-search-insert-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }, + + render: function () { + var self = this, opts = this.options; + + return { + type: "bi.vertical", + items: [{ + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + hgap: 5, + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } + }, { + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }] + }; + }, + + setKeyword: function (keyword, nodes) { + var isAddTipVisible = BI.isEmptyArray(nodes); + this.addTip.setVisible(isAddTipVisible); + this.partTree.setVisible(!isAddTipVisible); + isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; + +BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -66057,10 +66450,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); - 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]); + // 找不到就是新增值 + 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]); + } }); } @@ -66320,7 +66722,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; - var lastSearchValue = op.lastSearchValue || ""; + var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ @@ -66357,6 +66759,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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; } @@ -66486,6 +66897,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: state[1] }); } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + if (parentValues.length === 0 && times === 1) { + result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); + } BI.nextTick(function () { callback({ items: result, @@ -66552,6 +66967,22 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }, + _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++) { @@ -66638,6 +67069,59 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return this._getChildren(parentValues).length; } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.TreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_insert_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "TreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况 * * Created by GUY on 2015/10/29. diff --git a/dist/widget.js b/dist/widget.js index 0b623837d..a45f95b02 100644 --- a/dist/widget.js +++ b/dist/widget.js @@ -12952,6 +12952,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, { BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeInsertCombo + * @extends BI.Single + */ + +BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-insert-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || {}}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : {} + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: {}}; + } + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || {}; + this.combo.setValue({ + value: v || {} + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -13188,6 +13473,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, { BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchInsertPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { + + constants: { + height: 24, + }, + + props: { + baseCls: "bi-multi-tree-search-insert-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }, + + render: function () { + var self = this, opts = this.options; + + return { + type: "bi.vertical", + items: [{ + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + hgap: 5, + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } + }, { + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }] + }; + }, + + setKeyword: function (keyword, nodes) { + var isAddTipVisible = BI.isEmptyArray(nodes); + this.addTip.setVisible(isAddTipVisible); + this.partTree.setVisible(!isAddTipVisible); + isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; + +BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -23064,10 +23454,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); - 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]); + // 找不到就是新增值 + 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]); + } }); } @@ -23327,7 +23726,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; - var lastSearchValue = op.lastSearchValue || ""; + var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ @@ -23364,6 +23763,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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; } @@ -23493,6 +23901,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: state[1] }); } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + if (parentValues.length === 0 && times === 1) { + result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); + } BI.nextTick(function () { callback({ items: result, @@ -23559,6 +23971,22 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }, + _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++) { @@ -23645,6 +24073,59 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return this._getChildren(parentValues).length; } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.TreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_insert_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "TreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况 * * Created by GUY on 2015/10/29. diff --git a/src/base/tree/ztree/asynctree.js b/src/base/tree/ztree/asynctree.js index 23eb2123a..2273209d9 100644 --- a/src/base/tree/ztree/asynctree.js +++ b/src/base/tree/ztree/asynctree.js @@ -18,7 +18,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { var self = this; var setting = { async: { - enable: false, + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 otherParam: BI.cjkEncodeDO(paras) }, check: { @@ -108,6 +108,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { return setting; }, + // 用来更新this.options.paras.selectedValues, 和ztree内部无关 _selectTreeNode: function (treeId, treeNode) { var self = this, o = this.options; var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); @@ -153,7 +154,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { function callback (nodes, hasNext) { self.nodes.addNodes(treeNode, nodes); - + // 展开节点是没有分页的 if (hasNext === true) { BI.delay(function () { times++; @@ -170,6 +171,9 @@ BI.AsyncTree = BI.inherit(BI.TreeView, { } }, + // a,b 两棵树 + // a->b b->a 做两次校验, 构造一个校验后的map + // e.g. 以a为基准,如果b没有此节点,则在map中添加。 如b有,且是全选的, 则在map中构造全选(为什么不添加a的值呢? 因为这次是取并集), 如果b中也有和a一样的存值,就递归 _join: function (valueA, valueB) { var self = this; var map = {}; diff --git a/src/base/tree/ztree/parttree.js b/src/base/tree/ztree/parttree.js index 8718b5efa..c201f2141 100644 --- a/src/base/tree/ztree/parttree.js +++ b/src/base/tree/ztree/parttree.js @@ -45,6 +45,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); } else { // 如果选中的值中不存在该值不处理 + // 因为反正是不选中,没必要管 var t = this.options.paras.selectedValues; var p = parentValues.concat(name); for (var i = 0, len = p.length; i < len; i++) { @@ -52,6 +53,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { if (t == null) { return; } + // 选中中国-江苏, 搜索南京,取消勾选 if (BI.isEmpty(t)) { break; } @@ -115,9 +117,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } var hasNext = !!d.hasNext, nodes = d.items || []; o.paras.lastSearchValue = d.lastSearchValue; - if (nodes.length > 0) { - callback(self._dealWidthNodes(nodes)); - } + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); self.setTipVisible(nodes.length <= 0); self.loaded(); if (!hasNext) { diff --git a/src/base/tree/ztree/treeview.js b/src/base/tree/ztree/treeview.js index e7de3bbd5..bd87b215e 100644 --- a/src/base/tree/ztree/treeview.js +++ b/src/base/tree/ztree/treeview.js @@ -71,8 +71,8 @@ BI.TreeView = BI.inherit(BI.Pane, { async: { enable: true, url: getUrl, - autoParam: ["id", "name"], - otherParam: BI.cjkEncodeDO(paras) + autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name + otherParam: BI.cjkEncodeDO(paras) // 静态参数 }, check: { enable: true @@ -80,16 +80,16 @@ BI.TreeView = BI.inherit(BI.Pane, { data: { key: { title: "title", - name: "text" + name: "text" // 节点的name属性替换成text }, simpleData: { - enable: true + enable: true // 可以穿id,pid属性的对象数组 } }, view: { showIcon: false, expandSpeed: "", - nameIsHTML: true, + nameIsHTML: true, // 节点可以用html标签代替 dblClickExpand: false }, callback: { @@ -112,6 +112,7 @@ BI.TreeView = BI.inherit(BI.Pane, { if(status.half === true && status.checked === true) { checked = false; } + // 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调 self.nodes.checkNode(treeNode, !checked, true, true); } @@ -134,7 +135,7 @@ BI.TreeView = BI.inherit(BI.Pane, { } return true; } - BI.Msg.toast("Please Wait。", "warning"); + BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件 return false; } @@ -172,9 +173,9 @@ BI.TreeView = BI.inherit(BI.Pane, { function ajaxGetNodes (treeNode, reloadType) { var zTree = self.nodes; if (reloadType == "refresh") { - zTree.updateNode(treeNode); + zTree.updateNode(treeNode); // 刷新一下当前节点,如果treeNode.xxx被改了的话 } - zTree.reAsyncChildNodes(treeNode, reloadType, true); + zTree.reAsyncChildNodes(treeNode, reloadType, true); // 强制加载子节点,reloadType === refresh为先清空再加载,否则为追加到现有子节点之后 } function beforeCheck (treeId, treeNode) { @@ -252,15 +253,18 @@ BI.TreeView = BI.inherit(BI.Pane, { } 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; } + // 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况) var storeValues = BI.deepClone(this.options.paras.selectedValues); var treeNode = this._getTree(storeValues, path); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); }, + // 获取的是以values最后一个节点为根的子树 _getTree: function (map, values) { var cur = map; BI.any(values, function (i, value) { @@ -272,6 +276,7 @@ BI.TreeView = BI.inherit(BI.Pane, { return cur; }, + // 以values为path一路向里补充map, 并在末尾节点添加key: value节点 _addTreeNode: function (map, values, key, value) { var cur = map; BI.each(values, function (i, value) { @@ -299,7 +304,7 @@ BI.TreeView = BI.inherit(BI.Pane, { var self = this; var hashMap = {}; var rootNoots = this.nodes.getNodes(); - track(rootNoots); + track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点 function track (nodes) { BI.each(nodes, function (i, node) { var checkState = node.getCheckStatus(); diff --git a/src/component/treevaluechooser/abstract.treevaluechooser.js b/src/component/treevaluechooser/abstract.treevaluechooser.js index b0821bda1..5bd5b7875 100644 --- a/src/component/treevaluechooser/abstract.treevaluechooser.js +++ b/src/component/treevaluechooser/abstract.treevaluechooser.js @@ -92,10 +92,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } BI.each(selected, function (k) { var node = self._getTreeNode(parentValues, k); - 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]); + // 找不到就是新增值 + 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]); + } }); } @@ -355,7 +364,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var result = []; var keyword = op.keyword || ""; var selectedValues = op.selectedValues; - var lastSearchValue = op.lastSearchValue || ""; + var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 var output = search(); BI.nextTick(function () { callback({ @@ -392,6 +401,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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; } @@ -521,6 +539,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: state[1] }); } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + if (parentValues.length === 0 && times === 1) { + result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); + } BI.nextTick(function () { callback({ items: result, @@ -587,6 +609,22 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }, + _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++) { diff --git a/src/component/treevaluechooser/combo.treevaluechooser.insert.js b/src/component/treevaluechooser/combo.treevaluechooser.insert.js new file mode 100644 index 000000000..530c13f54 --- /dev/null +++ b/src/component/treevaluechooser/combo.treevaluechooser.insert.js @@ -0,0 +1,54 @@ +/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.TreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_insert_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "TreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo); \ No newline at end of file diff --git a/src/widget/multitree/multi.tree.insert.combo.js b/src/widget/multitree/multi.tree.insert.combo.js new file mode 100644 index 000000000..6133cf92f --- /dev/null +++ b/src/widget/multitree/multi.tree.insert.combo.js @@ -0,0 +1,286 @@ +/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeInsertCombo + * @extends BI.Single + */ + +BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-insert-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || {}}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : {} + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: {}}; + } + self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || {}; + this.combo.setValue({ + value: v || {} + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo); \ No newline at end of file diff --git a/src/widget/multitree/trigger/multi.tree.search.insert.pane.js b/src/widget/multitree/trigger/multi.tree.search.insert.pane.js new file mode 100644 index 000000000..ccad8fede --- /dev/null +++ b/src/widget/multitree/trigger/multi.tree.search.insert.pane.js @@ -0,0 +1,106 @@ +/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchInsertPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { + + constants: { + height: 24, + }, + + props: { + baseCls: "bi-multi-tree-search-insert-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }, + + render: function () { + var self = this, opts = this.options; + + return { + type: "bi.vertical", + items: [{ + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + hgap: 5, + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } + }, { + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }] + }; + }, + + setKeyword: function (keyword, nodes) { + var isAddTipVisible = BI.isEmptyArray(nodes); + this.addTip.setVisible(isAddTipVisible); + this.partTree.setVisible(!isAddTipVisible); + isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; + +BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane); \ No newline at end of file From 5381d22231e168bd5dff9cb7234474c408baeefe Mon Sep 17 00:00:00 2001 From: windy <1374721899@qq.com> Date: Sat, 4 May 2019 17:21:47 +0800 Subject: [PATCH 2/5] =?UTF-8?q?BI-44287=20feat:=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E9=80=89=E4=B8=AD=E4=B8=8D=E5=BD=B1=E5=93=8D=E7=88=B6=E5=AD=90?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E7=9A=84=E6=A0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gruntfile.js | 3 + .../component/demo.treevaluechoosercombo.js | 16 +- dist/2.0/fineui.css | 31 +- dist/2.0/fineui.ie.js | 1442 ++++++++++++++-- dist/2.0/fineui.js | 1442 ++++++++++++++-- dist/base.css | 23 +- dist/base.js | 347 +++- dist/bundle.css | 31 +- dist/bundle.ie.js | 1442 ++++++++++++++-- dist/bundle.js | 1442 ++++++++++++++-- dist/case.js | 80 + dist/demo.js | 16 +- dist/fineui.css | 31 +- dist/fineui.ie.js | 1442 ++++++++++++++-- dist/fineui.js | 1442 ++++++++++++++-- dist/fineui_without_jquery_polyfill.js | 1509 ++++++++++++---- dist/resource.css | 8 +- dist/widget.js | 1515 +++++++++++++---- public/css/background.css | 8 +- .../tree/ztree/jquery.ztree.excheck-3.5.js | 4 +- src/base/tree/ztree/list/listasynctree.js | 123 ++ src/base/tree/ztree/list/listparttree.js | 92 + src/base/tree/ztree/list/listtreeview.js | 114 ++ src/base/tree/ztree/parttree.js | 15 +- src/case/tree/ztree/tree.list.display.js | 81 + .../abstract.treevaluechooser.list.js | 261 +++ .../combo.listtreevaluechooser.js | 54 + .../base/colorchooser/colorpicker/editor.css | 8 +- src/css/base/tree/tree.css | 15 + src/css/resource/background.css | 8 +- src/less/base/tree/tree.list.display.less | 17 + src/less/resource/background.less | 4 +- .../multitree/check/multi.tree.check.pane.js | 7 +- src/widget/multitree/multi.tree.list.combo.js | 295 ++++ src/widget/multitree/multi.tree.popup.js | 11 +- .../trigger/multi.tree.search.insert.pane.js | 87 +- .../{ => trigger}/multi.tree.search.pane.js | 0 .../trigger/searcher.list.multi.tree.js | 158 ++ ui/css/background.css | 8 +- 39 files changed, 12037 insertions(+), 1595 deletions(-) create mode 100644 src/base/tree/ztree/list/listasynctree.js create mode 100644 src/base/tree/ztree/list/listparttree.js create mode 100644 src/base/tree/ztree/list/listtreeview.js create mode 100644 src/case/tree/ztree/tree.list.display.js create mode 100644 src/component/treevaluechooser/abstract.treevaluechooser.list.js create mode 100644 src/component/treevaluechooser/combo.listtreevaluechooser.js create mode 100644 src/less/base/tree/tree.list.display.less create mode 100644 src/widget/multitree/multi.tree.list.combo.js rename src/widget/multitree/{ => trigger}/multi.tree.search.pane.js (100%) create mode 100644 src/widget/multitree/trigger/searcher.list.multi.tree.js diff --git a/Gruntfile.js b/Gruntfile.js index e81af8caa..9f5ff5a10 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -49,6 +49,9 @@ module.exports = function (grunt) { "src/base/tree/ztree/treeview.js", "src/base/tree/ztree/asynctree.js", "src/base/tree/ztree/parttree.js", + "src/base/tree/ztree/list/listtreeview.js", + "src/base/tree/ztree/list/listasynctree.js", + "src/base/tree/ztree/list/listparttree.js", "src/base/**/*.js" ], dest: "dist/base.js" diff --git a/demo/js/component/demo.treevaluechoosercombo.js b/demo/js/component/demo.treevaluechoosercombo.js index 91e11a72c..1d5075e13 100644 --- a/demo/js/component/demo.treevaluechoosercombo.js +++ b/demo/js/component/demo.treevaluechoosercombo.js @@ -12,11 +12,21 @@ Demo.TreeValueChooser = BI.inherit(BI.Widget, { callback(BI.deepClone(Demo.CONSTANTS.TREEITEMS)); } }); + var widget1 = BI.createWidget({ + type: "bi.list_tree_value_chooser_insert_combo", + itemsCreator: function (op, callback) { + callback(BI.deepClone(Demo.CONSTANTS.TREEITEMS)); + } + }); return { type: "bi.vertical", - hgap: 200, - vgap: 10, - items: [widget] + items: [{ + type: "bi.vertical_adapt", + hgap: 200, + vgap: 10, + items: [widget, widget1] + }] + }; } }); diff --git a/dist/2.0/fineui.css b/dist/2.0/fineui.css index d03531953..40180856d 100644 --- a/dist/2.0/fineui.css +++ b/dist/2.0/fineui.css @@ -2228,8 +2228,8 @@ textarea { _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/half_selected.png'); + background: url('images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -2274,8 +2274,8 @@ textarea { _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/half_selected.png'); + background: url('images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { @@ -3775,6 +3775,21 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, opacity: 1; filter: alpha(opacity=100); } + +.bi-list-display-tree .ztree li a, +.bi-list-display-tree .ztree li span { + cursor: default !important; +} +.bi-list-display-tree .ztree li a:hover { + text-decoration: none; +} +.bi-list-display-tree .ztree li a.curSelectedNode { + padding-top: 1px; + border: none; + background-color: inherit; + opacity: 1; + filter: alpha(opacity=100); +} .ztree * { padding: 0; margin: 0; @@ -4558,8 +4573,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/half_selected.png'); + background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -4604,8 +4619,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/half_selected.png'); + background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { diff --git a/dist/2.0/fineui.ie.js b/dist/2.0/fineui.ie.js index 4ec7479be..3591d85da 100644 --- a/dist/2.0/fineui.ie.js +++ b/dist/2.0/fineui.ie.js @@ -37918,7 +37918,14 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var name = this._getNodeValue(treeNode); if (treeNode.checked === true) { - BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + this._buildTree(self.options.paras.selectedValues, BI.concat(parentValues, name)); + o.itemsCreator({ + type: BI.TreeView.REQ_TYPE_ADJUST_DATA, + selectedValues: self.options.paras.selectedValues + }, function (res) { + self.options.paras.selectedValues = res; + BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + }); } else { // 如果选中的值中不存在该值不处理 // 因为反正是不选中,没必要管 @@ -38020,12 +38027,6 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { getValue: function () { var o = this.options; var result = BI.PartTree.superclass.getValue.apply(this, arguments); - o.itemsCreator({ - type: BI.TreeView.REQ_TYPE_ADJUST_DATA, - selectedValues: result - }, function (res) { - result = res; - }); return result; }, @@ -38040,7 +38041,333 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } }); -BI.shortcut("bi.part_tree", BI.PartTree);BI.prepares.push(function () { +BI.shortcut("bi.part_tree", BI.PartTree);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为[["A"], ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListTreeView + * @extends BI.TreeView + */ +BI.ListTreeView = BI.inherit(BI.TreeView, { + + _constants: { + SPLIT: "<|>" + }, + + _defaultConfig: function () { + return BI.extend(BI.ListTreeView.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListTreeView.superclass._init.apply(this, arguments); + var o = this.options; + this.storeValue = o.value || {}; + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + onClick: onClick + } + }; + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + _selectTreeNode: function (treeId, treeNode) { + this._checkValue(treeNode, treeNode.checked); + BI.ListTreeView.superclass._selectTreeNode.apply(this, arguments); + }, + + _transArrayToMap: function (treeArrays) { + var self = this; + var map = {}; + BI.each(treeArrays, function (idx, array) { + var key = array.join(self._constants.SPLIT); + map[key] = true; + }); + return map; + }, + + _transMapToArray: function (treeMap) { + var self = this; + var array = []; + BI.each(treeMap, function (key) { + var item = key.split(self._constants.SPLIT); + array.push(item); + }); + return array; + }, + + _checkValue: function (treeNode, checked) { + var key = BI.concat(this._getParentValues(treeNode), this._getNodeValue(treeNode)).join(this._constants.SPLIT); + if(checked) { + this.storeValue[key] = true; + } else { + delete this.storeValue[key]; + } + }, + + setSelectedValue: function (value) { + this.options.paras.selectedValues = value || []; + this.storeValue = this._transArrayToMap(value); + }, + + getValue: function () { + return this._transMapToArray(this.storeValue); + } +}); + +BI.shortcut("bi.list_tree_view", BI.ListTreeView);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为["A", ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListListAsyncTree + * @extends BI.TreeView + */ +BI.ListAsyncTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListAsyncTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListAsyncTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 + otherParam: BI.cjkEncodeDO(paras) + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + beforeExpand: beforeExpand, + beforeCheck: beforeCheck, + onClick: onClick + } + }; + + function beforeCheck (treeId, treeNode) { + treeNode.half = false; + } + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function beforeExpand (treeId, treeNode) { + self._beforeExpandNode(treeId, treeNode); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + // 展开节点 + _beforeExpandNode: function (treeId, treeNode) { + var self = this, o = this.options; + var parentValues = treeNode.parentValues || self._getParentValues(treeNode); + var op = BI.extend({}, o.paras, { + id: treeNode.id, + times: 1, + parentValues: parentValues.concat(this._getNodeValue(treeNode)) + }); + var complete = function (d) { + var nodes = d.items || []; + if (nodes.length > 0) { + callback(self._dealWidthNodes(nodes), !!d.hasNext); + } + }; + var times = 1; + + function callback (nodes, hasNext) { + self.nodes.addNodes(treeNode, nodes); + // 展开节点是没有分页的 + if (hasNext === true) { + BI.delay(function () { + times++; + op.times = times; + o.itemsCreator(op, complete); + }, 100); + } + } + + if (!treeNode.children) { + setTimeout(function () { + o.itemsCreator(op, complete); + }, 17); + } + }, + + hasChecked: function () { + return !BI.isEmpty(this.options.paras.selectedValues) || BI.ListAsyncTree.superclass.hasChecked.apply(this, arguments); + }, + + // 生成树方法 + stroke: function (config) { + delete this.options.keyword; + BI.extend(this.options.paras, config); + var setting = this._configSetting(); + this._initTree(setting); + } +}); + +BI.shortcut("bi.list_async_tree", BI.ListAsyncTree);/** + * guy + * 局部树,两个请求树, 第一个请求构造树,第二个请求获取节点 + * @class BI.ListPartTree + * @extends BI.AsyncTree + */ +BI.ListPartTree = BI.inherit(BI.ListAsyncTree, { + _defaultConfig: function () { + return BI.extend(BI.ListPartTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + + _init: function () { + BI.ListPartTree.superclass._init.apply(this, arguments); + }, + + _loadMore: function () { + var self = this, o = this.options; + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: ++this.times + }); + this.tip.setLoading(); + o.itemsCreator(op, function (d) { + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + if (self._stop === true) { + return; + } + if (!hasNext) { + self.tip.setEnd(); + } else { + self.tip.setLoaded(); + } + if (nodes.length > 0) { + self.nodes.addNodes(null, self._dealWidthNodes(nodes)); + } + }); + }, + + _initTree: function (setting, keyword) { + var self = this, o = this.options; + this.times = 1; + var tree = this.tree; + tree.empty(); + self.tip.setVisible(false); + this.loading(); + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: this.times + }); + var complete = function (d) { + if (self._stop === true || keyword != o.paras.keyword) { + return; + } + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); + self.setTipVisible(nodes.length <= 0); + self.loaded(); + if (!hasNext) { + self.tip.invisible(); + } else { + self.tip.setLoaded(); + } + self.fireEvent(BI.Events.AFTERINIT); + }; + + function callback (nodes) { + if (self._stop === true) { + return; + } + self.nodes = $.fn.zTree.init(tree.element, setting, nodes); + } + + BI.delay(function () { + o.itemsCreator(op, complete); + }, 100); + }, + + // 生成树方法 + stroke: function (config) { + var o = this.options; + delete o.paras.keyword; + BI.extend(o.paras, config); + delete o.paras.lastSearchValue; + var setting = this._configSetting(); + this._initTree(setting, o.paras.keyword); + } +}); + +BI.shortcut("bi.list_part_tree", BI.ListPartTree);BI.prepares.push(function () { BI.Resizers = new BI.ResizeController(); BI.Layers = new BI.LayerController(); BI.Maskers = new BI.MaskersController(); @@ -49543,6 +49870,8 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* makeChkClass: function(setting, node) { var checkedKey = setting.data.key.checked, c = consts.checkbox, r = consts.radio, + checkboxType = setting.check.chkboxType; + var notEffectByOtherNode = (checkboxType.Y === "" && checkboxType.N === ""); fullStyle = ""; if (node.chkDisabled === true) { fullStyle = c.DISABLED; @@ -49551,7 +49880,7 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* } else if (setting.check.chkStyle == r.STYLE) { fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART; } else { - fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART); + fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) || notEffectByOtherNode ? c.FULL:c.PART) : ((node.check_Child_State < 1 || notEffectByOtherNode)? c.FULL:c.PART); } var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle; chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; @@ -58900,6 +59229,86 @@ BI.DisplayTree = BI.inherit(BI.TreeView, { BI.DisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.display_tree", BI.DisplayTree);/** + * guy + * 异步树 + * @class BI.ListListDisplayTree + * @extends BI.TreeView + */ +BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListDisplayTree.superclass._defaultConfig.apply(this, arguments), { + extraCls: "bi-list-display-tree" + }); + }, + _init: function () { + BI.ListDisplayTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var setting = { + view: { + selectedMulti: false, + dblClickExpand: false, + showIcon: false, + nameIsHTML: true, + showTitle: false, + fontCss: getFont + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + callback: { + beforeCollapse: beforeCollapse + } + }; + + function beforeCollapse(treeId, treeNode) { + return false; + } + + function getFont(treeId, node) { + return node.font ? node.font : {color: "#999999"}; + } + + return setting; + }, + + _dealWidthNodes: function (nodes) { + nodes = BI.ListDisplayTree.superclass._dealWidthNodes.apply(this, arguments); + var self = this, o = this.options; + BI.each(nodes, function (i, node) { + node.isParent = node.isParent || node.parent; + if (node.text == null) { + if (node.count > 0) { + node.text = node.value + "(" + BI.i18nText("BI-Basic_Altogether") + node.count + BI.i18nText("BI-Basic_Count") + ")"; + } + } + if(node.isLeaf === true) { + node.font = {color: "#3d4d66"}; + } + }); + return nodes; + }, + + initTree: function (nodes, setting) { + var setting = setting || this._configSetting(); + this.nodes = $.fn.zTree.init(this.tree.element, setting, nodes); + }, + + destroy: function () { + BI.ListDisplayTree.superclass.destroy.apply(this, arguments); + } +}); +BI.ListDisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.shortcut("bi.list_display_tree", BI.ListDisplayTree);/** * 简单的多选树 * * Created by GUY on 2016/2/16. @@ -72132,7 +72541,10 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-multi-tree-check-pane bi-background", - onClickContinueSelect: BI.emptyFn + onClickContinueSelect: BI.emptyFn, + el: { + type: "bi.display_tree" + } }); }, @@ -72174,7 +72586,7 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { }] }); - this.display = BI.createWidget({ + this.display = BI.createWidget(opts.el, { type: "bi.display_tree", cls: "bi-multi-tree-display", itemsCreator: function (op, callback) { @@ -72784,6 +73196,300 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeListCombo + * @extends BI.Single + */ + +BI.MultiTreeListCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-list-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeListCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || []}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_list_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + el: { + type: "bi.list_part_tree" + }, + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + el: { + type: "bi.list_display_tree" + }, + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + el: { + type: "bi.list_async_tree" + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : [] + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: []}; + } + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || []; + this.combo.setValue({ + value: v || [] + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeListCombo.EVENT_CONFIRM = "MultiTreeListCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -72796,24 +73502,27 @@ BI.MultiTreePopup = BI.inherit(BI.Pane, { maxWidth: "auto", minWidth: 100, maxHeight: 400, - onLoaded: BI.emptyFn + onLoaded: BI.emptyFn, + el: { + type: "bi.async_tree" + } }); }, _init: function () { BI.MultiTreePopup.superclass._init.apply(this, arguments); - var self = this, opts = this.options; + var self = this, opts = this.options, v = opts.value; this.selectedValues = {}; - this.tree = BI.createWidget({ + this.tree = BI.createWidget(opts.el, { type: "bi.async_tree", height: 400, cls: "popup-view-tree", itemsCreator: opts.itemsCreator, onLoaded: opts.onLoaded, - value: opts.value || {} + value: v.value || {} }); this.popupView = BI.createWidget({ @@ -72881,79 +73590,6 @@ BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** - * - * 在搜索框中输入文本弹出的面板 - * @class BI.MultiTreeSearchPane - * @extends BI.Pane - */ - -BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { - - _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-search-pane bi-card", - itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn - }); - }, - - _init: function () { - BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); - - var self = this, opts = this.options; - - this.partTree = BI.createWidget({ - type: "bi.part_tree", - element: this, - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, callback); - }, - value: opts.value - }); - - this.partTree.on(BI.Controller.EVENT_CHANGE, function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - }); - - this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); - }); - }, - - hasChecked: function () { - return this.partTree.hasChecked(); - }, - - setValue: function (v) { - this.setSelectedValue(v.value); - }, - - setSelectedValue: function (v) { - v || (v = {}); - this.partTree.setSelectedValue(v); - }, - - getValue: function () { - return this.partTree.getValue(); - }, - - empty: function () { - this.partTree.empty(); - }, - - populate: function (op) { - this.partTree.stroke.apply(this.partTree, arguments); - } -}); - -BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; - -BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; - -BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** * 查看已选按钮 * Created by guy on 15/11/3. * @class BI.MultiTreeCheckSelectedButton @@ -73035,52 +73671,65 @@ BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { props: { baseCls: "bi-multi-tree-search-insert-pane bi-card", itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + keywordGetter: BI.emptyFn, + el: { + type: "bi.part_tree" + } }, render: function () { var self = this, opts = this.options; return { - type: "bi.vertical", + type: "bi.absolute", items: [{ - type: "bi.text_button", - invisible: true, - ref: function (_ref) { - self.addTip = _ref; + el: { + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } }, - text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), - height: this.constants.height, - cls: "bi-high-light", - hgap: 5, - handler: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); - } + top: 5, + left: 0, + right: 0 }, { - type: "bi.part_tree", - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, function (res) { - callback(res); - self.setKeyword(opts.keywordGetter(), res.items); - }); - }, - ref: function (_ref) { - self.partTree = _ref; - }, - value: opts.value, - listeners: [{ - eventName: BI.Controller.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - } - }, { - eventName: BI.TreeView.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); - } - }] + el: BI.extend({ + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }, opts.el), + left: 0, + top: 0, + bottom: 0, + right: 0 }] }; }, @@ -73125,6 +73774,236 @@ BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-search-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }); + }, + + _init: function () { + BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); + + var self = this, opts = this.options; + + this.partTree = BI.createWidget({ + type: "bi.part_tree", + element: this, + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, callback); + }, + value: opts.value + }); + + this.partTree.on(BI.Controller.EVENT_CHANGE, function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + + this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + }); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; + +BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiListTreeSearcher + * @extends Widget + */ +BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, + isAutoSync: false, + onSearch: function (op, callback) { + callback({ + keyword: self.editor.getValue() + }); + }, + el: this.editor, + + popup: BI.extend({ + type: "bi.multi_tree_search_pane", + keywordGetter: function () { + return self.editor.getValue(); + }, + itemsCreator: function (op, callback) { + op.keyword = self.editor.getValue(); + o.itemsCreator(op, callback); + }, + value: o.value + }, o.popup), + + adapter: o.adapter, + masker: o.masker + }); + this.searcher.on(BI.Searcher.EVENT_START, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); + }); + this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { + if (this.hasMatched()) { + + } + self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); + }); + this.searcher.on(BI.Searcher.EVENT_STOP, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); + }); + this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); + }); + if (BI.isNotNull(o.value)) { + this.setState(o.value); + } + }, + + adjustView: function () { + this.searcher.adjustView(); + }, + + setAdapter: function (adapter) { + this.searcher.setAdapter(adapter); + }, + + isSearching: function () { + return this.searcher.isSearching(); + }, + + stopSearch: function () { + this.searcher.stopSearch(); + }, + + getKeyword: function () { + return this.editor.getValue(); + }, + + hasMatched: function () { + return this.searcher.hasMatched(); + }, + + hasChecked: function () { + return this.searcher.getView() && this.searcher.getView().hasChecked(); + }, + + setState: function (ob) { + var o = this.options; + ob || (ob = {}); + ob.value || (ob.value = []); + var count = 0; + if (BI.isNumber(ob)) { + this.editor.setState(ob); + } else if (BI.size(ob.value) === 0) { + this.editor.setState(BI.Selection.None); + } else { + var text = ""; + BI.each(ob.value, function (idx, path) { + var childValue = BI.last(path); + text += (o.valueFormatter(childValue + "") || childValue) + "; "; + count++; + }); + + if (count > 20) { + this.editor.setState(BI.Selection.Multi); + } else { + this.editor.setState(text); + } + } + }, + + setValue: function (ob) { + this.setState(ob); + this.searcher.setValue(ob); + }, + + getKey: function () { + return this.editor.getValue(); + }, + + getValue: function () { + return this.searcher.getValue(); + }, + + populate: function (items) { + this.searcher.populate.apply(this.searcher, arguments); + } +}); + +BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; +BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; +BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; +BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; +BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -83619,7 +84498,320 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { _getChildCount: function (parentValues) { return this._getChildren(parentValues).length; } +});BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { + + _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: BI.values(result) + }); + + function doCheck(parentValues, node, selected) { + BI.each(selected, function (idx, path) { + BI.each(path, function (id, value) { + var nodeValue = value; + var node = self._getTreeNode(path.slice(0, id), nodeValue); + // 找不到就是新增值 + if (BI.isNull(node)) { + createOneJson({ + id: BI.UUID(), + text: nodeValue, + value: nodeValue, + isLeaf: true + }, BI.UUID()); + } else { + if(!BI.has(result, node.id)) { + createOneJson(node, node.parent && node.parent.id); + } + result[node.id].isLeaf = id === path.length - 1; + } + }); + }); + } + + function createOneJson(node, pId, leaf) { + result[node.id] = { + id: node.id, + pId: pId, + text: node.text, + value: node.value, + open: true, + isLeaf: leaf + }; + } + }, + + _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, result); + } else if (output.length === self._const.perPage) { + var find = nodeSearch(1, [], children[i].value, []); + } + 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, result) { + if (self._isMatch(parentValues, current, keyword)) { + var checked = isSelected(current); + createOneJson(parentValues, current, false, checked, true, result); + return [true, checked]; + } + var newParents = BI.clone(parentValues); + newParents.push(current); + var children = self._getChildren(newParents); + + var can = false, checked = false; + + BI.each(children, function (i, child) { + var state = nodeSearch(deep + 1, newParents, child.value, result); + if (state[1] === true) { + checked = true; + } + if (state[0] === true) { + can = true; + } + }); + if (can === true) { + checked = isSelected(current); + createOneJson(parentValues, current, true, checked, false, result); + } + return [can, checked]; + } + + function createOneJson(parentValues, value, isOpen, checked, 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: false, + 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(value) { + return BI.any(selectedValues, function (idx, array) { + return BI.last(array) === value; + }); + } + + 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; + var result = []; + var times = op.times; + var parentValues = op.parentValues || []; + var selectedValues = op.selectedValues || []; + var valueMap = dealWidthSelectedValue(selectedValues); + var nodes = this._getChildren(parentValues); + for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { + var checked = BI.has(valueMap, nodes[i].value); + 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: checked, + halfCheck: false + }); + } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + 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 dealWidthSelectedValue(selectedValues) { + var valueMap = {}; + BI.each(selectedValues, function (idx, v) { + valueMap[BI.last(v)] = [2, 0]; + }); + return valueMap; + } + }, + + _getAddedValueNode: function (parentValues, selectedValues) { + var nodes = this._getChildren(parentValues); + var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { + return array.length === 1; + })); + return BI.map(BI.difference(values, 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 + }; + }); + } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.ListTreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-list-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_list_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "ListTreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 * * Created by GUY on 2015/10/29. diff --git a/dist/2.0/fineui.js b/dist/2.0/fineui.js index f75e83c0c..862e443c4 100644 --- a/dist/2.0/fineui.js +++ b/dist/2.0/fineui.js @@ -38322,7 +38322,14 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var name = this._getNodeValue(treeNode); if (treeNode.checked === true) { - BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + this._buildTree(self.options.paras.selectedValues, BI.concat(parentValues, name)); + o.itemsCreator({ + type: BI.TreeView.REQ_TYPE_ADJUST_DATA, + selectedValues: self.options.paras.selectedValues + }, function (res) { + self.options.paras.selectedValues = res; + BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + }); } else { // 如果选中的值中不存在该值不处理 // 因为反正是不选中,没必要管 @@ -38424,12 +38431,6 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { getValue: function () { var o = this.options; var result = BI.PartTree.superclass.getValue.apply(this, arguments); - o.itemsCreator({ - type: BI.TreeView.REQ_TYPE_ADJUST_DATA, - selectedValues: result - }, function (res) { - result = res; - }); return result; }, @@ -38444,7 +38445,333 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } }); -BI.shortcut("bi.part_tree", BI.PartTree);BI.prepares.push(function () { +BI.shortcut("bi.part_tree", BI.PartTree);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为[["A"], ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListTreeView + * @extends BI.TreeView + */ +BI.ListTreeView = BI.inherit(BI.TreeView, { + + _constants: { + SPLIT: "<|>" + }, + + _defaultConfig: function () { + return BI.extend(BI.ListTreeView.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListTreeView.superclass._init.apply(this, arguments); + var o = this.options; + this.storeValue = o.value || {}; + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + onClick: onClick + } + }; + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + _selectTreeNode: function (treeId, treeNode) { + this._checkValue(treeNode, treeNode.checked); + BI.ListTreeView.superclass._selectTreeNode.apply(this, arguments); + }, + + _transArrayToMap: function (treeArrays) { + var self = this; + var map = {}; + BI.each(treeArrays, function (idx, array) { + var key = array.join(self._constants.SPLIT); + map[key] = true; + }); + return map; + }, + + _transMapToArray: function (treeMap) { + var self = this; + var array = []; + BI.each(treeMap, function (key) { + var item = key.split(self._constants.SPLIT); + array.push(item); + }); + return array; + }, + + _checkValue: function (treeNode, checked) { + var key = BI.concat(this._getParentValues(treeNode), this._getNodeValue(treeNode)).join(this._constants.SPLIT); + if(checked) { + this.storeValue[key] = true; + } else { + delete this.storeValue[key]; + } + }, + + setSelectedValue: function (value) { + this.options.paras.selectedValues = value || []; + this.storeValue = this._transArrayToMap(value); + }, + + getValue: function () { + return this._transMapToArray(this.storeValue); + } +}); + +BI.shortcut("bi.list_tree_view", BI.ListTreeView);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为["A", ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListListAsyncTree + * @extends BI.TreeView + */ +BI.ListAsyncTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListAsyncTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListAsyncTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 + otherParam: BI.cjkEncodeDO(paras) + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + beforeExpand: beforeExpand, + beforeCheck: beforeCheck, + onClick: onClick + } + }; + + function beforeCheck (treeId, treeNode) { + treeNode.half = false; + } + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function beforeExpand (treeId, treeNode) { + self._beforeExpandNode(treeId, treeNode); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + // 展开节点 + _beforeExpandNode: function (treeId, treeNode) { + var self = this, o = this.options; + var parentValues = treeNode.parentValues || self._getParentValues(treeNode); + var op = BI.extend({}, o.paras, { + id: treeNode.id, + times: 1, + parentValues: parentValues.concat(this._getNodeValue(treeNode)) + }); + var complete = function (d) { + var nodes = d.items || []; + if (nodes.length > 0) { + callback(self._dealWidthNodes(nodes), !!d.hasNext); + } + }; + var times = 1; + + function callback (nodes, hasNext) { + self.nodes.addNodes(treeNode, nodes); + // 展开节点是没有分页的 + if (hasNext === true) { + BI.delay(function () { + times++; + op.times = times; + o.itemsCreator(op, complete); + }, 100); + } + } + + if (!treeNode.children) { + setTimeout(function () { + o.itemsCreator(op, complete); + }, 17); + } + }, + + hasChecked: function () { + return !BI.isEmpty(this.options.paras.selectedValues) || BI.ListAsyncTree.superclass.hasChecked.apply(this, arguments); + }, + + // 生成树方法 + stroke: function (config) { + delete this.options.keyword; + BI.extend(this.options.paras, config); + var setting = this._configSetting(); + this._initTree(setting); + } +}); + +BI.shortcut("bi.list_async_tree", BI.ListAsyncTree);/** + * guy + * 局部树,两个请求树, 第一个请求构造树,第二个请求获取节点 + * @class BI.ListPartTree + * @extends BI.AsyncTree + */ +BI.ListPartTree = BI.inherit(BI.ListAsyncTree, { + _defaultConfig: function () { + return BI.extend(BI.ListPartTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + + _init: function () { + BI.ListPartTree.superclass._init.apply(this, arguments); + }, + + _loadMore: function () { + var self = this, o = this.options; + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: ++this.times + }); + this.tip.setLoading(); + o.itemsCreator(op, function (d) { + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + if (self._stop === true) { + return; + } + if (!hasNext) { + self.tip.setEnd(); + } else { + self.tip.setLoaded(); + } + if (nodes.length > 0) { + self.nodes.addNodes(null, self._dealWidthNodes(nodes)); + } + }); + }, + + _initTree: function (setting, keyword) { + var self = this, o = this.options; + this.times = 1; + var tree = this.tree; + tree.empty(); + self.tip.setVisible(false); + this.loading(); + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: this.times + }); + var complete = function (d) { + if (self._stop === true || keyword != o.paras.keyword) { + return; + } + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); + self.setTipVisible(nodes.length <= 0); + self.loaded(); + if (!hasNext) { + self.tip.invisible(); + } else { + self.tip.setLoaded(); + } + self.fireEvent(BI.Events.AFTERINIT); + }; + + function callback (nodes) { + if (self._stop === true) { + return; + } + self.nodes = $.fn.zTree.init(tree.element, setting, nodes); + } + + BI.delay(function () { + o.itemsCreator(op, complete); + }, 100); + }, + + // 生成树方法 + stroke: function (config) { + var o = this.options; + delete o.paras.keyword; + BI.extend(o.paras, config); + delete o.paras.lastSearchValue; + var setting = this._configSetting(); + this._initTree(setting, o.paras.keyword); + } +}); + +BI.shortcut("bi.list_part_tree", BI.ListPartTree);BI.prepares.push(function () { BI.Resizers = new BI.ResizeController(); BI.Layers = new BI.LayerController(); BI.Maskers = new BI.MaskersController(); @@ -49947,6 +50274,8 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* makeChkClass: function(setting, node) { var checkedKey = setting.data.key.checked, c = consts.checkbox, r = consts.radio, + checkboxType = setting.check.chkboxType; + var notEffectByOtherNode = (checkboxType.Y === "" && checkboxType.N === ""); fullStyle = ""; if (node.chkDisabled === true) { fullStyle = c.DISABLED; @@ -49955,7 +50284,7 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* } else if (setting.check.chkStyle == r.STYLE) { fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART; } else { - fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART); + fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) || notEffectByOtherNode ? c.FULL:c.PART) : ((node.check_Child_State < 1 || notEffectByOtherNode)? c.FULL:c.PART); } var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle; chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; @@ -59304,6 +59633,86 @@ BI.DisplayTree = BI.inherit(BI.TreeView, { BI.DisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.display_tree", BI.DisplayTree);/** + * guy + * 异步树 + * @class BI.ListListDisplayTree + * @extends BI.TreeView + */ +BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListDisplayTree.superclass._defaultConfig.apply(this, arguments), { + extraCls: "bi-list-display-tree" + }); + }, + _init: function () { + BI.ListDisplayTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var setting = { + view: { + selectedMulti: false, + dblClickExpand: false, + showIcon: false, + nameIsHTML: true, + showTitle: false, + fontCss: getFont + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + callback: { + beforeCollapse: beforeCollapse + } + }; + + function beforeCollapse(treeId, treeNode) { + return false; + } + + function getFont(treeId, node) { + return node.font ? node.font : {color: "#999999"}; + } + + return setting; + }, + + _dealWidthNodes: function (nodes) { + nodes = BI.ListDisplayTree.superclass._dealWidthNodes.apply(this, arguments); + var self = this, o = this.options; + BI.each(nodes, function (i, node) { + node.isParent = node.isParent || node.parent; + if (node.text == null) { + if (node.count > 0) { + node.text = node.value + "(" + BI.i18nText("BI-Basic_Altogether") + node.count + BI.i18nText("BI-Basic_Count") + ")"; + } + } + if(node.isLeaf === true) { + node.font = {color: "#3d4d66"}; + } + }); + return nodes; + }, + + initTree: function (nodes, setting) { + var setting = setting || this._configSetting(); + this.nodes = $.fn.zTree.init(this.tree.element, setting, nodes); + }, + + destroy: function () { + BI.ListDisplayTree.superclass.destroy.apply(this, arguments); + } +}); +BI.ListDisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.shortcut("bi.list_display_tree", BI.ListDisplayTree);/** * 简单的多选树 * * Created by GUY on 2016/2/16. @@ -72536,7 +72945,10 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-multi-tree-check-pane bi-background", - onClickContinueSelect: BI.emptyFn + onClickContinueSelect: BI.emptyFn, + el: { + type: "bi.display_tree" + } }); }, @@ -72578,7 +72990,7 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { }] }); - this.display = BI.createWidget({ + this.display = BI.createWidget(opts.el, { type: "bi.display_tree", cls: "bi-multi-tree-display", itemsCreator: function (op, callback) { @@ -73188,6 +73600,300 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeListCombo + * @extends BI.Single + */ + +BI.MultiTreeListCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-list-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeListCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || []}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_list_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + el: { + type: "bi.list_part_tree" + }, + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + el: { + type: "bi.list_display_tree" + }, + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + el: { + type: "bi.list_async_tree" + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : [] + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: []}; + } + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || []; + this.combo.setValue({ + value: v || [] + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeListCombo.EVENT_CONFIRM = "MultiTreeListCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -73200,24 +73906,27 @@ BI.MultiTreePopup = BI.inherit(BI.Pane, { maxWidth: "auto", minWidth: 100, maxHeight: 400, - onLoaded: BI.emptyFn + onLoaded: BI.emptyFn, + el: { + type: "bi.async_tree" + } }); }, _init: function () { BI.MultiTreePopup.superclass._init.apply(this, arguments); - var self = this, opts = this.options; + var self = this, opts = this.options, v = opts.value; this.selectedValues = {}; - this.tree = BI.createWidget({ + this.tree = BI.createWidget(opts.el, { type: "bi.async_tree", height: 400, cls: "popup-view-tree", itemsCreator: opts.itemsCreator, onLoaded: opts.onLoaded, - value: opts.value || {} + value: v.value || {} }); this.popupView = BI.createWidget({ @@ -73285,79 +73994,6 @@ BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** - * - * 在搜索框中输入文本弹出的面板 - * @class BI.MultiTreeSearchPane - * @extends BI.Pane - */ - -BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { - - _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-search-pane bi-card", - itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn - }); - }, - - _init: function () { - BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); - - var self = this, opts = this.options; - - this.partTree = BI.createWidget({ - type: "bi.part_tree", - element: this, - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, callback); - }, - value: opts.value - }); - - this.partTree.on(BI.Controller.EVENT_CHANGE, function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - }); - - this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); - }); - }, - - hasChecked: function () { - return this.partTree.hasChecked(); - }, - - setValue: function (v) { - this.setSelectedValue(v.value); - }, - - setSelectedValue: function (v) { - v || (v = {}); - this.partTree.setSelectedValue(v); - }, - - getValue: function () { - return this.partTree.getValue(); - }, - - empty: function () { - this.partTree.empty(); - }, - - populate: function (op) { - this.partTree.stroke.apply(this.partTree, arguments); - } -}); - -BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; - -BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; - -BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** * 查看已选按钮 * Created by guy on 15/11/3. * @class BI.MultiTreeCheckSelectedButton @@ -73439,52 +74075,65 @@ BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { props: { baseCls: "bi-multi-tree-search-insert-pane bi-card", itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + keywordGetter: BI.emptyFn, + el: { + type: "bi.part_tree" + } }, render: function () { var self = this, opts = this.options; return { - type: "bi.vertical", + type: "bi.absolute", items: [{ - type: "bi.text_button", - invisible: true, - ref: function (_ref) { - self.addTip = _ref; + el: { + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } }, - text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), - height: this.constants.height, - cls: "bi-high-light", - hgap: 5, - handler: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); - } + top: 5, + left: 0, + right: 0 }, { - type: "bi.part_tree", - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, function (res) { - callback(res); - self.setKeyword(opts.keywordGetter(), res.items); - }); - }, - ref: function (_ref) { - self.partTree = _ref; - }, - value: opts.value, - listeners: [{ - eventName: BI.Controller.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - } - }, { - eventName: BI.TreeView.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); - } - }] + el: BI.extend({ + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }, opts.el), + left: 0, + top: 0, + bottom: 0, + right: 0 }] }; }, @@ -73529,6 +74178,236 @@ BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-search-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }); + }, + + _init: function () { + BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); + + var self = this, opts = this.options; + + this.partTree = BI.createWidget({ + type: "bi.part_tree", + element: this, + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, callback); + }, + value: opts.value + }); + + this.partTree.on(BI.Controller.EVENT_CHANGE, function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + + this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + }); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; + +BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiListTreeSearcher + * @extends Widget + */ +BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, + isAutoSync: false, + onSearch: function (op, callback) { + callback({ + keyword: self.editor.getValue() + }); + }, + el: this.editor, + + popup: BI.extend({ + type: "bi.multi_tree_search_pane", + keywordGetter: function () { + return self.editor.getValue(); + }, + itemsCreator: function (op, callback) { + op.keyword = self.editor.getValue(); + o.itemsCreator(op, callback); + }, + value: o.value + }, o.popup), + + adapter: o.adapter, + masker: o.masker + }); + this.searcher.on(BI.Searcher.EVENT_START, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); + }); + this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { + if (this.hasMatched()) { + + } + self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); + }); + this.searcher.on(BI.Searcher.EVENT_STOP, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); + }); + this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); + }); + if (BI.isNotNull(o.value)) { + this.setState(o.value); + } + }, + + adjustView: function () { + this.searcher.adjustView(); + }, + + setAdapter: function (adapter) { + this.searcher.setAdapter(adapter); + }, + + isSearching: function () { + return this.searcher.isSearching(); + }, + + stopSearch: function () { + this.searcher.stopSearch(); + }, + + getKeyword: function () { + return this.editor.getValue(); + }, + + hasMatched: function () { + return this.searcher.hasMatched(); + }, + + hasChecked: function () { + return this.searcher.getView() && this.searcher.getView().hasChecked(); + }, + + setState: function (ob) { + var o = this.options; + ob || (ob = {}); + ob.value || (ob.value = []); + var count = 0; + if (BI.isNumber(ob)) { + this.editor.setState(ob); + } else if (BI.size(ob.value) === 0) { + this.editor.setState(BI.Selection.None); + } else { + var text = ""; + BI.each(ob.value, function (idx, path) { + var childValue = BI.last(path); + text += (o.valueFormatter(childValue + "") || childValue) + "; "; + count++; + }); + + if (count > 20) { + this.editor.setState(BI.Selection.Multi); + } else { + this.editor.setState(text); + } + } + }, + + setValue: function (ob) { + this.setState(ob); + this.searcher.setValue(ob); + }, + + getKey: function () { + return this.editor.getValue(); + }, + + getValue: function () { + return this.searcher.getValue(); + }, + + populate: function (items) { + this.searcher.populate.apply(this.searcher, arguments); + } +}); + +BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; +BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; +BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; +BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; +BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -84023,7 +84902,320 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { _getChildCount: function (parentValues) { return this._getChildren(parentValues).length; } +});BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { + + _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: BI.values(result) + }); + + function doCheck(parentValues, node, selected) { + BI.each(selected, function (idx, path) { + BI.each(path, function (id, value) { + var nodeValue = value; + var node = self._getTreeNode(path.slice(0, id), nodeValue); + // 找不到就是新增值 + if (BI.isNull(node)) { + createOneJson({ + id: BI.UUID(), + text: nodeValue, + value: nodeValue, + isLeaf: true + }, BI.UUID()); + } else { + if(!BI.has(result, node.id)) { + createOneJson(node, node.parent && node.parent.id); + } + result[node.id].isLeaf = id === path.length - 1; + } + }); + }); + } + + function createOneJson(node, pId, leaf) { + result[node.id] = { + id: node.id, + pId: pId, + text: node.text, + value: node.value, + open: true, + isLeaf: leaf + }; + } + }, + + _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, result); + } else if (output.length === self._const.perPage) { + var find = nodeSearch(1, [], children[i].value, []); + } + 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, result) { + if (self._isMatch(parentValues, current, keyword)) { + var checked = isSelected(current); + createOneJson(parentValues, current, false, checked, true, result); + return [true, checked]; + } + var newParents = BI.clone(parentValues); + newParents.push(current); + var children = self._getChildren(newParents); + + var can = false, checked = false; + + BI.each(children, function (i, child) { + var state = nodeSearch(deep + 1, newParents, child.value, result); + if (state[1] === true) { + checked = true; + } + if (state[0] === true) { + can = true; + } + }); + if (can === true) { + checked = isSelected(current); + createOneJson(parentValues, current, true, checked, false, result); + } + return [can, checked]; + } + + function createOneJson(parentValues, value, isOpen, checked, 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: false, + 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(value) { + return BI.any(selectedValues, function (idx, array) { + return BI.last(array) === value; + }); + } + + 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; + var result = []; + var times = op.times; + var parentValues = op.parentValues || []; + var selectedValues = op.selectedValues || []; + var valueMap = dealWidthSelectedValue(selectedValues); + var nodes = this._getChildren(parentValues); + for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { + var checked = BI.has(valueMap, nodes[i].value); + 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: checked, + halfCheck: false + }); + } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + 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 dealWidthSelectedValue(selectedValues) { + var valueMap = {}; + BI.each(selectedValues, function (idx, v) { + valueMap[BI.last(v)] = [2, 0]; + }); + return valueMap; + } + }, + + _getAddedValueNode: function (parentValues, selectedValues) { + var nodes = this._getChildren(parentValues); + var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { + return array.length === 1; + })); + return BI.map(BI.difference(values, 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 + }; + }); + } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.ListTreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-list-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_list_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "ListTreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 * * Created by GUY on 2015/10/29. diff --git a/dist/base.css b/dist/base.css index edecdcf44..885f7082f 100644 --- a/dist/base.css +++ b/dist/base.css @@ -72,8 +72,8 @@ _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/half_selected.png'); + background: url('images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -118,8 +118,8 @@ _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/half_selected.png'); + background: url('images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { @@ -1619,6 +1619,21 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, opacity: 1; filter: alpha(opacity=100); } + +.bi-list-display-tree .ztree li a, +.bi-list-display-tree .ztree li span { + cursor: default !important; +} +.bi-list-display-tree .ztree li a:hover { + text-decoration: none; +} +.bi-list-display-tree .ztree li a.curSelectedNode { + padding-top: 1px; + border: none; + background-color: inherit; + opacity: 1; + filter: alpha(opacity=100); +} .ztree * { padding: 0; margin: 0; diff --git a/dist/base.js b/dist/base.js index d92486f83..4f2350b06 100644 --- a/dist/base.js +++ b/dist/base.js @@ -2455,7 +2455,14 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var name = this._getNodeValue(treeNode); if (treeNode.checked === true) { - BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + this._buildTree(self.options.paras.selectedValues, BI.concat(parentValues, name)); + o.itemsCreator({ + type: BI.TreeView.REQ_TYPE_ADJUST_DATA, + selectedValues: self.options.paras.selectedValues + }, function (res) { + self.options.paras.selectedValues = res; + BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + }); } else { // 如果选中的值中不存在该值不处理 // 因为反正是不选中,没必要管 @@ -2557,12 +2564,6 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { getValue: function () { var o = this.options; var result = BI.PartTree.superclass.getValue.apply(this, arguments); - o.itemsCreator({ - type: BI.TreeView.REQ_TYPE_ADJUST_DATA, - selectedValues: result - }, function (res) { - result = res; - }); return result; }, @@ -2577,7 +2578,333 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } }); -BI.shortcut("bi.part_tree", BI.PartTree);BI.prepares.push(function () { +BI.shortcut("bi.part_tree", BI.PartTree);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为[["A"], ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListTreeView + * @extends BI.TreeView + */ +BI.ListTreeView = BI.inherit(BI.TreeView, { + + _constants: { + SPLIT: "<|>" + }, + + _defaultConfig: function () { + return BI.extend(BI.ListTreeView.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListTreeView.superclass._init.apply(this, arguments); + var o = this.options; + this.storeValue = o.value || {}; + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + onClick: onClick + } + }; + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + _selectTreeNode: function (treeId, treeNode) { + this._checkValue(treeNode, treeNode.checked); + BI.ListTreeView.superclass._selectTreeNode.apply(this, arguments); + }, + + _transArrayToMap: function (treeArrays) { + var self = this; + var map = {}; + BI.each(treeArrays, function (idx, array) { + var key = array.join(self._constants.SPLIT); + map[key] = true; + }); + return map; + }, + + _transMapToArray: function (treeMap) { + var self = this; + var array = []; + BI.each(treeMap, function (key) { + var item = key.split(self._constants.SPLIT); + array.push(item); + }); + return array; + }, + + _checkValue: function (treeNode, checked) { + var key = BI.concat(this._getParentValues(treeNode), this._getNodeValue(treeNode)).join(this._constants.SPLIT); + if(checked) { + this.storeValue[key] = true; + } else { + delete this.storeValue[key]; + } + }, + + setSelectedValue: function (value) { + this.options.paras.selectedValues = value || []; + this.storeValue = this._transArrayToMap(value); + }, + + getValue: function () { + return this._transMapToArray(this.storeValue); + } +}); + +BI.shortcut("bi.list_tree_view", BI.ListTreeView);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为["A", ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListListAsyncTree + * @extends BI.TreeView + */ +BI.ListAsyncTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListAsyncTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListAsyncTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 + otherParam: BI.cjkEncodeDO(paras) + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + beforeExpand: beforeExpand, + beforeCheck: beforeCheck, + onClick: onClick + } + }; + + function beforeCheck (treeId, treeNode) { + treeNode.half = false; + } + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function beforeExpand (treeId, treeNode) { + self._beforeExpandNode(treeId, treeNode); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + // 展开节点 + _beforeExpandNode: function (treeId, treeNode) { + var self = this, o = this.options; + var parentValues = treeNode.parentValues || self._getParentValues(treeNode); + var op = BI.extend({}, o.paras, { + id: treeNode.id, + times: 1, + parentValues: parentValues.concat(this._getNodeValue(treeNode)) + }); + var complete = function (d) { + var nodes = d.items || []; + if (nodes.length > 0) { + callback(self._dealWidthNodes(nodes), !!d.hasNext); + } + }; + var times = 1; + + function callback (nodes, hasNext) { + self.nodes.addNodes(treeNode, nodes); + // 展开节点是没有分页的 + if (hasNext === true) { + BI.delay(function () { + times++; + op.times = times; + o.itemsCreator(op, complete); + }, 100); + } + } + + if (!treeNode.children) { + setTimeout(function () { + o.itemsCreator(op, complete); + }, 17); + } + }, + + hasChecked: function () { + return !BI.isEmpty(this.options.paras.selectedValues) || BI.ListAsyncTree.superclass.hasChecked.apply(this, arguments); + }, + + // 生成树方法 + stroke: function (config) { + delete this.options.keyword; + BI.extend(this.options.paras, config); + var setting = this._configSetting(); + this._initTree(setting); + } +}); + +BI.shortcut("bi.list_async_tree", BI.ListAsyncTree);/** + * guy + * 局部树,两个请求树, 第一个请求构造树,第二个请求获取节点 + * @class BI.ListPartTree + * @extends BI.AsyncTree + */ +BI.ListPartTree = BI.inherit(BI.ListAsyncTree, { + _defaultConfig: function () { + return BI.extend(BI.ListPartTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + + _init: function () { + BI.ListPartTree.superclass._init.apply(this, arguments); + }, + + _loadMore: function () { + var self = this, o = this.options; + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: ++this.times + }); + this.tip.setLoading(); + o.itemsCreator(op, function (d) { + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + if (self._stop === true) { + return; + } + if (!hasNext) { + self.tip.setEnd(); + } else { + self.tip.setLoaded(); + } + if (nodes.length > 0) { + self.nodes.addNodes(null, self._dealWidthNodes(nodes)); + } + }); + }, + + _initTree: function (setting, keyword) { + var self = this, o = this.options; + this.times = 1; + var tree = this.tree; + tree.empty(); + self.tip.setVisible(false); + this.loading(); + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: this.times + }); + var complete = function (d) { + if (self._stop === true || keyword != o.paras.keyword) { + return; + } + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); + self.setTipVisible(nodes.length <= 0); + self.loaded(); + if (!hasNext) { + self.tip.invisible(); + } else { + self.tip.setLoaded(); + } + self.fireEvent(BI.Events.AFTERINIT); + }; + + function callback (nodes) { + if (self._stop === true) { + return; + } + self.nodes = $.fn.zTree.init(tree.element, setting, nodes); + } + + BI.delay(function () { + o.itemsCreator(op, complete); + }, 100); + }, + + // 生成树方法 + stroke: function (config) { + var o = this.options; + delete o.paras.keyword; + BI.extend(o.paras, config); + delete o.paras.lastSearchValue; + var setting = this._configSetting(); + this._initTree(setting, o.paras.keyword); + } +}); + +BI.shortcut("bi.list_part_tree", BI.ListPartTree);BI.prepares.push(function () { BI.Resizers = new BI.ResizeController(); BI.Layers = new BI.LayerController(); BI.Maskers = new BI.MaskersController(); @@ -14080,6 +14407,8 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* makeChkClass: function(setting, node) { var checkedKey = setting.data.key.checked, c = consts.checkbox, r = consts.radio, + checkboxType = setting.check.chkboxType; + var notEffectByOtherNode = (checkboxType.Y === "" && checkboxType.N === ""); fullStyle = ""; if (node.chkDisabled === true) { fullStyle = c.DISABLED; @@ -14088,7 +14417,7 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* } else if (setting.check.chkStyle == r.STYLE) { fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART; } else { - fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART); + fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) || notEffectByOtherNode ? c.FULL:c.PART) : ((node.check_Child_State < 1 || notEffectByOtherNode)? c.FULL:c.PART); } var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle; chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; diff --git a/dist/bundle.css b/dist/bundle.css index d03531953..40180856d 100644 --- a/dist/bundle.css +++ b/dist/bundle.css @@ -2228,8 +2228,8 @@ textarea { _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/half_selected.png'); + background: url('images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -2274,8 +2274,8 @@ textarea { _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/half_selected.png'); + background: url('images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { @@ -3775,6 +3775,21 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, opacity: 1; filter: alpha(opacity=100); } + +.bi-list-display-tree .ztree li a, +.bi-list-display-tree .ztree li span { + cursor: default !important; +} +.bi-list-display-tree .ztree li a:hover { + text-decoration: none; +} +.bi-list-display-tree .ztree li a.curSelectedNode { + padding-top: 1px; + border: none; + background-color: inherit; + opacity: 1; + filter: alpha(opacity=100); +} .ztree * { padding: 0; margin: 0; @@ -4558,8 +4573,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/half_selected.png'); + background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -4604,8 +4619,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/half_selected.png'); + background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { diff --git a/dist/bundle.ie.js b/dist/bundle.ie.js index 4ec7479be..3591d85da 100644 --- a/dist/bundle.ie.js +++ b/dist/bundle.ie.js @@ -37918,7 +37918,14 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var name = this._getNodeValue(treeNode); if (treeNode.checked === true) { - BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + this._buildTree(self.options.paras.selectedValues, BI.concat(parentValues, name)); + o.itemsCreator({ + type: BI.TreeView.REQ_TYPE_ADJUST_DATA, + selectedValues: self.options.paras.selectedValues + }, function (res) { + self.options.paras.selectedValues = res; + BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + }); } else { // 如果选中的值中不存在该值不处理 // 因为反正是不选中,没必要管 @@ -38020,12 +38027,6 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { getValue: function () { var o = this.options; var result = BI.PartTree.superclass.getValue.apply(this, arguments); - o.itemsCreator({ - type: BI.TreeView.REQ_TYPE_ADJUST_DATA, - selectedValues: result - }, function (res) { - result = res; - }); return result; }, @@ -38040,7 +38041,333 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } }); -BI.shortcut("bi.part_tree", BI.PartTree);BI.prepares.push(function () { +BI.shortcut("bi.part_tree", BI.PartTree);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为[["A"], ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListTreeView + * @extends BI.TreeView + */ +BI.ListTreeView = BI.inherit(BI.TreeView, { + + _constants: { + SPLIT: "<|>" + }, + + _defaultConfig: function () { + return BI.extend(BI.ListTreeView.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListTreeView.superclass._init.apply(this, arguments); + var o = this.options; + this.storeValue = o.value || {}; + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + onClick: onClick + } + }; + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + _selectTreeNode: function (treeId, treeNode) { + this._checkValue(treeNode, treeNode.checked); + BI.ListTreeView.superclass._selectTreeNode.apply(this, arguments); + }, + + _transArrayToMap: function (treeArrays) { + var self = this; + var map = {}; + BI.each(treeArrays, function (idx, array) { + var key = array.join(self._constants.SPLIT); + map[key] = true; + }); + return map; + }, + + _transMapToArray: function (treeMap) { + var self = this; + var array = []; + BI.each(treeMap, function (key) { + var item = key.split(self._constants.SPLIT); + array.push(item); + }); + return array; + }, + + _checkValue: function (treeNode, checked) { + var key = BI.concat(this._getParentValues(treeNode), this._getNodeValue(treeNode)).join(this._constants.SPLIT); + if(checked) { + this.storeValue[key] = true; + } else { + delete this.storeValue[key]; + } + }, + + setSelectedValue: function (value) { + this.options.paras.selectedValues = value || []; + this.storeValue = this._transArrayToMap(value); + }, + + getValue: function () { + return this._transMapToArray(this.storeValue); + } +}); + +BI.shortcut("bi.list_tree_view", BI.ListTreeView);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为["A", ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListListAsyncTree + * @extends BI.TreeView + */ +BI.ListAsyncTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListAsyncTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListAsyncTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 + otherParam: BI.cjkEncodeDO(paras) + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + beforeExpand: beforeExpand, + beforeCheck: beforeCheck, + onClick: onClick + } + }; + + function beforeCheck (treeId, treeNode) { + treeNode.half = false; + } + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function beforeExpand (treeId, treeNode) { + self._beforeExpandNode(treeId, treeNode); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + // 展开节点 + _beforeExpandNode: function (treeId, treeNode) { + var self = this, o = this.options; + var parentValues = treeNode.parentValues || self._getParentValues(treeNode); + var op = BI.extend({}, o.paras, { + id: treeNode.id, + times: 1, + parentValues: parentValues.concat(this._getNodeValue(treeNode)) + }); + var complete = function (d) { + var nodes = d.items || []; + if (nodes.length > 0) { + callback(self._dealWidthNodes(nodes), !!d.hasNext); + } + }; + var times = 1; + + function callback (nodes, hasNext) { + self.nodes.addNodes(treeNode, nodes); + // 展开节点是没有分页的 + if (hasNext === true) { + BI.delay(function () { + times++; + op.times = times; + o.itemsCreator(op, complete); + }, 100); + } + } + + if (!treeNode.children) { + setTimeout(function () { + o.itemsCreator(op, complete); + }, 17); + } + }, + + hasChecked: function () { + return !BI.isEmpty(this.options.paras.selectedValues) || BI.ListAsyncTree.superclass.hasChecked.apply(this, arguments); + }, + + // 生成树方法 + stroke: function (config) { + delete this.options.keyword; + BI.extend(this.options.paras, config); + var setting = this._configSetting(); + this._initTree(setting); + } +}); + +BI.shortcut("bi.list_async_tree", BI.ListAsyncTree);/** + * guy + * 局部树,两个请求树, 第一个请求构造树,第二个请求获取节点 + * @class BI.ListPartTree + * @extends BI.AsyncTree + */ +BI.ListPartTree = BI.inherit(BI.ListAsyncTree, { + _defaultConfig: function () { + return BI.extend(BI.ListPartTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + + _init: function () { + BI.ListPartTree.superclass._init.apply(this, arguments); + }, + + _loadMore: function () { + var self = this, o = this.options; + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: ++this.times + }); + this.tip.setLoading(); + o.itemsCreator(op, function (d) { + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + if (self._stop === true) { + return; + } + if (!hasNext) { + self.tip.setEnd(); + } else { + self.tip.setLoaded(); + } + if (nodes.length > 0) { + self.nodes.addNodes(null, self._dealWidthNodes(nodes)); + } + }); + }, + + _initTree: function (setting, keyword) { + var self = this, o = this.options; + this.times = 1; + var tree = this.tree; + tree.empty(); + self.tip.setVisible(false); + this.loading(); + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: this.times + }); + var complete = function (d) { + if (self._stop === true || keyword != o.paras.keyword) { + return; + } + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); + self.setTipVisible(nodes.length <= 0); + self.loaded(); + if (!hasNext) { + self.tip.invisible(); + } else { + self.tip.setLoaded(); + } + self.fireEvent(BI.Events.AFTERINIT); + }; + + function callback (nodes) { + if (self._stop === true) { + return; + } + self.nodes = $.fn.zTree.init(tree.element, setting, nodes); + } + + BI.delay(function () { + o.itemsCreator(op, complete); + }, 100); + }, + + // 生成树方法 + stroke: function (config) { + var o = this.options; + delete o.paras.keyword; + BI.extend(o.paras, config); + delete o.paras.lastSearchValue; + var setting = this._configSetting(); + this._initTree(setting, o.paras.keyword); + } +}); + +BI.shortcut("bi.list_part_tree", BI.ListPartTree);BI.prepares.push(function () { BI.Resizers = new BI.ResizeController(); BI.Layers = new BI.LayerController(); BI.Maskers = new BI.MaskersController(); @@ -49543,6 +49870,8 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* makeChkClass: function(setting, node) { var checkedKey = setting.data.key.checked, c = consts.checkbox, r = consts.radio, + checkboxType = setting.check.chkboxType; + var notEffectByOtherNode = (checkboxType.Y === "" && checkboxType.N === ""); fullStyle = ""; if (node.chkDisabled === true) { fullStyle = c.DISABLED; @@ -49551,7 +49880,7 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* } else if (setting.check.chkStyle == r.STYLE) { fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART; } else { - fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART); + fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) || notEffectByOtherNode ? c.FULL:c.PART) : ((node.check_Child_State < 1 || notEffectByOtherNode)? c.FULL:c.PART); } var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle; chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; @@ -58900,6 +59229,86 @@ BI.DisplayTree = BI.inherit(BI.TreeView, { BI.DisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.display_tree", BI.DisplayTree);/** + * guy + * 异步树 + * @class BI.ListListDisplayTree + * @extends BI.TreeView + */ +BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListDisplayTree.superclass._defaultConfig.apply(this, arguments), { + extraCls: "bi-list-display-tree" + }); + }, + _init: function () { + BI.ListDisplayTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var setting = { + view: { + selectedMulti: false, + dblClickExpand: false, + showIcon: false, + nameIsHTML: true, + showTitle: false, + fontCss: getFont + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + callback: { + beforeCollapse: beforeCollapse + } + }; + + function beforeCollapse(treeId, treeNode) { + return false; + } + + function getFont(treeId, node) { + return node.font ? node.font : {color: "#999999"}; + } + + return setting; + }, + + _dealWidthNodes: function (nodes) { + nodes = BI.ListDisplayTree.superclass._dealWidthNodes.apply(this, arguments); + var self = this, o = this.options; + BI.each(nodes, function (i, node) { + node.isParent = node.isParent || node.parent; + if (node.text == null) { + if (node.count > 0) { + node.text = node.value + "(" + BI.i18nText("BI-Basic_Altogether") + node.count + BI.i18nText("BI-Basic_Count") + ")"; + } + } + if(node.isLeaf === true) { + node.font = {color: "#3d4d66"}; + } + }); + return nodes; + }, + + initTree: function (nodes, setting) { + var setting = setting || this._configSetting(); + this.nodes = $.fn.zTree.init(this.tree.element, setting, nodes); + }, + + destroy: function () { + BI.ListDisplayTree.superclass.destroy.apply(this, arguments); + } +}); +BI.ListDisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.shortcut("bi.list_display_tree", BI.ListDisplayTree);/** * 简单的多选树 * * Created by GUY on 2016/2/16. @@ -72132,7 +72541,10 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-multi-tree-check-pane bi-background", - onClickContinueSelect: BI.emptyFn + onClickContinueSelect: BI.emptyFn, + el: { + type: "bi.display_tree" + } }); }, @@ -72174,7 +72586,7 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { }] }); - this.display = BI.createWidget({ + this.display = BI.createWidget(opts.el, { type: "bi.display_tree", cls: "bi-multi-tree-display", itemsCreator: function (op, callback) { @@ -72784,6 +73196,300 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeListCombo + * @extends BI.Single + */ + +BI.MultiTreeListCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-list-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeListCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || []}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_list_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + el: { + type: "bi.list_part_tree" + }, + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + el: { + type: "bi.list_display_tree" + }, + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + el: { + type: "bi.list_async_tree" + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : [] + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: []}; + } + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || []; + this.combo.setValue({ + value: v || [] + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeListCombo.EVENT_CONFIRM = "MultiTreeListCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -72796,24 +73502,27 @@ BI.MultiTreePopup = BI.inherit(BI.Pane, { maxWidth: "auto", minWidth: 100, maxHeight: 400, - onLoaded: BI.emptyFn + onLoaded: BI.emptyFn, + el: { + type: "bi.async_tree" + } }); }, _init: function () { BI.MultiTreePopup.superclass._init.apply(this, arguments); - var self = this, opts = this.options; + var self = this, opts = this.options, v = opts.value; this.selectedValues = {}; - this.tree = BI.createWidget({ + this.tree = BI.createWidget(opts.el, { type: "bi.async_tree", height: 400, cls: "popup-view-tree", itemsCreator: opts.itemsCreator, onLoaded: opts.onLoaded, - value: opts.value || {} + value: v.value || {} }); this.popupView = BI.createWidget({ @@ -72881,79 +73590,6 @@ BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** - * - * 在搜索框中输入文本弹出的面板 - * @class BI.MultiTreeSearchPane - * @extends BI.Pane - */ - -BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { - - _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-search-pane bi-card", - itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn - }); - }, - - _init: function () { - BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); - - var self = this, opts = this.options; - - this.partTree = BI.createWidget({ - type: "bi.part_tree", - element: this, - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, callback); - }, - value: opts.value - }); - - this.partTree.on(BI.Controller.EVENT_CHANGE, function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - }); - - this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); - }); - }, - - hasChecked: function () { - return this.partTree.hasChecked(); - }, - - setValue: function (v) { - this.setSelectedValue(v.value); - }, - - setSelectedValue: function (v) { - v || (v = {}); - this.partTree.setSelectedValue(v); - }, - - getValue: function () { - return this.partTree.getValue(); - }, - - empty: function () { - this.partTree.empty(); - }, - - populate: function (op) { - this.partTree.stroke.apply(this.partTree, arguments); - } -}); - -BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; - -BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; - -BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** * 查看已选按钮 * Created by guy on 15/11/3. * @class BI.MultiTreeCheckSelectedButton @@ -73035,52 +73671,65 @@ BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { props: { baseCls: "bi-multi-tree-search-insert-pane bi-card", itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + keywordGetter: BI.emptyFn, + el: { + type: "bi.part_tree" + } }, render: function () { var self = this, opts = this.options; return { - type: "bi.vertical", + type: "bi.absolute", items: [{ - type: "bi.text_button", - invisible: true, - ref: function (_ref) { - self.addTip = _ref; + el: { + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } }, - text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), - height: this.constants.height, - cls: "bi-high-light", - hgap: 5, - handler: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); - } + top: 5, + left: 0, + right: 0 }, { - type: "bi.part_tree", - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, function (res) { - callback(res); - self.setKeyword(opts.keywordGetter(), res.items); - }); - }, - ref: function (_ref) { - self.partTree = _ref; - }, - value: opts.value, - listeners: [{ - eventName: BI.Controller.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - } - }, { - eventName: BI.TreeView.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); - } - }] + el: BI.extend({ + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }, opts.el), + left: 0, + top: 0, + bottom: 0, + right: 0 }] }; }, @@ -73125,6 +73774,236 @@ BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-search-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }); + }, + + _init: function () { + BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); + + var self = this, opts = this.options; + + this.partTree = BI.createWidget({ + type: "bi.part_tree", + element: this, + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, callback); + }, + value: opts.value + }); + + this.partTree.on(BI.Controller.EVENT_CHANGE, function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + + this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + }); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; + +BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiListTreeSearcher + * @extends Widget + */ +BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, + isAutoSync: false, + onSearch: function (op, callback) { + callback({ + keyword: self.editor.getValue() + }); + }, + el: this.editor, + + popup: BI.extend({ + type: "bi.multi_tree_search_pane", + keywordGetter: function () { + return self.editor.getValue(); + }, + itemsCreator: function (op, callback) { + op.keyword = self.editor.getValue(); + o.itemsCreator(op, callback); + }, + value: o.value + }, o.popup), + + adapter: o.adapter, + masker: o.masker + }); + this.searcher.on(BI.Searcher.EVENT_START, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); + }); + this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { + if (this.hasMatched()) { + + } + self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); + }); + this.searcher.on(BI.Searcher.EVENT_STOP, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); + }); + this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); + }); + if (BI.isNotNull(o.value)) { + this.setState(o.value); + } + }, + + adjustView: function () { + this.searcher.adjustView(); + }, + + setAdapter: function (adapter) { + this.searcher.setAdapter(adapter); + }, + + isSearching: function () { + return this.searcher.isSearching(); + }, + + stopSearch: function () { + this.searcher.stopSearch(); + }, + + getKeyword: function () { + return this.editor.getValue(); + }, + + hasMatched: function () { + return this.searcher.hasMatched(); + }, + + hasChecked: function () { + return this.searcher.getView() && this.searcher.getView().hasChecked(); + }, + + setState: function (ob) { + var o = this.options; + ob || (ob = {}); + ob.value || (ob.value = []); + var count = 0; + if (BI.isNumber(ob)) { + this.editor.setState(ob); + } else if (BI.size(ob.value) === 0) { + this.editor.setState(BI.Selection.None); + } else { + var text = ""; + BI.each(ob.value, function (idx, path) { + var childValue = BI.last(path); + text += (o.valueFormatter(childValue + "") || childValue) + "; "; + count++; + }); + + if (count > 20) { + this.editor.setState(BI.Selection.Multi); + } else { + this.editor.setState(text); + } + } + }, + + setValue: function (ob) { + this.setState(ob); + this.searcher.setValue(ob); + }, + + getKey: function () { + return this.editor.getValue(); + }, + + getValue: function () { + return this.searcher.getValue(); + }, + + populate: function (items) { + this.searcher.populate.apply(this.searcher, arguments); + } +}); + +BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; +BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; +BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; +BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; +BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -83619,7 +84498,320 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { _getChildCount: function (parentValues) { return this._getChildren(parentValues).length; } +});BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { + + _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: BI.values(result) + }); + + function doCheck(parentValues, node, selected) { + BI.each(selected, function (idx, path) { + BI.each(path, function (id, value) { + var nodeValue = value; + var node = self._getTreeNode(path.slice(0, id), nodeValue); + // 找不到就是新增值 + if (BI.isNull(node)) { + createOneJson({ + id: BI.UUID(), + text: nodeValue, + value: nodeValue, + isLeaf: true + }, BI.UUID()); + } else { + if(!BI.has(result, node.id)) { + createOneJson(node, node.parent && node.parent.id); + } + result[node.id].isLeaf = id === path.length - 1; + } + }); + }); + } + + function createOneJson(node, pId, leaf) { + result[node.id] = { + id: node.id, + pId: pId, + text: node.text, + value: node.value, + open: true, + isLeaf: leaf + }; + } + }, + + _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, result); + } else if (output.length === self._const.perPage) { + var find = nodeSearch(1, [], children[i].value, []); + } + 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, result) { + if (self._isMatch(parentValues, current, keyword)) { + var checked = isSelected(current); + createOneJson(parentValues, current, false, checked, true, result); + return [true, checked]; + } + var newParents = BI.clone(parentValues); + newParents.push(current); + var children = self._getChildren(newParents); + + var can = false, checked = false; + + BI.each(children, function (i, child) { + var state = nodeSearch(deep + 1, newParents, child.value, result); + if (state[1] === true) { + checked = true; + } + if (state[0] === true) { + can = true; + } + }); + if (can === true) { + checked = isSelected(current); + createOneJson(parentValues, current, true, checked, false, result); + } + return [can, checked]; + } + + function createOneJson(parentValues, value, isOpen, checked, 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: false, + 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(value) { + return BI.any(selectedValues, function (idx, array) { + return BI.last(array) === value; + }); + } + + 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; + var result = []; + var times = op.times; + var parentValues = op.parentValues || []; + var selectedValues = op.selectedValues || []; + var valueMap = dealWidthSelectedValue(selectedValues); + var nodes = this._getChildren(parentValues); + for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { + var checked = BI.has(valueMap, nodes[i].value); + 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: checked, + halfCheck: false + }); + } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + 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 dealWidthSelectedValue(selectedValues) { + var valueMap = {}; + BI.each(selectedValues, function (idx, v) { + valueMap[BI.last(v)] = [2, 0]; + }); + return valueMap; + } + }, + + _getAddedValueNode: function (parentValues, selectedValues) { + var nodes = this._getChildren(parentValues); + var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { + return array.length === 1; + })); + return BI.map(BI.difference(values, 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 + }; + }); + } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.ListTreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-list-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_list_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "ListTreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 * * Created by GUY on 2015/10/29. diff --git a/dist/bundle.js b/dist/bundle.js index f75e83c0c..862e443c4 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -38322,7 +38322,14 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var name = this._getNodeValue(treeNode); if (treeNode.checked === true) { - BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + this._buildTree(self.options.paras.selectedValues, BI.concat(parentValues, name)); + o.itemsCreator({ + type: BI.TreeView.REQ_TYPE_ADJUST_DATA, + selectedValues: self.options.paras.selectedValues + }, function (res) { + self.options.paras.selectedValues = res; + BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + }); } else { // 如果选中的值中不存在该值不处理 // 因为反正是不选中,没必要管 @@ -38424,12 +38431,6 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { getValue: function () { var o = this.options; var result = BI.PartTree.superclass.getValue.apply(this, arguments); - o.itemsCreator({ - type: BI.TreeView.REQ_TYPE_ADJUST_DATA, - selectedValues: result - }, function (res) { - result = res; - }); return result; }, @@ -38444,7 +38445,333 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } }); -BI.shortcut("bi.part_tree", BI.PartTree);BI.prepares.push(function () { +BI.shortcut("bi.part_tree", BI.PartTree);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为[["A"], ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListTreeView + * @extends BI.TreeView + */ +BI.ListTreeView = BI.inherit(BI.TreeView, { + + _constants: { + SPLIT: "<|>" + }, + + _defaultConfig: function () { + return BI.extend(BI.ListTreeView.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListTreeView.superclass._init.apply(this, arguments); + var o = this.options; + this.storeValue = o.value || {}; + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + onClick: onClick + } + }; + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + _selectTreeNode: function (treeId, treeNode) { + this._checkValue(treeNode, treeNode.checked); + BI.ListTreeView.superclass._selectTreeNode.apply(this, arguments); + }, + + _transArrayToMap: function (treeArrays) { + var self = this; + var map = {}; + BI.each(treeArrays, function (idx, array) { + var key = array.join(self._constants.SPLIT); + map[key] = true; + }); + return map; + }, + + _transMapToArray: function (treeMap) { + var self = this; + var array = []; + BI.each(treeMap, function (key) { + var item = key.split(self._constants.SPLIT); + array.push(item); + }); + return array; + }, + + _checkValue: function (treeNode, checked) { + var key = BI.concat(this._getParentValues(treeNode), this._getNodeValue(treeNode)).join(this._constants.SPLIT); + if(checked) { + this.storeValue[key] = true; + } else { + delete this.storeValue[key]; + } + }, + + setSelectedValue: function (value) { + this.options.paras.selectedValues = value || []; + this.storeValue = this._transArrayToMap(value); + }, + + getValue: function () { + return this._transMapToArray(this.storeValue); + } +}); + +BI.shortcut("bi.list_tree_view", BI.ListTreeView);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为["A", ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListListAsyncTree + * @extends BI.TreeView + */ +BI.ListAsyncTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListAsyncTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListAsyncTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 + otherParam: BI.cjkEncodeDO(paras) + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + beforeExpand: beforeExpand, + beforeCheck: beforeCheck, + onClick: onClick + } + }; + + function beforeCheck (treeId, treeNode) { + treeNode.half = false; + } + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function beforeExpand (treeId, treeNode) { + self._beforeExpandNode(treeId, treeNode); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + // 展开节点 + _beforeExpandNode: function (treeId, treeNode) { + var self = this, o = this.options; + var parentValues = treeNode.parentValues || self._getParentValues(treeNode); + var op = BI.extend({}, o.paras, { + id: treeNode.id, + times: 1, + parentValues: parentValues.concat(this._getNodeValue(treeNode)) + }); + var complete = function (d) { + var nodes = d.items || []; + if (nodes.length > 0) { + callback(self._dealWidthNodes(nodes), !!d.hasNext); + } + }; + var times = 1; + + function callback (nodes, hasNext) { + self.nodes.addNodes(treeNode, nodes); + // 展开节点是没有分页的 + if (hasNext === true) { + BI.delay(function () { + times++; + op.times = times; + o.itemsCreator(op, complete); + }, 100); + } + } + + if (!treeNode.children) { + setTimeout(function () { + o.itemsCreator(op, complete); + }, 17); + } + }, + + hasChecked: function () { + return !BI.isEmpty(this.options.paras.selectedValues) || BI.ListAsyncTree.superclass.hasChecked.apply(this, arguments); + }, + + // 生成树方法 + stroke: function (config) { + delete this.options.keyword; + BI.extend(this.options.paras, config); + var setting = this._configSetting(); + this._initTree(setting); + } +}); + +BI.shortcut("bi.list_async_tree", BI.ListAsyncTree);/** + * guy + * 局部树,两个请求树, 第一个请求构造树,第二个请求获取节点 + * @class BI.ListPartTree + * @extends BI.AsyncTree + */ +BI.ListPartTree = BI.inherit(BI.ListAsyncTree, { + _defaultConfig: function () { + return BI.extend(BI.ListPartTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + + _init: function () { + BI.ListPartTree.superclass._init.apply(this, arguments); + }, + + _loadMore: function () { + var self = this, o = this.options; + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: ++this.times + }); + this.tip.setLoading(); + o.itemsCreator(op, function (d) { + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + if (self._stop === true) { + return; + } + if (!hasNext) { + self.tip.setEnd(); + } else { + self.tip.setLoaded(); + } + if (nodes.length > 0) { + self.nodes.addNodes(null, self._dealWidthNodes(nodes)); + } + }); + }, + + _initTree: function (setting, keyword) { + var self = this, o = this.options; + this.times = 1; + var tree = this.tree; + tree.empty(); + self.tip.setVisible(false); + this.loading(); + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: this.times + }); + var complete = function (d) { + if (self._stop === true || keyword != o.paras.keyword) { + return; + } + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); + self.setTipVisible(nodes.length <= 0); + self.loaded(); + if (!hasNext) { + self.tip.invisible(); + } else { + self.tip.setLoaded(); + } + self.fireEvent(BI.Events.AFTERINIT); + }; + + function callback (nodes) { + if (self._stop === true) { + return; + } + self.nodes = $.fn.zTree.init(tree.element, setting, nodes); + } + + BI.delay(function () { + o.itemsCreator(op, complete); + }, 100); + }, + + // 生成树方法 + stroke: function (config) { + var o = this.options; + delete o.paras.keyword; + BI.extend(o.paras, config); + delete o.paras.lastSearchValue; + var setting = this._configSetting(); + this._initTree(setting, o.paras.keyword); + } +}); + +BI.shortcut("bi.list_part_tree", BI.ListPartTree);BI.prepares.push(function () { BI.Resizers = new BI.ResizeController(); BI.Layers = new BI.LayerController(); BI.Maskers = new BI.MaskersController(); @@ -49947,6 +50274,8 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* makeChkClass: function(setting, node) { var checkedKey = setting.data.key.checked, c = consts.checkbox, r = consts.radio, + checkboxType = setting.check.chkboxType; + var notEffectByOtherNode = (checkboxType.Y === "" && checkboxType.N === ""); fullStyle = ""; if (node.chkDisabled === true) { fullStyle = c.DISABLED; @@ -49955,7 +50284,7 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* } else if (setting.check.chkStyle == r.STYLE) { fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART; } else { - fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART); + fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) || notEffectByOtherNode ? c.FULL:c.PART) : ((node.check_Child_State < 1 || notEffectByOtherNode)? c.FULL:c.PART); } var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle; chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; @@ -59304,6 +59633,86 @@ BI.DisplayTree = BI.inherit(BI.TreeView, { BI.DisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.display_tree", BI.DisplayTree);/** + * guy + * 异步树 + * @class BI.ListListDisplayTree + * @extends BI.TreeView + */ +BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListDisplayTree.superclass._defaultConfig.apply(this, arguments), { + extraCls: "bi-list-display-tree" + }); + }, + _init: function () { + BI.ListDisplayTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var setting = { + view: { + selectedMulti: false, + dblClickExpand: false, + showIcon: false, + nameIsHTML: true, + showTitle: false, + fontCss: getFont + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + callback: { + beforeCollapse: beforeCollapse + } + }; + + function beforeCollapse(treeId, treeNode) { + return false; + } + + function getFont(treeId, node) { + return node.font ? node.font : {color: "#999999"}; + } + + return setting; + }, + + _dealWidthNodes: function (nodes) { + nodes = BI.ListDisplayTree.superclass._dealWidthNodes.apply(this, arguments); + var self = this, o = this.options; + BI.each(nodes, function (i, node) { + node.isParent = node.isParent || node.parent; + if (node.text == null) { + if (node.count > 0) { + node.text = node.value + "(" + BI.i18nText("BI-Basic_Altogether") + node.count + BI.i18nText("BI-Basic_Count") + ")"; + } + } + if(node.isLeaf === true) { + node.font = {color: "#3d4d66"}; + } + }); + return nodes; + }, + + initTree: function (nodes, setting) { + var setting = setting || this._configSetting(); + this.nodes = $.fn.zTree.init(this.tree.element, setting, nodes); + }, + + destroy: function () { + BI.ListDisplayTree.superclass.destroy.apply(this, arguments); + } +}); +BI.ListDisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.shortcut("bi.list_display_tree", BI.ListDisplayTree);/** * 简单的多选树 * * Created by GUY on 2016/2/16. @@ -72536,7 +72945,10 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-multi-tree-check-pane bi-background", - onClickContinueSelect: BI.emptyFn + onClickContinueSelect: BI.emptyFn, + el: { + type: "bi.display_tree" + } }); }, @@ -72578,7 +72990,7 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { }] }); - this.display = BI.createWidget({ + this.display = BI.createWidget(opts.el, { type: "bi.display_tree", cls: "bi-multi-tree-display", itemsCreator: function (op, callback) { @@ -73188,6 +73600,300 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeListCombo + * @extends BI.Single + */ + +BI.MultiTreeListCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-list-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeListCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || []}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_list_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + el: { + type: "bi.list_part_tree" + }, + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + el: { + type: "bi.list_display_tree" + }, + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + el: { + type: "bi.list_async_tree" + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : [] + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: []}; + } + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || []; + this.combo.setValue({ + value: v || [] + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeListCombo.EVENT_CONFIRM = "MultiTreeListCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -73200,24 +73906,27 @@ BI.MultiTreePopup = BI.inherit(BI.Pane, { maxWidth: "auto", minWidth: 100, maxHeight: 400, - onLoaded: BI.emptyFn + onLoaded: BI.emptyFn, + el: { + type: "bi.async_tree" + } }); }, _init: function () { BI.MultiTreePopup.superclass._init.apply(this, arguments); - var self = this, opts = this.options; + var self = this, opts = this.options, v = opts.value; this.selectedValues = {}; - this.tree = BI.createWidget({ + this.tree = BI.createWidget(opts.el, { type: "bi.async_tree", height: 400, cls: "popup-view-tree", itemsCreator: opts.itemsCreator, onLoaded: opts.onLoaded, - value: opts.value || {} + value: v.value || {} }); this.popupView = BI.createWidget({ @@ -73285,79 +73994,6 @@ BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** - * - * 在搜索框中输入文本弹出的面板 - * @class BI.MultiTreeSearchPane - * @extends BI.Pane - */ - -BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { - - _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-search-pane bi-card", - itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn - }); - }, - - _init: function () { - BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); - - var self = this, opts = this.options; - - this.partTree = BI.createWidget({ - type: "bi.part_tree", - element: this, - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, callback); - }, - value: opts.value - }); - - this.partTree.on(BI.Controller.EVENT_CHANGE, function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - }); - - this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); - }); - }, - - hasChecked: function () { - return this.partTree.hasChecked(); - }, - - setValue: function (v) { - this.setSelectedValue(v.value); - }, - - setSelectedValue: function (v) { - v || (v = {}); - this.partTree.setSelectedValue(v); - }, - - getValue: function () { - return this.partTree.getValue(); - }, - - empty: function () { - this.partTree.empty(); - }, - - populate: function (op) { - this.partTree.stroke.apply(this.partTree, arguments); - } -}); - -BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; - -BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; - -BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** * 查看已选按钮 * Created by guy on 15/11/3. * @class BI.MultiTreeCheckSelectedButton @@ -73439,52 +74075,65 @@ BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { props: { baseCls: "bi-multi-tree-search-insert-pane bi-card", itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + keywordGetter: BI.emptyFn, + el: { + type: "bi.part_tree" + } }, render: function () { var self = this, opts = this.options; return { - type: "bi.vertical", + type: "bi.absolute", items: [{ - type: "bi.text_button", - invisible: true, - ref: function (_ref) { - self.addTip = _ref; + el: { + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } }, - text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), - height: this.constants.height, - cls: "bi-high-light", - hgap: 5, - handler: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); - } + top: 5, + left: 0, + right: 0 }, { - type: "bi.part_tree", - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, function (res) { - callback(res); - self.setKeyword(opts.keywordGetter(), res.items); - }); - }, - ref: function (_ref) { - self.partTree = _ref; - }, - value: opts.value, - listeners: [{ - eventName: BI.Controller.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - } - }, { - eventName: BI.TreeView.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); - } - }] + el: BI.extend({ + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }, opts.el), + left: 0, + top: 0, + bottom: 0, + right: 0 }] }; }, @@ -73529,6 +74178,236 @@ BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-search-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }); + }, + + _init: function () { + BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); + + var self = this, opts = this.options; + + this.partTree = BI.createWidget({ + type: "bi.part_tree", + element: this, + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, callback); + }, + value: opts.value + }); + + this.partTree.on(BI.Controller.EVENT_CHANGE, function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + + this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + }); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; + +BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiListTreeSearcher + * @extends Widget + */ +BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, + isAutoSync: false, + onSearch: function (op, callback) { + callback({ + keyword: self.editor.getValue() + }); + }, + el: this.editor, + + popup: BI.extend({ + type: "bi.multi_tree_search_pane", + keywordGetter: function () { + return self.editor.getValue(); + }, + itemsCreator: function (op, callback) { + op.keyword = self.editor.getValue(); + o.itemsCreator(op, callback); + }, + value: o.value + }, o.popup), + + adapter: o.adapter, + masker: o.masker + }); + this.searcher.on(BI.Searcher.EVENT_START, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); + }); + this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { + if (this.hasMatched()) { + + } + self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); + }); + this.searcher.on(BI.Searcher.EVENT_STOP, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); + }); + this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); + }); + if (BI.isNotNull(o.value)) { + this.setState(o.value); + } + }, + + adjustView: function () { + this.searcher.adjustView(); + }, + + setAdapter: function (adapter) { + this.searcher.setAdapter(adapter); + }, + + isSearching: function () { + return this.searcher.isSearching(); + }, + + stopSearch: function () { + this.searcher.stopSearch(); + }, + + getKeyword: function () { + return this.editor.getValue(); + }, + + hasMatched: function () { + return this.searcher.hasMatched(); + }, + + hasChecked: function () { + return this.searcher.getView() && this.searcher.getView().hasChecked(); + }, + + setState: function (ob) { + var o = this.options; + ob || (ob = {}); + ob.value || (ob.value = []); + var count = 0; + if (BI.isNumber(ob)) { + this.editor.setState(ob); + } else if (BI.size(ob.value) === 0) { + this.editor.setState(BI.Selection.None); + } else { + var text = ""; + BI.each(ob.value, function (idx, path) { + var childValue = BI.last(path); + text += (o.valueFormatter(childValue + "") || childValue) + "; "; + count++; + }); + + if (count > 20) { + this.editor.setState(BI.Selection.Multi); + } else { + this.editor.setState(text); + } + } + }, + + setValue: function (ob) { + this.setState(ob); + this.searcher.setValue(ob); + }, + + getKey: function () { + return this.editor.getValue(); + }, + + getValue: function () { + return this.searcher.getValue(); + }, + + populate: function (items) { + this.searcher.populate.apply(this.searcher, arguments); + } +}); + +BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; +BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; +BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; +BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; +BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -84023,7 +84902,320 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { _getChildCount: function (parentValues) { return this._getChildren(parentValues).length; } +});BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { + + _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: BI.values(result) + }); + + function doCheck(parentValues, node, selected) { + BI.each(selected, function (idx, path) { + BI.each(path, function (id, value) { + var nodeValue = value; + var node = self._getTreeNode(path.slice(0, id), nodeValue); + // 找不到就是新增值 + if (BI.isNull(node)) { + createOneJson({ + id: BI.UUID(), + text: nodeValue, + value: nodeValue, + isLeaf: true + }, BI.UUID()); + } else { + if(!BI.has(result, node.id)) { + createOneJson(node, node.parent && node.parent.id); + } + result[node.id].isLeaf = id === path.length - 1; + } + }); + }); + } + + function createOneJson(node, pId, leaf) { + result[node.id] = { + id: node.id, + pId: pId, + text: node.text, + value: node.value, + open: true, + isLeaf: leaf + }; + } + }, + + _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, result); + } else if (output.length === self._const.perPage) { + var find = nodeSearch(1, [], children[i].value, []); + } + 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, result) { + if (self._isMatch(parentValues, current, keyword)) { + var checked = isSelected(current); + createOneJson(parentValues, current, false, checked, true, result); + return [true, checked]; + } + var newParents = BI.clone(parentValues); + newParents.push(current); + var children = self._getChildren(newParents); + + var can = false, checked = false; + + BI.each(children, function (i, child) { + var state = nodeSearch(deep + 1, newParents, child.value, result); + if (state[1] === true) { + checked = true; + } + if (state[0] === true) { + can = true; + } + }); + if (can === true) { + checked = isSelected(current); + createOneJson(parentValues, current, true, checked, false, result); + } + return [can, checked]; + } + + function createOneJson(parentValues, value, isOpen, checked, 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: false, + 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(value) { + return BI.any(selectedValues, function (idx, array) { + return BI.last(array) === value; + }); + } + + 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; + var result = []; + var times = op.times; + var parentValues = op.parentValues || []; + var selectedValues = op.selectedValues || []; + var valueMap = dealWidthSelectedValue(selectedValues); + var nodes = this._getChildren(parentValues); + for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { + var checked = BI.has(valueMap, nodes[i].value); + 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: checked, + halfCheck: false + }); + } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + 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 dealWidthSelectedValue(selectedValues) { + var valueMap = {}; + BI.each(selectedValues, function (idx, v) { + valueMap[BI.last(v)] = [2, 0]; + }); + return valueMap; + } + }, + + _getAddedValueNode: function (parentValues, selectedValues) { + var nodes = this._getChildren(parentValues); + var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { + return array.length === 1; + })); + return BI.map(BI.difference(values, 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 + }; + }); + } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.ListTreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-list-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_list_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "ListTreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 * * Created by GUY on 2015/10/29. diff --git a/dist/case.js b/dist/case.js index 5890a0020..82dd9f7a5 100644 --- a/dist/case.js +++ b/dist/case.js @@ -9155,6 +9155,86 @@ BI.DisplayTree = BI.inherit(BI.TreeView, { BI.DisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.display_tree", BI.DisplayTree);/** + * guy + * 异步树 + * @class BI.ListListDisplayTree + * @extends BI.TreeView + */ +BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListDisplayTree.superclass._defaultConfig.apply(this, arguments), { + extraCls: "bi-list-display-tree" + }); + }, + _init: function () { + BI.ListDisplayTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var setting = { + view: { + selectedMulti: false, + dblClickExpand: false, + showIcon: false, + nameIsHTML: true, + showTitle: false, + fontCss: getFont + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + callback: { + beforeCollapse: beforeCollapse + } + }; + + function beforeCollapse(treeId, treeNode) { + return false; + } + + function getFont(treeId, node) { + return node.font ? node.font : {color: "#999999"}; + } + + return setting; + }, + + _dealWidthNodes: function (nodes) { + nodes = BI.ListDisplayTree.superclass._dealWidthNodes.apply(this, arguments); + var self = this, o = this.options; + BI.each(nodes, function (i, node) { + node.isParent = node.isParent || node.parent; + if (node.text == null) { + if (node.count > 0) { + node.text = node.value + "(" + BI.i18nText("BI-Basic_Altogether") + node.count + BI.i18nText("BI-Basic_Count") + ")"; + } + } + if(node.isLeaf === true) { + node.font = {color: "#3d4d66"}; + } + }); + return nodes; + }, + + initTree: function (nodes, setting) { + var setting = setting || this._configSetting(); + this.nodes = $.fn.zTree.init(this.tree.element, setting, nodes); + }, + + destroy: function () { + BI.ListDisplayTree.superclass.destroy.apply(this, arguments); + } +}); +BI.ListDisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.shortcut("bi.list_display_tree", BI.ListDisplayTree);/** * 简单的多选树 * * Created by GUY on 2016/2/16. diff --git a/dist/demo.js b/dist/demo.js index 910eb5bcc..9831888e1 100644 --- a/dist/demo.js +++ b/dist/demo.js @@ -2707,11 +2707,21 @@ BI.shortcut("demo.center", Demo.Center);Demo.TreeValueChooser = BI.inherit(BI.Wi callback(BI.deepClone(Demo.CONSTANTS.TREEITEMS)); } }); + var widget1 = BI.createWidget({ + type: "bi.list_tree_value_chooser_insert_combo", + itemsCreator: function (op, callback) { + callback(BI.deepClone(Demo.CONSTANTS.TREEITEMS)); + } + }); return { type: "bi.vertical", - hgap: 200, - vgap: 10, - items: [widget] + items: [{ + type: "bi.vertical_adapt", + hgap: 200, + vgap: 10, + items: [widget, widget1] + }] + }; } }); diff --git a/dist/fineui.css b/dist/fineui.css index 1c296a696..68d3fd322 100644 --- a/dist/fineui.css +++ b/dist/fineui.css @@ -2228,8 +2228,8 @@ textarea { _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/half_selected.png'); + background: url('images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -2274,8 +2274,8 @@ textarea { _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/half_selected.png'); + background: url('images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { @@ -3775,6 +3775,21 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, opacity: 1; filter: alpha(opacity=100); } + +.bi-list-display-tree .ztree li a, +.bi-list-display-tree .ztree li span { + cursor: default !important; +} +.bi-list-display-tree .ztree li a:hover { + text-decoration: none; +} +.bi-list-display-tree .ztree li a.curSelectedNode { + padding-top: 1px; + border: none; + background-color: inherit; + opacity: 1; + filter: alpha(opacity=100); +} .ztree * { padding: 0; margin: 0; @@ -4558,8 +4573,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('resources?path=/com/fr/web/ui/images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/2x/icon/half_selected.png'); + background: url('resources?path=/com/fr/web/ui/images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -4604,8 +4619,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('resources?path=/com/fr/web/ui/images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/1x/icon/half_selected.png'); + background: url('resources?path=/com/fr/web/ui/images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { diff --git a/dist/fineui.ie.js b/dist/fineui.ie.js index af5c350f2..d88578187 100644 --- a/dist/fineui.ie.js +++ b/dist/fineui.ie.js @@ -38163,7 +38163,14 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var name = this._getNodeValue(treeNode); if (treeNode.checked === true) { - BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + this._buildTree(self.options.paras.selectedValues, BI.concat(parentValues, name)); + o.itemsCreator({ + type: BI.TreeView.REQ_TYPE_ADJUST_DATA, + selectedValues: self.options.paras.selectedValues + }, function (res) { + self.options.paras.selectedValues = res; + BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + }); } else { // 如果选中的值中不存在该值不处理 // 因为反正是不选中,没必要管 @@ -38265,12 +38272,6 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { getValue: function () { var o = this.options; var result = BI.PartTree.superclass.getValue.apply(this, arguments); - o.itemsCreator({ - type: BI.TreeView.REQ_TYPE_ADJUST_DATA, - selectedValues: result - }, function (res) { - result = res; - }); return result; }, @@ -38285,7 +38286,333 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } }); -BI.shortcut("bi.part_tree", BI.PartTree);BI.prepares.push(function () { +BI.shortcut("bi.part_tree", BI.PartTree);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为[["A"], ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListTreeView + * @extends BI.TreeView + */ +BI.ListTreeView = BI.inherit(BI.TreeView, { + + _constants: { + SPLIT: "<|>" + }, + + _defaultConfig: function () { + return BI.extend(BI.ListTreeView.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListTreeView.superclass._init.apply(this, arguments); + var o = this.options; + this.storeValue = o.value || {}; + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + onClick: onClick + } + }; + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + _selectTreeNode: function (treeId, treeNode) { + this._checkValue(treeNode, treeNode.checked); + BI.ListTreeView.superclass._selectTreeNode.apply(this, arguments); + }, + + _transArrayToMap: function (treeArrays) { + var self = this; + var map = {}; + BI.each(treeArrays, function (idx, array) { + var key = array.join(self._constants.SPLIT); + map[key] = true; + }); + return map; + }, + + _transMapToArray: function (treeMap) { + var self = this; + var array = []; + BI.each(treeMap, function (key) { + var item = key.split(self._constants.SPLIT); + array.push(item); + }); + return array; + }, + + _checkValue: function (treeNode, checked) { + var key = BI.concat(this._getParentValues(treeNode), this._getNodeValue(treeNode)).join(this._constants.SPLIT); + if(checked) { + this.storeValue[key] = true; + } else { + delete this.storeValue[key]; + } + }, + + setSelectedValue: function (value) { + this.options.paras.selectedValues = value || []; + this.storeValue = this._transArrayToMap(value); + }, + + getValue: function () { + return this._transMapToArray(this.storeValue); + } +}); + +BI.shortcut("bi.list_tree_view", BI.ListTreeView);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为["A", ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListListAsyncTree + * @extends BI.TreeView + */ +BI.ListAsyncTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListAsyncTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListAsyncTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 + otherParam: BI.cjkEncodeDO(paras) + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + beforeExpand: beforeExpand, + beforeCheck: beforeCheck, + onClick: onClick + } + }; + + function beforeCheck (treeId, treeNode) { + treeNode.half = false; + } + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function beforeExpand (treeId, treeNode) { + self._beforeExpandNode(treeId, treeNode); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + // 展开节点 + _beforeExpandNode: function (treeId, treeNode) { + var self = this, o = this.options; + var parentValues = treeNode.parentValues || self._getParentValues(treeNode); + var op = BI.extend({}, o.paras, { + id: treeNode.id, + times: 1, + parentValues: parentValues.concat(this._getNodeValue(treeNode)) + }); + var complete = function (d) { + var nodes = d.items || []; + if (nodes.length > 0) { + callback(self._dealWidthNodes(nodes), !!d.hasNext); + } + }; + var times = 1; + + function callback (nodes, hasNext) { + self.nodes.addNodes(treeNode, nodes); + // 展开节点是没有分页的 + if (hasNext === true) { + BI.delay(function () { + times++; + op.times = times; + o.itemsCreator(op, complete); + }, 100); + } + } + + if (!treeNode.children) { + setTimeout(function () { + o.itemsCreator(op, complete); + }, 17); + } + }, + + hasChecked: function () { + return !BI.isEmpty(this.options.paras.selectedValues) || BI.ListAsyncTree.superclass.hasChecked.apply(this, arguments); + }, + + // 生成树方法 + stroke: function (config) { + delete this.options.keyword; + BI.extend(this.options.paras, config); + var setting = this._configSetting(); + this._initTree(setting); + } +}); + +BI.shortcut("bi.list_async_tree", BI.ListAsyncTree);/** + * guy + * 局部树,两个请求树, 第一个请求构造树,第二个请求获取节点 + * @class BI.ListPartTree + * @extends BI.AsyncTree + */ +BI.ListPartTree = BI.inherit(BI.ListAsyncTree, { + _defaultConfig: function () { + return BI.extend(BI.ListPartTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + + _init: function () { + BI.ListPartTree.superclass._init.apply(this, arguments); + }, + + _loadMore: function () { + var self = this, o = this.options; + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: ++this.times + }); + this.tip.setLoading(); + o.itemsCreator(op, function (d) { + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + if (self._stop === true) { + return; + } + if (!hasNext) { + self.tip.setEnd(); + } else { + self.tip.setLoaded(); + } + if (nodes.length > 0) { + self.nodes.addNodes(null, self._dealWidthNodes(nodes)); + } + }); + }, + + _initTree: function (setting, keyword) { + var self = this, o = this.options; + this.times = 1; + var tree = this.tree; + tree.empty(); + self.tip.setVisible(false); + this.loading(); + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: this.times + }); + var complete = function (d) { + if (self._stop === true || keyword != o.paras.keyword) { + return; + } + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); + self.setTipVisible(nodes.length <= 0); + self.loaded(); + if (!hasNext) { + self.tip.invisible(); + } else { + self.tip.setLoaded(); + } + self.fireEvent(BI.Events.AFTERINIT); + }; + + function callback (nodes) { + if (self._stop === true) { + return; + } + self.nodes = $.fn.zTree.init(tree.element, setting, nodes); + } + + BI.delay(function () { + o.itemsCreator(op, complete); + }, 100); + }, + + // 生成树方法 + stroke: function (config) { + var o = this.options; + delete o.paras.keyword; + BI.extend(o.paras, config); + delete o.paras.lastSearchValue; + var setting = this._configSetting(); + this._initTree(setting, o.paras.keyword); + } +}); + +BI.shortcut("bi.list_part_tree", BI.ListPartTree);BI.prepares.push(function () { BI.Resizers = new BI.ResizeController(); BI.Layers = new BI.LayerController(); BI.Maskers = new BI.MaskersController(); @@ -49788,6 +50115,8 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* makeChkClass: function(setting, node) { var checkedKey = setting.data.key.checked, c = consts.checkbox, r = consts.radio, + checkboxType = setting.check.chkboxType; + var notEffectByOtherNode = (checkboxType.Y === "" && checkboxType.N === ""); fullStyle = ""; if (node.chkDisabled === true) { fullStyle = c.DISABLED; @@ -49796,7 +50125,7 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* } else if (setting.check.chkStyle == r.STYLE) { fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART; } else { - fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART); + fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) || notEffectByOtherNode ? c.FULL:c.PART) : ((node.check_Child_State < 1 || notEffectByOtherNode)? c.FULL:c.PART); } var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle; chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; @@ -59145,6 +59474,86 @@ BI.DisplayTree = BI.inherit(BI.TreeView, { BI.DisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.display_tree", BI.DisplayTree);/** + * guy + * 异步树 + * @class BI.ListListDisplayTree + * @extends BI.TreeView + */ +BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListDisplayTree.superclass._defaultConfig.apply(this, arguments), { + extraCls: "bi-list-display-tree" + }); + }, + _init: function () { + BI.ListDisplayTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var setting = { + view: { + selectedMulti: false, + dblClickExpand: false, + showIcon: false, + nameIsHTML: true, + showTitle: false, + fontCss: getFont + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + callback: { + beforeCollapse: beforeCollapse + } + }; + + function beforeCollapse(treeId, treeNode) { + return false; + } + + function getFont(treeId, node) { + return node.font ? node.font : {color: "#999999"}; + } + + return setting; + }, + + _dealWidthNodes: function (nodes) { + nodes = BI.ListDisplayTree.superclass._dealWidthNodes.apply(this, arguments); + var self = this, o = this.options; + BI.each(nodes, function (i, node) { + node.isParent = node.isParent || node.parent; + if (node.text == null) { + if (node.count > 0) { + node.text = node.value + "(" + BI.i18nText("BI-Basic_Altogether") + node.count + BI.i18nText("BI-Basic_Count") + ")"; + } + } + if(node.isLeaf === true) { + node.font = {color: "#3d4d66"}; + } + }); + return nodes; + }, + + initTree: function (nodes, setting) { + var setting = setting || this._configSetting(); + this.nodes = $.fn.zTree.init(this.tree.element, setting, nodes); + }, + + destroy: function () { + BI.ListDisplayTree.superclass.destroy.apply(this, arguments); + } +}); +BI.ListDisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.shortcut("bi.list_display_tree", BI.ListDisplayTree);/** * 简单的多选树 * * Created by GUY on 2016/2/16. @@ -72377,7 +72786,10 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-multi-tree-check-pane bi-background", - onClickContinueSelect: BI.emptyFn + onClickContinueSelect: BI.emptyFn, + el: { + type: "bi.display_tree" + } }); }, @@ -72419,7 +72831,7 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { }] }); - this.display = BI.createWidget({ + this.display = BI.createWidget(opts.el, { type: "bi.display_tree", cls: "bi-multi-tree-display", itemsCreator: function (op, callback) { @@ -73029,6 +73441,300 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeListCombo + * @extends BI.Single + */ + +BI.MultiTreeListCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-list-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeListCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || []}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_list_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + el: { + type: "bi.list_part_tree" + }, + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + el: { + type: "bi.list_display_tree" + }, + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + el: { + type: "bi.list_async_tree" + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : [] + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: []}; + } + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || []; + this.combo.setValue({ + value: v || [] + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeListCombo.EVENT_CONFIRM = "MultiTreeListCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -73041,24 +73747,27 @@ BI.MultiTreePopup = BI.inherit(BI.Pane, { maxWidth: "auto", minWidth: 100, maxHeight: 400, - onLoaded: BI.emptyFn + onLoaded: BI.emptyFn, + el: { + type: "bi.async_tree" + } }); }, _init: function () { BI.MultiTreePopup.superclass._init.apply(this, arguments); - var self = this, opts = this.options; + var self = this, opts = this.options, v = opts.value; this.selectedValues = {}; - this.tree = BI.createWidget({ + this.tree = BI.createWidget(opts.el, { type: "bi.async_tree", height: 400, cls: "popup-view-tree", itemsCreator: opts.itemsCreator, onLoaded: opts.onLoaded, - value: opts.value || {} + value: v.value || {} }); this.popupView = BI.createWidget({ @@ -73126,79 +73835,6 @@ BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** - * - * 在搜索框中输入文本弹出的面板 - * @class BI.MultiTreeSearchPane - * @extends BI.Pane - */ - -BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { - - _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-search-pane bi-card", - itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn - }); - }, - - _init: function () { - BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); - - var self = this, opts = this.options; - - this.partTree = BI.createWidget({ - type: "bi.part_tree", - element: this, - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, callback); - }, - value: opts.value - }); - - this.partTree.on(BI.Controller.EVENT_CHANGE, function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - }); - - this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); - }); - }, - - hasChecked: function () { - return this.partTree.hasChecked(); - }, - - setValue: function (v) { - this.setSelectedValue(v.value); - }, - - setSelectedValue: function (v) { - v || (v = {}); - this.partTree.setSelectedValue(v); - }, - - getValue: function () { - return this.partTree.getValue(); - }, - - empty: function () { - this.partTree.empty(); - }, - - populate: function (op) { - this.partTree.stroke.apply(this.partTree, arguments); - } -}); - -BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; - -BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; - -BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** * 查看已选按钮 * Created by guy on 15/11/3. * @class BI.MultiTreeCheckSelectedButton @@ -73280,52 +73916,65 @@ BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { props: { baseCls: "bi-multi-tree-search-insert-pane bi-card", itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + keywordGetter: BI.emptyFn, + el: { + type: "bi.part_tree" + } }, render: function () { var self = this, opts = this.options; return { - type: "bi.vertical", + type: "bi.absolute", items: [{ - type: "bi.text_button", - invisible: true, - ref: function (_ref) { - self.addTip = _ref; + el: { + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } }, - text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), - height: this.constants.height, - cls: "bi-high-light", - hgap: 5, - handler: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); - } + top: 5, + left: 0, + right: 0 }, { - type: "bi.part_tree", - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, function (res) { - callback(res); - self.setKeyword(opts.keywordGetter(), res.items); - }); - }, - ref: function (_ref) { - self.partTree = _ref; - }, - value: opts.value, - listeners: [{ - eventName: BI.Controller.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - } - }, { - eventName: BI.TreeView.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); - } - }] + el: BI.extend({ + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }, opts.el), + left: 0, + top: 0, + bottom: 0, + right: 0 }] }; }, @@ -73370,6 +74019,236 @@ BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-search-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }); + }, + + _init: function () { + BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); + + var self = this, opts = this.options; + + this.partTree = BI.createWidget({ + type: "bi.part_tree", + element: this, + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, callback); + }, + value: opts.value + }); + + this.partTree.on(BI.Controller.EVENT_CHANGE, function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + + this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + }); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; + +BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiListTreeSearcher + * @extends Widget + */ +BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, + isAutoSync: false, + onSearch: function (op, callback) { + callback({ + keyword: self.editor.getValue() + }); + }, + el: this.editor, + + popup: BI.extend({ + type: "bi.multi_tree_search_pane", + keywordGetter: function () { + return self.editor.getValue(); + }, + itemsCreator: function (op, callback) { + op.keyword = self.editor.getValue(); + o.itemsCreator(op, callback); + }, + value: o.value + }, o.popup), + + adapter: o.adapter, + masker: o.masker + }); + this.searcher.on(BI.Searcher.EVENT_START, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); + }); + this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { + if (this.hasMatched()) { + + } + self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); + }); + this.searcher.on(BI.Searcher.EVENT_STOP, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); + }); + this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); + }); + if (BI.isNotNull(o.value)) { + this.setState(o.value); + } + }, + + adjustView: function () { + this.searcher.adjustView(); + }, + + setAdapter: function (adapter) { + this.searcher.setAdapter(adapter); + }, + + isSearching: function () { + return this.searcher.isSearching(); + }, + + stopSearch: function () { + this.searcher.stopSearch(); + }, + + getKeyword: function () { + return this.editor.getValue(); + }, + + hasMatched: function () { + return this.searcher.hasMatched(); + }, + + hasChecked: function () { + return this.searcher.getView() && this.searcher.getView().hasChecked(); + }, + + setState: function (ob) { + var o = this.options; + ob || (ob = {}); + ob.value || (ob.value = []); + var count = 0; + if (BI.isNumber(ob)) { + this.editor.setState(ob); + } else if (BI.size(ob.value) === 0) { + this.editor.setState(BI.Selection.None); + } else { + var text = ""; + BI.each(ob.value, function (idx, path) { + var childValue = BI.last(path); + text += (o.valueFormatter(childValue + "") || childValue) + "; "; + count++; + }); + + if (count > 20) { + this.editor.setState(BI.Selection.Multi); + } else { + this.editor.setState(text); + } + } + }, + + setValue: function (ob) { + this.setState(ob); + this.searcher.setValue(ob); + }, + + getKey: function () { + return this.editor.getValue(); + }, + + getValue: function () { + return this.searcher.getValue(); + }, + + populate: function (items) { + this.searcher.populate.apply(this.searcher, arguments); + } +}); + +BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; +BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; +BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; +BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; +BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -83864,7 +84743,320 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { _getChildCount: function (parentValues) { return this._getChildren(parentValues).length; } +});BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { + + _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: BI.values(result) + }); + + function doCheck(parentValues, node, selected) { + BI.each(selected, function (idx, path) { + BI.each(path, function (id, value) { + var nodeValue = value; + var node = self._getTreeNode(path.slice(0, id), nodeValue); + // 找不到就是新增值 + if (BI.isNull(node)) { + createOneJson({ + id: BI.UUID(), + text: nodeValue, + value: nodeValue, + isLeaf: true + }, BI.UUID()); + } else { + if(!BI.has(result, node.id)) { + createOneJson(node, node.parent && node.parent.id); + } + result[node.id].isLeaf = id === path.length - 1; + } + }); + }); + } + + function createOneJson(node, pId, leaf) { + result[node.id] = { + id: node.id, + pId: pId, + text: node.text, + value: node.value, + open: true, + isLeaf: leaf + }; + } + }, + + _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, result); + } else if (output.length === self._const.perPage) { + var find = nodeSearch(1, [], children[i].value, []); + } + 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, result) { + if (self._isMatch(parentValues, current, keyword)) { + var checked = isSelected(current); + createOneJson(parentValues, current, false, checked, true, result); + return [true, checked]; + } + var newParents = BI.clone(parentValues); + newParents.push(current); + var children = self._getChildren(newParents); + + var can = false, checked = false; + + BI.each(children, function (i, child) { + var state = nodeSearch(deep + 1, newParents, child.value, result); + if (state[1] === true) { + checked = true; + } + if (state[0] === true) { + can = true; + } + }); + if (can === true) { + checked = isSelected(current); + createOneJson(parentValues, current, true, checked, false, result); + } + return [can, checked]; + } + + function createOneJson(parentValues, value, isOpen, checked, 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: false, + 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(value) { + return BI.any(selectedValues, function (idx, array) { + return BI.last(array) === value; + }); + } + + 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; + var result = []; + var times = op.times; + var parentValues = op.parentValues || []; + var selectedValues = op.selectedValues || []; + var valueMap = dealWidthSelectedValue(selectedValues); + var nodes = this._getChildren(parentValues); + for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { + var checked = BI.has(valueMap, nodes[i].value); + 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: checked, + halfCheck: false + }); + } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + 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 dealWidthSelectedValue(selectedValues) { + var valueMap = {}; + BI.each(selectedValues, function (idx, v) { + valueMap[BI.last(v)] = [2, 0]; + }); + return valueMap; + } + }, + + _getAddedValueNode: function (parentValues, selectedValues) { + var nodes = this._getChildren(parentValues); + var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { + return array.length === 1; + })); + return BI.map(BI.difference(values, 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 + }; + }); + } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.ListTreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-list-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_list_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "ListTreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 * * Created by GUY on 2015/10/29. diff --git a/dist/fineui.js b/dist/fineui.js index e49d3e252..d99cbfd13 100644 --- a/dist/fineui.js +++ b/dist/fineui.js @@ -38567,7 +38567,14 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var name = this._getNodeValue(treeNode); if (treeNode.checked === true) { - BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + this._buildTree(self.options.paras.selectedValues, BI.concat(parentValues, name)); + o.itemsCreator({ + type: BI.TreeView.REQ_TYPE_ADJUST_DATA, + selectedValues: self.options.paras.selectedValues + }, function (res) { + self.options.paras.selectedValues = res; + BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + }); } else { // 如果选中的值中不存在该值不处理 // 因为反正是不选中,没必要管 @@ -38669,12 +38676,6 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { getValue: function () { var o = this.options; var result = BI.PartTree.superclass.getValue.apply(this, arguments); - o.itemsCreator({ - type: BI.TreeView.REQ_TYPE_ADJUST_DATA, - selectedValues: result - }, function (res) { - result = res; - }); return result; }, @@ -38689,7 +38690,333 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { } }); -BI.shortcut("bi.part_tree", BI.PartTree);BI.prepares.push(function () { +BI.shortcut("bi.part_tree", BI.PartTree);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为[["A"], ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListTreeView + * @extends BI.TreeView + */ +BI.ListTreeView = BI.inherit(BI.TreeView, { + + _constants: { + SPLIT: "<|>" + }, + + _defaultConfig: function () { + return BI.extend(BI.ListTreeView.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListTreeView.superclass._init.apply(this, arguments); + var o = this.options; + this.storeValue = o.value || {}; + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + onClick: onClick + } + }; + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + _selectTreeNode: function (treeId, treeNode) { + this._checkValue(treeNode, treeNode.checked); + BI.ListTreeView.superclass._selectTreeNode.apply(this, arguments); + }, + + _transArrayToMap: function (treeArrays) { + var self = this; + var map = {}; + BI.each(treeArrays, function (idx, array) { + var key = array.join(self._constants.SPLIT); + map[key] = true; + }); + return map; + }, + + _transMapToArray: function (treeMap) { + var self = this; + var array = []; + BI.each(treeMap, function (key) { + var item = key.split(self._constants.SPLIT); + array.push(item); + }); + return array; + }, + + _checkValue: function (treeNode, checked) { + var key = BI.concat(this._getParentValues(treeNode), this._getNodeValue(treeNode)).join(this._constants.SPLIT); + if(checked) { + this.storeValue[key] = true; + } else { + delete this.storeValue[key]; + } + }, + + setSelectedValue: function (value) { + this.options.paras.selectedValues = value || []; + this.storeValue = this._transArrayToMap(value); + }, + + getValue: function () { + return this._transMapToArray(this.storeValue); + } +}); + +BI.shortcut("bi.list_tree_view", BI.ListTreeView);/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为["A", ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListListAsyncTree + * @extends BI.TreeView + */ +BI.ListAsyncTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListAsyncTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListAsyncTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 + otherParam: BI.cjkEncodeDO(paras) + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + beforeExpand: beforeExpand, + beforeCheck: beforeCheck, + onClick: onClick + } + }; + + function beforeCheck (treeId, treeNode) { + treeNode.half = false; + } + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function beforeExpand (treeId, treeNode) { + self._beforeExpandNode(treeId, treeNode); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + // 展开节点 + _beforeExpandNode: function (treeId, treeNode) { + var self = this, o = this.options; + var parentValues = treeNode.parentValues || self._getParentValues(treeNode); + var op = BI.extend({}, o.paras, { + id: treeNode.id, + times: 1, + parentValues: parentValues.concat(this._getNodeValue(treeNode)) + }); + var complete = function (d) { + var nodes = d.items || []; + if (nodes.length > 0) { + callback(self._dealWidthNodes(nodes), !!d.hasNext); + } + }; + var times = 1; + + function callback (nodes, hasNext) { + self.nodes.addNodes(treeNode, nodes); + // 展开节点是没有分页的 + if (hasNext === true) { + BI.delay(function () { + times++; + op.times = times; + o.itemsCreator(op, complete); + }, 100); + } + } + + if (!treeNode.children) { + setTimeout(function () { + o.itemsCreator(op, complete); + }, 17); + } + }, + + hasChecked: function () { + return !BI.isEmpty(this.options.paras.selectedValues) || BI.ListAsyncTree.superclass.hasChecked.apply(this, arguments); + }, + + // 生成树方法 + stroke: function (config) { + delete this.options.keyword; + BI.extend(this.options.paras, config); + var setting = this._configSetting(); + this._initTree(setting); + } +}); + +BI.shortcut("bi.list_async_tree", BI.ListAsyncTree);/** + * guy + * 局部树,两个请求树, 第一个请求构造树,第二个请求获取节点 + * @class BI.ListPartTree + * @extends BI.AsyncTree + */ +BI.ListPartTree = BI.inherit(BI.ListAsyncTree, { + _defaultConfig: function () { + return BI.extend(BI.ListPartTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + + _init: function () { + BI.ListPartTree.superclass._init.apply(this, arguments); + }, + + _loadMore: function () { + var self = this, o = this.options; + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: ++this.times + }); + this.tip.setLoading(); + o.itemsCreator(op, function (d) { + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + if (self._stop === true) { + return; + } + if (!hasNext) { + self.tip.setEnd(); + } else { + self.tip.setLoaded(); + } + if (nodes.length > 0) { + self.nodes.addNodes(null, self._dealWidthNodes(nodes)); + } + }); + }, + + _initTree: function (setting, keyword) { + var self = this, o = this.options; + this.times = 1; + var tree = this.tree; + tree.empty(); + self.tip.setVisible(false); + this.loading(); + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: this.times + }); + var complete = function (d) { + if (self._stop === true || keyword != o.paras.keyword) { + return; + } + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); + self.setTipVisible(nodes.length <= 0); + self.loaded(); + if (!hasNext) { + self.tip.invisible(); + } else { + self.tip.setLoaded(); + } + self.fireEvent(BI.Events.AFTERINIT); + }; + + function callback (nodes) { + if (self._stop === true) { + return; + } + self.nodes = $.fn.zTree.init(tree.element, setting, nodes); + } + + BI.delay(function () { + o.itemsCreator(op, complete); + }, 100); + }, + + // 生成树方法 + stroke: function (config) { + var o = this.options; + delete o.paras.keyword; + BI.extend(o.paras, config); + delete o.paras.lastSearchValue; + var setting = this._configSetting(); + this._initTree(setting, o.paras.keyword); + } +}); + +BI.shortcut("bi.list_part_tree", BI.ListPartTree);BI.prepares.push(function () { BI.Resizers = new BI.ResizeController(); BI.Layers = new BI.LayerController(); BI.Maskers = new BI.MaskersController(); @@ -50192,6 +50519,8 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* makeChkClass: function(setting, node) { var checkedKey = setting.data.key.checked, c = consts.checkbox, r = consts.radio, + checkboxType = setting.check.chkboxType; + var notEffectByOtherNode = (checkboxType.Y === "" && checkboxType.N === ""); fullStyle = ""; if (node.chkDisabled === true) { fullStyle = c.DISABLED; @@ -50200,7 +50529,7 @@ BI.shortcut("bi.custom_tree", BI.CustomTree);/* } else if (setting.check.chkStyle == r.STYLE) { fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART; } else { - fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART); + fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) || notEffectByOtherNode ? c.FULL:c.PART) : ((node.check_Child_State < 1 || notEffectByOtherNode)? c.FULL:c.PART); } var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle; chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; @@ -59549,6 +59878,86 @@ BI.DisplayTree = BI.inherit(BI.TreeView, { BI.DisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; BI.shortcut("bi.display_tree", BI.DisplayTree);/** + * guy + * 异步树 + * @class BI.ListListDisplayTree + * @extends BI.TreeView + */ +BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListDisplayTree.superclass._defaultConfig.apply(this, arguments), { + extraCls: "bi-list-display-tree" + }); + }, + _init: function () { + BI.ListDisplayTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var setting = { + view: { + selectedMulti: false, + dblClickExpand: false, + showIcon: false, + nameIsHTML: true, + showTitle: false, + fontCss: getFont + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + callback: { + beforeCollapse: beforeCollapse + } + }; + + function beforeCollapse(treeId, treeNode) { + return false; + } + + function getFont(treeId, node) { + return node.font ? node.font : {color: "#999999"}; + } + + return setting; + }, + + _dealWidthNodes: function (nodes) { + nodes = BI.ListDisplayTree.superclass._dealWidthNodes.apply(this, arguments); + var self = this, o = this.options; + BI.each(nodes, function (i, node) { + node.isParent = node.isParent || node.parent; + if (node.text == null) { + if (node.count > 0) { + node.text = node.value + "(" + BI.i18nText("BI-Basic_Altogether") + node.count + BI.i18nText("BI-Basic_Count") + ")"; + } + } + if(node.isLeaf === true) { + node.font = {color: "#3d4d66"}; + } + }); + return nodes; + }, + + initTree: function (nodes, setting) { + var setting = setting || this._configSetting(); + this.nodes = $.fn.zTree.init(this.tree.element, setting, nodes); + }, + + destroy: function () { + BI.ListDisplayTree.superclass.destroy.apply(this, arguments); + } +}); +BI.ListDisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.shortcut("bi.list_display_tree", BI.ListDisplayTree);/** * 简单的多选树 * * Created by GUY on 2016/2/16. @@ -72781,7 +73190,10 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-multi-tree-check-pane bi-background", - onClickContinueSelect: BI.emptyFn + onClickContinueSelect: BI.emptyFn, + el: { + type: "bi.display_tree" + } }); }, @@ -72823,7 +73235,7 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { }] }); - this.display = BI.createWidget({ + this.display = BI.createWidget(opts.el, { type: "bi.display_tree", cls: "bi-multi-tree-display", itemsCreator: function (op, callback) { @@ -73433,6 +73845,300 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeListCombo + * @extends BI.Single + */ + +BI.MultiTreeListCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-list-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeListCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || []}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_list_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + el: { + type: "bi.list_part_tree" + }, + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + el: { + type: "bi.list_display_tree" + }, + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + el: { + type: "bi.list_async_tree" + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : [] + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: []}; + } + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || []; + this.combo.setValue({ + value: v || [] + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeListCombo.EVENT_CONFIRM = "MultiTreeListCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo);/** * 带加载的多选下拉面板 * @class BI.MultiTreePopup * @extends BI.Pane @@ -73445,24 +74151,27 @@ BI.MultiTreePopup = BI.inherit(BI.Pane, { maxWidth: "auto", minWidth: 100, maxHeight: 400, - onLoaded: BI.emptyFn + onLoaded: BI.emptyFn, + el: { + type: "bi.async_tree" + } }); }, _init: function () { BI.MultiTreePopup.superclass._init.apply(this, arguments); - var self = this, opts = this.options; + var self = this, opts = this.options, v = opts.value; this.selectedValues = {}; - this.tree = BI.createWidget({ + this.tree = BI.createWidget(opts.el, { type: "bi.async_tree", height: 400, cls: "popup-view-tree", itemsCreator: opts.itemsCreator, onLoaded: opts.onLoaded, - value: opts.value || {} + value: v.value || {} }); this.popupView = BI.createWidget({ @@ -73530,79 +74239,6 @@ BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** - * - * 在搜索框中输入文本弹出的面板 - * @class BI.MultiTreeSearchPane - * @extends BI.Pane - */ - -BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { - - _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-search-pane bi-card", - itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn - }); - }, - - _init: function () { - BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); - - var self = this, opts = this.options; - - this.partTree = BI.createWidget({ - type: "bi.part_tree", - element: this, - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, callback); - }, - value: opts.value - }); - - this.partTree.on(BI.Controller.EVENT_CHANGE, function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - }); - - this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); - }); - }, - - hasChecked: function () { - return this.partTree.hasChecked(); - }, - - setValue: function (v) { - this.setSelectedValue(v.value); - }, - - setSelectedValue: function (v) { - v || (v = {}); - this.partTree.setSelectedValue(v); - }, - - getValue: function () { - return this.partTree.getValue(); - }, - - empty: function () { - this.partTree.empty(); - }, - - populate: function (op) { - this.partTree.stroke.apply(this.partTree, arguments); - } -}); - -BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; - -BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; - -BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** * 查看已选按钮 * Created by guy on 15/11/3. * @class BI.MultiTreeCheckSelectedButton @@ -73684,52 +74320,65 @@ BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { props: { baseCls: "bi-multi-tree-search-insert-pane bi-card", itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + keywordGetter: BI.emptyFn, + el: { + type: "bi.part_tree" + } }, render: function () { var self = this, opts = this.options; return { - type: "bi.vertical", + type: "bi.absolute", items: [{ - type: "bi.text_button", - invisible: true, - ref: function (_ref) { - self.addTip = _ref; + el: { + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } }, - text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), - height: this.constants.height, - cls: "bi-high-light", - hgap: 5, - handler: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); - } + top: 5, + left: 0, + right: 0 }, { - type: "bi.part_tree", - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, function (res) { - callback(res); - self.setKeyword(opts.keywordGetter(), res.items); - }); - }, - ref: function (_ref) { - self.partTree = _ref; - }, - value: opts.value, - listeners: [{ - eventName: BI.Controller.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - } - }, { - eventName: BI.TreeView.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); - } - }] + el: BI.extend({ + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }, opts.el), + left: 0, + top: 0, + bottom: 0, + right: 0 }] }; }, @@ -73774,6 +74423,236 @@ BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchPane + * @extends BI.Pane + */ + +BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-search-pane bi-card", + itemsCreator: BI.emptyFn, + keywordGetter: BI.emptyFn + }); + }, + + _init: function () { + BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); + + var self = this, opts = this.options; + + this.partTree = BI.createWidget({ + type: "bi.part_tree", + element: this, + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, callback); + }, + value: opts.value + }); + + this.partTree.on(BI.Controller.EVENT_CHANGE, function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + + this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + }); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; + +BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiListTreeSearcher + * @extends Widget + */ +BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, + isAutoSync: false, + onSearch: function (op, callback) { + callback({ + keyword: self.editor.getValue() + }); + }, + el: this.editor, + + popup: BI.extend({ + type: "bi.multi_tree_search_pane", + keywordGetter: function () { + return self.editor.getValue(); + }, + itemsCreator: function (op, callback) { + op.keyword = self.editor.getValue(); + o.itemsCreator(op, callback); + }, + value: o.value + }, o.popup), + + adapter: o.adapter, + masker: o.masker + }); + this.searcher.on(BI.Searcher.EVENT_START, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); + }); + this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { + if (this.hasMatched()) { + + } + self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); + }); + this.searcher.on(BI.Searcher.EVENT_STOP, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); + }); + this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); + }); + if (BI.isNotNull(o.value)) { + this.setState(o.value); + } + }, + + adjustView: function () { + this.searcher.adjustView(); + }, + + setAdapter: function (adapter) { + this.searcher.setAdapter(adapter); + }, + + isSearching: function () { + return this.searcher.isSearching(); + }, + + stopSearch: function () { + this.searcher.stopSearch(); + }, + + getKeyword: function () { + return this.editor.getValue(); + }, + + hasMatched: function () { + return this.searcher.hasMatched(); + }, + + hasChecked: function () { + return this.searcher.getView() && this.searcher.getView().hasChecked(); + }, + + setState: function (ob) { + var o = this.options; + ob || (ob = {}); + ob.value || (ob.value = []); + var count = 0; + if (BI.isNumber(ob)) { + this.editor.setState(ob); + } else if (BI.size(ob.value) === 0) { + this.editor.setState(BI.Selection.None); + } else { + var text = ""; + BI.each(ob.value, function (idx, path) { + var childValue = BI.last(path); + text += (o.valueFormatter(childValue + "") || childValue) + "; "; + count++; + }); + + if (count > 20) { + this.editor.setState(BI.Selection.Multi); + } else { + this.editor.setState(text); + } + } + }, + + setValue: function (ob) { + this.setState(ob); + this.searcher.setValue(ob); + }, + + getKey: function () { + return this.editor.getValue(); + }, + + getValue: function () { + return this.searcher.getValue(); + }, + + populate: function (items) { + this.searcher.populate.apply(this.searcher, arguments); + } +}); + +BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; +BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; +BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; +BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; +BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher);/** * searcher * Created by guy on 15/11/3. * @class BI.MultiTreeSearcher @@ -84268,7 +85147,320 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { _getChildCount: function (parentValues) { return this._getChildren(parentValues).length; } +});BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { + + _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: BI.values(result) + }); + + function doCheck(parentValues, node, selected) { + BI.each(selected, function (idx, path) { + BI.each(path, function (id, value) { + var nodeValue = value; + var node = self._getTreeNode(path.slice(0, id), nodeValue); + // 找不到就是新增值 + if (BI.isNull(node)) { + createOneJson({ + id: BI.UUID(), + text: nodeValue, + value: nodeValue, + isLeaf: true + }, BI.UUID()); + } else { + if(!BI.has(result, node.id)) { + createOneJson(node, node.parent && node.parent.id); + } + result[node.id].isLeaf = id === path.length - 1; + } + }); + }); + } + + function createOneJson(node, pId, leaf) { + result[node.id] = { + id: node.id, + pId: pId, + text: node.text, + value: node.value, + open: true, + isLeaf: leaf + }; + } + }, + + _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, result); + } else if (output.length === self._const.perPage) { + var find = nodeSearch(1, [], children[i].value, []); + } + 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, result) { + if (self._isMatch(parentValues, current, keyword)) { + var checked = isSelected(current); + createOneJson(parentValues, current, false, checked, true, result); + return [true, checked]; + } + var newParents = BI.clone(parentValues); + newParents.push(current); + var children = self._getChildren(newParents); + + var can = false, checked = false; + + BI.each(children, function (i, child) { + var state = nodeSearch(deep + 1, newParents, child.value, result); + if (state[1] === true) { + checked = true; + } + if (state[0] === true) { + can = true; + } + }); + if (can === true) { + checked = isSelected(current); + createOneJson(parentValues, current, true, checked, false, result); + } + return [can, checked]; + } + + function createOneJson(parentValues, value, isOpen, checked, 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: false, + 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(value) { + return BI.any(selectedValues, function (idx, array) { + return BI.last(array) === value; + }); + } + + 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; + var result = []; + var times = op.times; + var parentValues = op.parentValues || []; + var selectedValues = op.selectedValues || []; + var valueMap = dealWidthSelectedValue(selectedValues); + var nodes = this._getChildren(parentValues); + for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { + var checked = BI.has(valueMap, nodes[i].value); + 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: checked, + halfCheck: false + }); + } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + 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 dealWidthSelectedValue(selectedValues) { + var valueMap = {}; + BI.each(selectedValues, function (idx, v) { + valueMap[BI.last(v)] = [2, 0]; + }); + return valueMap; + } + }, + + _getAddedValueNode: function (parentValues, selectedValues) { + var nodes = this._getChildren(parentValues); + var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { + return array.length === 1; + })); + return BI.map(BI.difference(values, 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 + }; + }); + } });/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.ListTreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-list-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_list_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "ListTreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 * * Created by GUY on 2015/10/29. diff --git a/dist/fineui_without_jquery_polyfill.js b/dist/fineui_without_jquery_polyfill.js index 12a530339..8adf3980e 100644 --- a/dist/fineui_without_jquery_polyfill.js +++ b/dist/fineui_without_jquery_polyfill.js @@ -55581,7 +55581,10 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-multi-tree-check-pane bi-background", - onClickContinueSelect: BI.emptyFn + onClickContinueSelect: BI.emptyFn, + el: { + type: "bi.display_tree" + } }); }, @@ -55623,7 +55626,7 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { }] }); - this.display = BI.createWidget({ + this.display = BI.createWidget(opts.el, { type: "bi.display_tree", cls: "bi-multi-tree-display", itemsCreator: function (op, callback) { @@ -56233,176 +56236,400 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 带加载的多选下拉面板 - * @class BI.MultiTreePopup - * @extends BI.Pane + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeListCombo + * @extends BI.Single */ -BI.MultiTreePopup = BI.inherit(BI.Pane, { + +BI.MultiTreeListCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, _defaultConfig: function () { - return BI.extend(BI.MultiTreePopup.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-popup", - maxWidth: "auto", - minWidth: 100, - maxHeight: 400, - onLoaded: BI.emptyFn + return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-list-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 }); }, _init: function () { - BI.MultiTreePopup.superclass._init.apply(this, arguments); - - var self = this, opts = this.options; + BI.MultiTreeListCombo.superclass._init.apply(this, arguments); - this.selectedValues = {}; + var self = this, o = this.options; - this.tree = BI.createWidget({ - type: "bi.async_tree", - height: 400, - cls: "popup-view-tree", - itemsCreator: opts.itemsCreator, - onLoaded: opts.onLoaded, - value: opts.value || {} - }); + var isInit = false; + var want2showCounter = false; - this.popupView = BI.createWidget({ - type: "bi.multi_popup_view", - element: this, - stopPropagation: false, - maxWidth: opts.maxWidth, - minWidth: opts.minWidth, - maxHeight: opts.maxHeight, - buttons: [BI.i18nText("BI-Basic_Clears"), BI.i18nText("BI-Basic_Sure")], - el: this.tree - }); + this.storeValue = {value: o.value || []}; - this.popupView.on(BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON, function (index) { - switch (index) { - case 0: - self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CLEAR); - break; - case 1: - self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CONFIRM); - break; - } - }); + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_list_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + el: { + type: "bi.list_part_tree" + }, + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + el: { + type: "bi.list_display_tree" + }, + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} - this.tree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreePopup.EVENT_CHANGE); }); - this.tree.on(BI.TreeView.EVENT_AFTERINIT, function () { - self.fireEvent(BI.MultiTreePopup.EVENT_AFTERINIT); + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + el: { + type: "bi.list_async_tree" + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : [] + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } }); - }, - - getValue: function () { - return this.tree.getValue(); - }, + var change = false; + var clear = false; // 标识当前是否点击了清空 - setValue: function (v) { - v || (v = {}); - this.tree.setSelectedValue(v.value); - }, + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; - populate: function (config) { - this.tree.stroke(config); - }, + var isPopupView = function () { + return self.combo.isViewVisible(); + }; - hasChecked: function () { - return this.tree.hasChecked(); - }, + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); - resetHeight: function (h) { - this.popupView.resetHeight(h); - }, + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } - resetWidth: function (w) { - this.popupView.resetWidth(w); - } -}); + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); -BI.MultiTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; -BI.MultiTreePopup.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreePopup.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; -BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); -BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** - * - * 在搜索框中输入文本弹出的面板 - * @class BI.MultiTreeSearchPane + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: []}; + } + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || []; + this.combo.setValue({ + value: v || [] + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeListCombo.EVENT_CONFIRM = "MultiTreeListCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo);/** + * 带加载的多选下拉面板 + * @class BI.MultiTreePopup * @extends BI.Pane */ - -BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { +BI.MultiTreePopup = BI.inherit(BI.Pane, { _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-search-pane bi-card", - itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + return BI.extend(BI.MultiTreePopup.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-popup", + maxWidth: "auto", + minWidth: 100, + maxHeight: 400, + onLoaded: BI.emptyFn, + el: { + type: "bi.async_tree" + } }); }, _init: function () { - BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); + BI.MultiTreePopup.superclass._init.apply(this, arguments); - var self = this, opts = this.options; + var self = this, opts = this.options, v = opts.value; - this.partTree = BI.createWidget({ - type: "bi.part_tree", + this.selectedValues = {}; + + this.tree = BI.createWidget(opts.el, { + type: "bi.async_tree", + height: 400, + cls: "popup-view-tree", + itemsCreator: opts.itemsCreator, + onLoaded: opts.onLoaded, + value: v.value || {} + }); + + this.popupView = BI.createWidget({ + type: "bi.multi_popup_view", element: this, - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, callback); - }, - value: opts.value + stopPropagation: false, + maxWidth: opts.maxWidth, + minWidth: opts.minWidth, + maxHeight: opts.maxHeight, + buttons: [BI.i18nText("BI-Basic_Clears"), BI.i18nText("BI-Basic_Sure")], + el: this.tree }); - this.partTree.on(BI.Controller.EVENT_CHANGE, function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + this.popupView.on(BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON, function (index) { + switch (index) { + case 0: + self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CLEAR); + break; + case 1: + self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CONFIRM); + break; + } }); - this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + this.tree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreePopup.EVENT_CHANGE); + }); + + this.tree.on(BI.TreeView.EVENT_AFTERINIT, function () { + self.fireEvent(BI.MultiTreePopup.EVENT_AFTERINIT); }); + }, - hasChecked: function () { - return this.partTree.hasChecked(); + getValue: function () { + return this.tree.getValue(); }, setValue: function (v) { - this.setSelectedValue(v.value); + v || (v = {}); + this.tree.setSelectedValue(v.value); }, - setSelectedValue: function (v) { - v || (v = {}); - this.partTree.setSelectedValue(v); + populate: function (config) { + this.tree.stroke(config); }, - getValue: function () { - return this.partTree.getValue(); + hasChecked: function () { + return this.tree.hasChecked(); }, - empty: function () { - this.partTree.empty(); + resetHeight: function (h) { + this.popupView.resetHeight(h); }, - populate: function (op) { - this.partTree.stroke.apply(this.partTree, arguments); + resetWidth: function (w) { + this.popupView.resetWidth(w); } }); -BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiTreePopup.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreePopup.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; -BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; -BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** +BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** * 查看已选按钮 * Created by guy on 15/11/3. * @class BI.MultiTreeCheckSelectedButton @@ -56484,52 +56711,65 @@ BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { props: { baseCls: "bi-multi-tree-search-insert-pane bi-card", itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + keywordGetter: BI.emptyFn, + el: { + type: "bi.part_tree" + } }, render: function () { var self = this, opts = this.options; return { - type: "bi.vertical", + type: "bi.absolute", items: [{ - type: "bi.text_button", - invisible: true, - ref: function (_ref) { - self.addTip = _ref; + el: { + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } }, - text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), - height: this.constants.height, - cls: "bi-high-light", - hgap: 5, - handler: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); - } + top: 5, + left: 0, + right: 0 }, { - type: "bi.part_tree", - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, function (res) { - callback(res); - self.setKeyword(opts.keywordGetter(), res.items); - }); - }, - ref: function (_ref) { - self.partTree = _ref; - }, - value: opts.value, - listeners: [{ - eventName: BI.Controller.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - } - }, { - eventName: BI.TreeView.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); - } - }] + el: BI.extend({ + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }, opts.el), + left: 0, + top: 0, + bottom: 0, + right: 0 }] }; }, @@ -56574,38 +56814,268 @@ BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** - * searcher - * Created by guy on 15/11/3. - * @class BI.MultiTreeSearcher - * @extends Widget + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchPane + * @extends BI.Pane */ -BI.MultiTreeSearcher = BI.inherit(BI.Widget, { + +BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearcher.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-searcher", + return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-search-pane bi-card", itemsCreator: BI.emptyFn, - valueFormatter: function (v) { - return v; - }, - popup: {}, - - adapter: null, - masker: {} + keywordGetter: BI.emptyFn }); }, _init: function () { - BI.MultiTreeSearcher.superclass._init.apply(this, arguments); - var self = this, o = this.options; - this.editor = BI.createWidget({ - type: "bi.multi_select_editor", - height: o.height, - el: { - type: "bi.simple_state_editor", - height: o.height - } - }); + BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); + + var self = this, opts = this.options; + + this.partTree = BI.createWidget({ + type: "bi.part_tree", + element: this, + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, callback); + }, + value: opts.value + }); + + this.partTree.on(BI.Controller.EVENT_CHANGE, function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + + this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + }); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; + +BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiListTreeSearcher + * @extends Widget + */ +BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, + isAutoSync: false, + onSearch: function (op, callback) { + callback({ + keyword: self.editor.getValue() + }); + }, + el: this.editor, + + popup: BI.extend({ + type: "bi.multi_tree_search_pane", + keywordGetter: function () { + return self.editor.getValue(); + }, + itemsCreator: function (op, callback) { + op.keyword = self.editor.getValue(); + o.itemsCreator(op, callback); + }, + value: o.value + }, o.popup), + + adapter: o.adapter, + masker: o.masker + }); + this.searcher.on(BI.Searcher.EVENT_START, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); + }); + this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { + if (this.hasMatched()) { + + } + self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); + }); + this.searcher.on(BI.Searcher.EVENT_STOP, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); + }); + this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); + }); + if (BI.isNotNull(o.value)) { + this.setState(o.value); + } + }, + + adjustView: function () { + this.searcher.adjustView(); + }, + + setAdapter: function (adapter) { + this.searcher.setAdapter(adapter); + }, + + isSearching: function () { + return this.searcher.isSearching(); + }, + + stopSearch: function () { + this.searcher.stopSearch(); + }, + + getKeyword: function () { + return this.editor.getValue(); + }, + + hasMatched: function () { + return this.searcher.hasMatched(); + }, + + hasChecked: function () { + return this.searcher.getView() && this.searcher.getView().hasChecked(); + }, + + setState: function (ob) { + var o = this.options; + ob || (ob = {}); + ob.value || (ob.value = []); + var count = 0; + if (BI.isNumber(ob)) { + this.editor.setState(ob); + } else if (BI.size(ob.value) === 0) { + this.editor.setState(BI.Selection.None); + } else { + var text = ""; + BI.each(ob.value, function (idx, path) { + var childValue = BI.last(path); + text += (o.valueFormatter(childValue + "") || childValue) + "; "; + count++; + }); + + if (count > 20) { + this.editor.setState(BI.Selection.Multi); + } else { + this.editor.setState(text); + } + } + }, + + setValue: function (ob) { + this.setState(ob); + this.searcher.setValue(ob); + }, + + getKey: function () { + return this.editor.getValue(); + }, + + getValue: function () { + return this.searcher.getValue(); + }, + + populate: function (items) { + this.searcher.populate.apply(this.searcher, arguments); + } +}); + +BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; +BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; +BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; +BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; +BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiTreeSearcher + * @extends Widget + */ +BI.MultiTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); this.searcher = BI.createWidget({ type: "bi.searcher", @@ -66668,52 +67138,456 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return true; } } - return false; + 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; + 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 = dealWidthSelectedValue(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] + }); + } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + 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 dealWidthSelectedValue(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[value] = [1, BI.size(nextNames)]; + }); + return valueMap; + } + + function getCheckState(current, parentValues, valueMap, checkState) { + 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) { + check = BI.has(valueMap, current); + } else { + 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 node = this._getTreeNode(parentValues, value); + if (!node) { + return false; + } + var find = BI.Func.getSearchResult([node.text || node.value], keyword); + 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(); }, - _reqAdjustTreeNode: function (op, callback) { + _getChildCount: function (parentValues) { + return this._getChildren(parentValues).length; + } +});BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { + + _reqDisplayTreeNode: function (op, callback) { var self = this; - var result = []; + 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, []); + doCheck([], this.tree.getRoot(), selectedValues); - var jo = {}; - BI.each(result, function (i, strs) { - self._buildTree(jo, strs); + callback({ + items: BI.values(result) }); - 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; - } + function doCheck(parentValues, node, selected) { + BI.each(selected, function (idx, path) { + BI.each(path, function (id, value) { + var nodeValue = value; + var node = self._getTreeNode(path.slice(0, id), nodeValue); + // 找不到就是新增值 + if (BI.isNull(node)) { + createOneJson({ + id: BI.UUID(), + text: nodeValue, + value: nodeValue, + isLeaf: true + }, BI.UUID()); + } else { + if(!BI.has(result, node.id)) { + createOneJson(node, node.parent && node.parent.id); + } + result[node.id].isLeaf = id === path.length - 1; + } + }); }); - return can && isAllSelected(selected, parents); } - function isAllSelected(selected, parents) { - return BI.isEmpty(selected) || self._getChildCount(parents) === BI.size(selected); + function createOneJson(node, pId, leaf) { + result[node.id] = { + id: node.id, + pId: pId, + text: node.text, + value: node.value, + open: true, + isLeaf: leaf + }; } }, @@ -66748,9 +67622,9 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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); + var find = nodeSearch(1, [], children[i].value, result); } else if (output.length === self._const.perPage) { - var find = nodeSearch(1, [], children[i].value, false, []); + var find = nodeSearch(1, [], children[i].value, []); } if (find[0] === true) { output.push(children[i].value); @@ -66771,10 +67645,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return output; } - function nodeSearch(deep, parentValues, current, isAllSelect, result) { + function nodeSearch(deep, parentValues, current, result) { if (self._isMatch(parentValues, current, keyword)) { - var checked = isAllSelect || isSelected(parentValues, current); - createOneJson(parentValues, current, false, checked, !isAllSelect && isHalf(parentValues, current), true, result); + var checked = isSelected(current); + createOneJson(parentValues, current, false, checked, true, result); return [true, checked]; } var newParents = BI.clone(parentValues); @@ -66783,9 +67657,8 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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); + var state = nodeSearch(deep + 1, newParents, child.value, result); if (state[1] === true) { checked = true; } @@ -66794,13 +67667,13 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }); if (can === true) { - checked = isCurAllSelected || (isSelected(parentValues, current) && checked); - createOneJson(parentValues, current, true, checked, false, false, result); + checked = isSelected(current); + createOneJson(parentValues, current, true, checked, false, result); } return [can, checked]; } - function createOneJson(parentValues, value, isOpen, checked, half, flag, result) { + function createOneJson(parentValues, value, isOpen, checked, flag, result) { var node = self._getTreeNode(parentValues, value); result.push({ id: node.id, @@ -66811,7 +67684,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { isParent: node.getChildrenLength() > 0, open: isOpen, checked: checked, - halfCheck: half, + halfCheck: false, flag: flag }); } @@ -66844,15 +67717,9 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { }); } - 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 isSelected(value) { + return BI.any(selectedValues, function (idx, array) { + return BI.last(array) === value; }); } @@ -66876,16 +67743,12 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var self = this; 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 = dealWidthSelectedValue(parentValues, selectedValues); - // } + var selectedValues = op.selectedValues || []; + var valueMap = dealWidthSelectedValue(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); + var checked = BI.has(valueMap, nodes[i].value); result.push({ id: nodes[i].id, pId: nodes[i].pId, @@ -66893,8 +67756,8 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { text: nodes[i].text, times: 1, isParent: nodes[i].getChildrenLength() > 0, - checked: state[0], - halfCheck: state[1] + checked: checked, + halfCheck: false }); } // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 @@ -66908,68 +67771,21 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { }); }); - 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 dealWidthSelectedValue(parentValues, selectedValues) { + function dealWidthSelectedValue(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[value] = [1, BI.size(nextNames)]; + BI.each(selectedValues, function (idx, v) { + valueMap[BI.last(v)] = [2, 0]; }); return valueMap; } - - function getCheckState(current, parentValues, valueMap, checkState) { - 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) { - check = BI.has(valueMap, current); - } else { - 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) { + var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { + return array.length === 1; + })); + return BI.map(BI.difference(values, BI.map(nodes, "value")), function (idx, v) { return { id: BI.UUID(), pId: nodes.length > 0 ? nodes[0].pId : BI.UUID(), @@ -66981,94 +67797,61 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: false }; }); - }, + } +});/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.ListTreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { - _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; + _defaultConfig: function () { + return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-list-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); }, - _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]; - } - } + _init: function () { + BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); } - }, - - _buildTree: function (jo, values) { - var t = jo; - BI.each(values, function (i, v) { - if (!BI.has(t, v)) { - t[v] = {}; - } - t = t[v]; + this.combo = BI.createWidget({ + type: "bi.multi_tree_list_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height }); - }, - _isMatch: function (parentValues, value, keyword) { - var node = this._getTreeNode(parentValues, value); - if (!node) { - return false; - } - var find = BI.Func.getSearchResult([node.text || node.value], keyword); - return find.find.length > 0 || find.match.length > 0; + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); + }); }, - _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; + setValue: function (v) { + this.combo.setValue(v); }, - _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(); + getValue: function () { + return this.combo.getValue(); }, - _getChildCount: function (parentValues) { - return this._getChildren(parentValues).length; + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); } -});/** +}); +BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "ListTreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 * * Created by GUY on 2015/10/29. diff --git a/dist/resource.css b/dist/resource.css index cad505e88..fe83a374a 100644 --- a/dist/resource.css +++ b/dist/resource.css @@ -122,8 +122,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/half_selected.png'); + background: url('images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -168,8 +168,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/half_selected.png'); + background: url('images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { diff --git a/dist/widget.js b/dist/widget.js index a45f95b02..0a3250a50 100644 --- a/dist/widget.js +++ b/dist/widget.js @@ -12585,7 +12585,10 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-multi-tree-check-pane bi-background", - onClickContinueSelect: BI.emptyFn + onClickContinueSelect: BI.emptyFn, + el: { + type: "bi.display_tree" + } }); }, @@ -12627,7 +12630,7 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { }] }); - this.display = BI.createWidget({ + this.display = BI.createWidget(opts.el, { type: "bi.display_tree", cls: "bi-multi-tree-display", itemsCreator: function (op, callback) { @@ -13237,176 +13240,400 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 带加载的多选下拉面板 - * @class BI.MultiTreePopup - * @extends BI.Pane + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeListCombo + * @extends BI.Single */ -BI.MultiTreePopup = BI.inherit(BI.Pane, { + +BI.MultiTreeListCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, _defaultConfig: function () { - return BI.extend(BI.MultiTreePopup.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-popup", - maxWidth: "auto", - minWidth: 100, - maxHeight: 400, - onLoaded: BI.emptyFn + return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-list-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 }); }, _init: function () { - BI.MultiTreePopup.superclass._init.apply(this, arguments); - - var self = this, opts = this.options; + BI.MultiTreeListCombo.superclass._init.apply(this, arguments); - this.selectedValues = {}; + var self = this, o = this.options; - this.tree = BI.createWidget({ - type: "bi.async_tree", - height: 400, - cls: "popup-view-tree", - itemsCreator: opts.itemsCreator, - onLoaded: opts.onLoaded, - value: opts.value || {} - }); + var isInit = false; + var want2showCounter = false; - this.popupView = BI.createWidget({ - type: "bi.multi_popup_view", - element: this, - stopPropagation: false, - maxWidth: opts.maxWidth, - minWidth: opts.minWidth, - maxHeight: opts.maxHeight, - buttons: [BI.i18nText("BI-Basic_Clears"), BI.i18nText("BI-Basic_Sure")], - el: this.tree - }); + this.storeValue = {value: o.value || []}; - this.popupView.on(BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON, function (index) { - switch (index) { - case 0: - self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CLEAR); - break; - case 1: - self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CONFIRM); - break; - } - }); + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_list_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + el: { + type: "bi.list_part_tree" + }, + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + el: { + type: "bi.list_display_tree" + }, + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} - this.tree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreePopup.EVENT_CHANGE); }); - this.tree.on(BI.TreeView.EVENT_AFTERINIT, function () { - self.fireEvent(BI.MultiTreePopup.EVENT_AFTERINIT); + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + el: { + type: "bi.list_async_tree" + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : [] + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } }); - }, - - getValue: function () { - return this.tree.getValue(); - }, + var change = false; + var clear = false; // 标识当前是否点击了清空 - setValue: function (v) { - v || (v = {}); - this.tree.setSelectedValue(v.value); - }, + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; - populate: function (config) { - this.tree.stroke(config); - }, + var isPopupView = function () { + return self.combo.isViewVisible(); + }; - hasChecked: function () { - return this.tree.hasChecked(); - }, + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); - resetHeight: function (h) { - this.popupView.resetHeight(h); - }, + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } - resetWidth: function (w) { - this.popupView.resetWidth(w); - } -}); + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); -BI.MultiTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; -BI.MultiTreePopup.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreePopup.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; -BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); -BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** - * - * 在搜索框中输入文本弹出的面板 - * @class BI.MultiTreeSearchPane + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: []}; + } + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || []; + this.combo.setValue({ + value: v || [] + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeListCombo.EVENT_CONFIRM = "MultiTreeListCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo);/** + * 带加载的多选下拉面板 + * @class BI.MultiTreePopup * @extends BI.Pane */ - -BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { +BI.MultiTreePopup = BI.inherit(BI.Pane, { _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-search-pane bi-card", - itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + return BI.extend(BI.MultiTreePopup.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-popup", + maxWidth: "auto", + minWidth: 100, + maxHeight: 400, + onLoaded: BI.emptyFn, + el: { + type: "bi.async_tree" + } }); }, _init: function () { - BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); + BI.MultiTreePopup.superclass._init.apply(this, arguments); - var self = this, opts = this.options; + var self = this, opts = this.options, v = opts.value; - this.partTree = BI.createWidget({ - type: "bi.part_tree", + this.selectedValues = {}; + + this.tree = BI.createWidget(opts.el, { + type: "bi.async_tree", + height: 400, + cls: "popup-view-tree", + itemsCreator: opts.itemsCreator, + onLoaded: opts.onLoaded, + value: v.value || {} + }); + + this.popupView = BI.createWidget({ + type: "bi.multi_popup_view", element: this, - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, callback); - }, - value: opts.value + stopPropagation: false, + maxWidth: opts.maxWidth, + minWidth: opts.minWidth, + maxHeight: opts.maxHeight, + buttons: [BI.i18nText("BI-Basic_Clears"), BI.i18nText("BI-Basic_Sure")], + el: this.tree }); - this.partTree.on(BI.Controller.EVENT_CHANGE, function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + this.popupView.on(BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON, function (index) { + switch (index) { + case 0: + self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CLEAR); + break; + case 1: + self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CONFIRM); + break; + } }); - this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { - self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + this.tree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreePopup.EVENT_CHANGE); + }); + + this.tree.on(BI.TreeView.EVENT_AFTERINIT, function () { + self.fireEvent(BI.MultiTreePopup.EVENT_AFTERINIT); }); + }, - hasChecked: function () { - return this.partTree.hasChecked(); + getValue: function () { + return this.tree.getValue(); }, setValue: function (v) { - this.setSelectedValue(v.value); + v || (v = {}); + this.tree.setSelectedValue(v.value); }, - setSelectedValue: function (v) { - v || (v = {}); - this.partTree.setSelectedValue(v); + populate: function (config) { + this.tree.stroke(config); }, - getValue: function () { - return this.partTree.getValue(); + hasChecked: function () { + return this.tree.hasChecked(); }, - empty: function () { - this.partTree.empty(); + resetHeight: function (h) { + this.popupView.resetHeight(h); }, - populate: function (op) { - this.partTree.stroke.apply(this.partTree, arguments); + resetWidth: function (w) { + this.popupView.resetWidth(w); } }); -BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiTreePopup.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreePopup.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; +BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; -BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; -BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; -BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** +BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** * 查看已选按钮 * Created by guy on 15/11/3. * @class BI.MultiTreeCheckSelectedButton @@ -13488,52 +13715,65 @@ BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { props: { baseCls: "bi-multi-tree-search-insert-pane bi-card", itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + keywordGetter: BI.emptyFn, + el: { + type: "bi.part_tree" + } }, render: function () { var self = this, opts = this.options; return { - type: "bi.vertical", + type: "bi.absolute", items: [{ - type: "bi.text_button", - invisible: true, - ref: function (_ref) { - self.addTip = _ref; + el: { + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } }, - text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), - height: this.constants.height, - cls: "bi-high-light", - hgap: 5, - handler: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); - } + top: 5, + left: 0, + right: 0 }, { - type: "bi.part_tree", - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, function (res) { - callback(res); - self.setKeyword(opts.keywordGetter(), res.items); - }); - }, - ref: function (_ref) { - self.partTree = _ref; - }, - value: opts.value, - listeners: [{ - eventName: BI.Controller.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - } - }, { - eventName: BI.TreeView.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); - } - }] + el: BI.extend({ + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }, opts.el), + left: 0, + top: 0, + bottom: 0, + right: 0 }] }; }, @@ -13578,43 +13818,273 @@ BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** - * searcher - * Created by guy on 15/11/3. - * @class BI.MultiTreeSearcher - * @extends Widget + * + * 在搜索框中输入文本弹出的面板 + * @class BI.MultiTreeSearchPane + * @extends BI.Pane */ -BI.MultiTreeSearcher = BI.inherit(BI.Widget, { + +BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { _defaultConfig: function () { - return BI.extend(BI.MultiTreeSearcher.superclass._defaultConfig.apply(this, arguments), { - baseCls: "bi-multi-tree-searcher", + return BI.extend(BI.MultiTreeSearchPane.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-search-pane bi-card", itemsCreator: BI.emptyFn, - valueFormatter: function (v) { - return v; - }, - popup: {}, - - adapter: null, - masker: {} + keywordGetter: BI.emptyFn }); }, _init: function () { - BI.MultiTreeSearcher.superclass._init.apply(this, arguments); - var self = this, o = this.options; - this.editor = BI.createWidget({ - type: "bi.multi_select_editor", - height: o.height, - el: { - type: "bi.simple_state_editor", - height: o.height - } - }); + BI.MultiTreeSearchPane.superclass._init.apply(this, arguments); - this.searcher = BI.createWidget({ - type: "bi.searcher", + var self = this, opts = this.options; + + this.partTree = BI.createWidget({ + type: "bi.part_tree", element: this, - isAutoSearch: false, + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, callback); + }, + value: opts.value + }); + + this.partTree.on(BI.Controller.EVENT_CHANGE, function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + + this.partTree.on(BI.TreeView.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); + }); + }, + + hasChecked: function () { + return this.partTree.hasChecked(); + }, + + setValue: function (v) { + this.setSelectedValue(v.value); + }, + + setSelectedValue: function (v) { + v || (v = {}); + this.partTree.setSelectedValue(v); + }, + + getValue: function () { + return this.partTree.getValue(); + }, + + empty: function () { + this.partTree.empty(); + }, + + populate: function (op) { + this.partTree.stroke.apply(this.partTree, arguments); + } +}); + +BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; +BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; + +BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiListTreeSearcher + * @extends Widget + */ +BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, + isAutoSync: false, + onSearch: function (op, callback) { + callback({ + keyword: self.editor.getValue() + }); + }, + el: this.editor, + + popup: BI.extend({ + type: "bi.multi_tree_search_pane", + keywordGetter: function () { + return self.editor.getValue(); + }, + itemsCreator: function (op, callback) { + op.keyword = self.editor.getValue(); + o.itemsCreator(op, callback); + }, + value: o.value + }, o.popup), + + adapter: o.adapter, + masker: o.masker + }); + this.searcher.on(BI.Searcher.EVENT_START, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); + }); + this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { + if (this.hasMatched()) { + + } + self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); + }); + this.searcher.on(BI.Searcher.EVENT_STOP, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); + }); + this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); + }); + if (BI.isNotNull(o.value)) { + this.setState(o.value); + } + }, + + adjustView: function () { + this.searcher.adjustView(); + }, + + setAdapter: function (adapter) { + this.searcher.setAdapter(adapter); + }, + + isSearching: function () { + return this.searcher.isSearching(); + }, + + stopSearch: function () { + this.searcher.stopSearch(); + }, + + getKeyword: function () { + return this.editor.getValue(); + }, + + hasMatched: function () { + return this.searcher.hasMatched(); + }, + + hasChecked: function () { + return this.searcher.getView() && this.searcher.getView().hasChecked(); + }, + + setState: function (ob) { + var o = this.options; + ob || (ob = {}); + ob.value || (ob.value = []); + var count = 0; + if (BI.isNumber(ob)) { + this.editor.setState(ob); + } else if (BI.size(ob.value) === 0) { + this.editor.setState(BI.Selection.None); + } else { + var text = ""; + BI.each(ob.value, function (idx, path) { + var childValue = BI.last(path); + text += (o.valueFormatter(childValue + "") || childValue) + "; "; + count++; + }); + + if (count > 20) { + this.editor.setState(BI.Selection.Multi); + } else { + this.editor.setState(text); + } + } + }, + + setValue: function (ob) { + this.setState(ob); + this.searcher.setValue(ob); + }, + + getKey: function () { + return this.editor.getValue(); + }, + + getValue: function () { + return this.searcher.getValue(); + }, + + populate: function (items) { + this.searcher.populate.apply(this.searcher, arguments); + } +}); + +BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; +BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; +BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; +BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; +BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher);/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiTreeSearcher + * @extends Widget + */ +BI.MultiTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, isAutoSync: false, onSearch: function (op, callback) { callback({ @@ -23672,52 +24142,456 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return true; } } - return false; + 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; + 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 = dealWidthSelectedValue(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] + }); + } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + 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 dealWidthSelectedValue(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[value] = [1, BI.size(nextNames)]; + }); + return valueMap; + } + + function getCheckState(current, parentValues, valueMap, checkState) { + 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) { + check = BI.has(valueMap, current); + } else { + 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 node = this._getTreeNode(parentValues, value); + if (!node) { + return false; + } + var find = BI.Func.getSearchResult([node.text || node.value], keyword); + 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(); }, - _reqAdjustTreeNode: function (op, callback) { + _getChildCount: function (parentValues) { + return this._getChildren(parentValues).length; + } +});BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { + + _reqDisplayTreeNode: function (op, callback) { var self = this; - var result = []; + 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, []); + doCheck([], this.tree.getRoot(), selectedValues); - var jo = {}; - BI.each(result, function (i, strs) { - self._buildTree(jo, strs); + callback({ + items: BI.values(result) }); - 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; - } + function doCheck(parentValues, node, selected) { + BI.each(selected, function (idx, path) { + BI.each(path, function (id, value) { + var nodeValue = value; + var node = self._getTreeNode(path.slice(0, id), nodeValue); + // 找不到就是新增值 + if (BI.isNull(node)) { + createOneJson({ + id: BI.UUID(), + text: nodeValue, + value: nodeValue, + isLeaf: true + }, BI.UUID()); + } else { + if(!BI.has(result, node.id)) { + createOneJson(node, node.parent && node.parent.id); + } + result[node.id].isLeaf = id === path.length - 1; + } + }); }); - return can && isAllSelected(selected, parents); } - function isAllSelected(selected, parents) { - return BI.isEmpty(selected) || self._getChildCount(parents) === BI.size(selected); + function createOneJson(node, pId, leaf) { + result[node.id] = { + id: node.id, + pId: pId, + text: node.text, + value: node.value, + open: true, + isLeaf: leaf + }; } }, @@ -23752,9 +24626,9 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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); + var find = nodeSearch(1, [], children[i].value, result); } else if (output.length === self._const.perPage) { - var find = nodeSearch(1, [], children[i].value, false, []); + var find = nodeSearch(1, [], children[i].value, []); } if (find[0] === true) { output.push(children[i].value); @@ -23775,10 +24649,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { return output; } - function nodeSearch(deep, parentValues, current, isAllSelect, result) { + function nodeSearch(deep, parentValues, current, result) { if (self._isMatch(parentValues, current, keyword)) { - var checked = isAllSelect || isSelected(parentValues, current); - createOneJson(parentValues, current, false, checked, !isAllSelect && isHalf(parentValues, current), true, result); + var checked = isSelected(current); + createOneJson(parentValues, current, false, checked, true, result); return [true, checked]; } var newParents = BI.clone(parentValues); @@ -23787,9 +24661,8 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { 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); + var state = nodeSearch(deep + 1, newParents, child.value, result); if (state[1] === true) { checked = true; } @@ -23798,13 +24671,13 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { } }); if (can === true) { - checked = isCurAllSelected || (isSelected(parentValues, current) && checked); - createOneJson(parentValues, current, true, checked, false, false, result); + checked = isSelected(current); + createOneJson(parentValues, current, true, checked, false, result); } return [can, checked]; } - function createOneJson(parentValues, value, isOpen, checked, half, flag, result) { + function createOneJson(parentValues, value, isOpen, checked, flag, result) { var node = self._getTreeNode(parentValues, value); result.push({ id: node.id, @@ -23815,7 +24688,7 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { isParent: node.getChildrenLength() > 0, open: isOpen, checked: checked, - halfCheck: half, + halfCheck: false, flag: flag }); } @@ -23848,15 +24721,9 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { }); } - 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 isSelected(value) { + return BI.any(selectedValues, function (idx, array) { + return BI.last(array) === value; }); } @@ -23880,16 +24747,12 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { var self = this; 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 = dealWidthSelectedValue(parentValues, selectedValues); - // } + var selectedValues = op.selectedValues || []; + var valueMap = dealWidthSelectedValue(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); + var checked = BI.has(valueMap, nodes[i].value); result.push({ id: nodes[i].id, pId: nodes[i].pId, @@ -23897,8 +24760,8 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { text: nodes[i].text, times: 1, isParent: nodes[i].getChildrenLength() > 0, - checked: state[0], - halfCheck: state[1] + checked: checked, + halfCheck: false }); } // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 @@ -23912,68 +24775,21 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { }); }); - 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 dealWidthSelectedValue(parentValues, selectedValues) { + function dealWidthSelectedValue(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[value] = [1, BI.size(nextNames)]; + BI.each(selectedValues, function (idx, v) { + valueMap[BI.last(v)] = [2, 0]; }); return valueMap; } - - function getCheckState(current, parentValues, valueMap, checkState) { - 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) { - check = BI.has(valueMap, current); - } else { - 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) { + var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { + return array.length === 1; + })); + return BI.map(BI.difference(values, BI.map(nodes, "value")), function (idx, v) { return { id: BI.UUID(), pId: nodes.length > 0 ? nodes[0].pId : BI.UUID(), @@ -23985,94 +24801,61 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { halfCheck: false }; }); - }, + } +});/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.ListTreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { - _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; + _defaultConfig: function () { + return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-list-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); }, - _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]; - } - } + _init: function () { + BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); } - }, - - _buildTree: function (jo, values) { - var t = jo; - BI.each(values, function (i, v) { - if (!BI.has(t, v)) { - t[v] = {}; - } - t = t[v]; + this.combo = BI.createWidget({ + type: "bi.multi_tree_list_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height }); - }, - _isMatch: function (parentValues, value, keyword) { - var node = this._getTreeNode(parentValues, value); - if (!node) { - return false; - } - var find = BI.Func.getSearchResult([node.text || node.value], keyword); - return find.find.length > 0 || find.match.length > 0; + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); + }); }, - _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; + setValue: function (v) { + this.combo.setValue(v); }, - _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(); + getValue: function () { + return this.combo.getValue(); }, - _getChildCount: function (parentValues) { - return this._getChildren(parentValues).length; + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); } -});/** +}); +BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "ListTreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo);/** * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 * * Created by GUY on 2015/10/29. diff --git a/public/css/background.css b/public/css/background.css index 06d0a8e7f..4a8e7653f 100644 --- a/public/css/background.css +++ b/public/css/background.css @@ -51,8 +51,8 @@ _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/half_selected.png'); + background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -97,8 +97,8 @@ _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/half_selected.png'); + background: url('http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://fine-design-storage.oss-cn-shanghai.aliyuncs.com/fineui/2.0/images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { diff --git a/src/base/tree/ztree/jquery.ztree.excheck-3.5.js b/src/base/tree/ztree/jquery.ztree.excheck-3.5.js index 1a2774bca..fb0a5b8e8 100644 --- a/src/base/tree/ztree/jquery.ztree.excheck-3.5.js +++ b/src/base/tree/ztree/jquery.ztree.excheck-3.5.js @@ -425,6 +425,8 @@ makeChkClass: function(setting, node) { var checkedKey = setting.data.key.checked, c = consts.checkbox, r = consts.radio, + checkboxType = setting.check.chkboxType; + var notEffectByOtherNode = (checkboxType.Y === "" && checkboxType.N === ""); fullStyle = ""; if (node.chkDisabled === true) { fullStyle = c.DISABLED; @@ -433,7 +435,7 @@ } else if (setting.check.chkStyle == r.STYLE) { fullStyle = (node.check_Child_State < 1)? c.FULL:c.PART; } else { - fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART); + fullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) || notEffectByOtherNode ? c.FULL:c.PART) : ((node.check_Child_State < 1 || notEffectByOtherNode)? c.FULL:c.PART); } var chkName = setting.check.chkStyle + "_" + (node[checkedKey] ? c.TRUE : c.FALSE) + "_" + fullStyle; chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; diff --git a/src/base/tree/ztree/list/listasynctree.js b/src/base/tree/ztree/list/listasynctree.js new file mode 100644 index 000000000..a15c73993 --- /dev/null +++ b/src/base/tree/ztree/list/listasynctree.js @@ -0,0 +1,123 @@ +/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为["A", ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListListAsyncTree + * @extends BI.TreeView + */ +BI.ListAsyncTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListAsyncTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListAsyncTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的 + otherParam: BI.cjkEncodeDO(paras) + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + beforeExpand: beforeExpand, + beforeCheck: beforeCheck, + onClick: onClick + } + }; + + function beforeCheck (treeId, treeNode) { + treeNode.half = false; + } + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function beforeExpand (treeId, treeNode) { + self._beforeExpandNode(treeId, treeNode); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + // 展开节点 + _beforeExpandNode: function (treeId, treeNode) { + var self = this, o = this.options; + var parentValues = treeNode.parentValues || self._getParentValues(treeNode); + var op = BI.extend({}, o.paras, { + id: treeNode.id, + times: 1, + parentValues: parentValues.concat(this._getNodeValue(treeNode)) + }); + var complete = function (d) { + var nodes = d.items || []; + if (nodes.length > 0) { + callback(self._dealWidthNodes(nodes), !!d.hasNext); + } + }; + var times = 1; + + function callback (nodes, hasNext) { + self.nodes.addNodes(treeNode, nodes); + // 展开节点是没有分页的 + if (hasNext === true) { + BI.delay(function () { + times++; + op.times = times; + o.itemsCreator(op, complete); + }, 100); + } + } + + if (!treeNode.children) { + setTimeout(function () { + o.itemsCreator(op, complete); + }, 17); + } + }, + + hasChecked: function () { + return !BI.isEmpty(this.options.paras.selectedValues) || BI.ListAsyncTree.superclass.hasChecked.apply(this, arguments); + }, + + // 生成树方法 + stroke: function (config) { + delete this.options.keyword; + BI.extend(this.options.paras, config); + var setting = this._configSetting(); + this._initTree(setting); + } +}); + +BI.shortcut("bi.list_async_tree", BI.ListAsyncTree); \ No newline at end of file diff --git a/src/base/tree/ztree/list/listparttree.js b/src/base/tree/ztree/list/listparttree.js new file mode 100644 index 000000000..8a1fda13b --- /dev/null +++ b/src/base/tree/ztree/list/listparttree.js @@ -0,0 +1,92 @@ +/** + * guy + * 局部树,两个请求树, 第一个请求构造树,第二个请求获取节点 + * @class BI.ListPartTree + * @extends BI.AsyncTree + */ +BI.ListPartTree = BI.inherit(BI.ListAsyncTree, { + _defaultConfig: function () { + return BI.extend(BI.ListPartTree.superclass._defaultConfig.apply(this, arguments), {}); + }, + + _init: function () { + BI.ListPartTree.superclass._init.apply(this, arguments); + }, + + _loadMore: function () { + var self = this, o = this.options; + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: ++this.times + }); + this.tip.setLoading(); + o.itemsCreator(op, function (d) { + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + if (self._stop === true) { + return; + } + if (!hasNext) { + self.tip.setEnd(); + } else { + self.tip.setLoaded(); + } + if (nodes.length > 0) { + self.nodes.addNodes(null, self._dealWidthNodes(nodes)); + } + }); + }, + + _initTree: function (setting, keyword) { + var self = this, o = this.options; + this.times = 1; + var tree = this.tree; + tree.empty(); + self.tip.setVisible(false); + this.loading(); + var op = BI.extend({}, o.paras, { + type: BI.TreeView.REQ_TYPE_INIT_DATA, + times: this.times + }); + var complete = function (d) { + if (self._stop === true || keyword != o.paras.keyword) { + return; + } + var hasNext = !!d.hasNext, nodes = d.items || []; + o.paras.lastSearchValue = d.lastSearchValue; + // 没有请求到数据也要初始化空树, 如果不初始化, 树就是上一次构造的树, 节点信息都是过期的 + callback(nodes.length > 0 ? self._dealWidthNodes(nodes) : []); + self.setTipVisible(nodes.length <= 0); + self.loaded(); + if (!hasNext) { + self.tip.invisible(); + } else { + self.tip.setLoaded(); + } + self.fireEvent(BI.Events.AFTERINIT); + }; + + function callback (nodes) { + if (self._stop === true) { + return; + } + self.nodes = $.fn.zTree.init(tree.element, setting, nodes); + } + + BI.delay(function () { + o.itemsCreator(op, complete); + }, 100); + }, + + // 生成树方法 + stroke: function (config) { + var o = this.options; + delete o.paras.keyword; + BI.extend(o.paras, config); + delete o.paras.lastSearchValue; + var setting = this._configSetting(); + this._initTree(setting, o.paras.keyword); + } +}); + +BI.shortcut("bi.list_part_tree", BI.ListPartTree); \ No newline at end of file diff --git a/src/base/tree/ztree/list/listtreeview.js b/src/base/tree/ztree/list/listtreeview.js new file mode 100644 index 000000000..854267028 --- /dev/null +++ b/src/base/tree/ztree/list/listtreeview.js @@ -0,0 +1,114 @@ +/** + * author: windy + * 继承自treeView, 此树的父子节点的勾选状态互不影响, 此树不会有半选节点 + * 返回value格式为[["A"], ["A", "a"]]表示勾选了A且勾选了a + * @class BI.ListTreeView + * @extends BI.TreeView + */ +BI.ListTreeView = BI.inherit(BI.TreeView, { + + _constants: { + SPLIT: "<|>" + }, + + _defaultConfig: function () { + return BI.extend(BI.ListTreeView.superclass._defaultConfig.apply(this, arguments), {}); + }, + _init: function () { + BI.ListTreeView.superclass._init.apply(this, arguments); + var o = this.options; + this.storeValue = o.value || {}; + }, + + // 配置属性 + _configSetting: function () { + var paras = this.options.paras; + var self = this; + var setting = { + async: { + enable: false + }, + check: { + enable: true, + chkboxType: {Y: "", N: ""} + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + view: { + showIcon: false, + expandSpeed: "", + nameIsHTML: true, + dblClickExpand: false + }, + callback: { + onCheck: onCheck, + onClick: onClick + } + }; + + function onClick (event, treeId, treeNode) { + var zTree = $.fn.zTree.getZTreeObj(treeId); + var checked = treeNode.checked; + self._checkValue(treeNode, !checked); + zTree.checkNode(treeNode, !checked, true, true); + } + + function onCheck (event, treeId, treeNode) { + self._selectTreeNode(treeId, treeNode); + } + + return setting; + }, + + _selectTreeNode: function (treeId, treeNode) { + this._checkValue(treeNode, treeNode.checked); + BI.ListTreeView.superclass._selectTreeNode.apply(this, arguments); + }, + + _transArrayToMap: function (treeArrays) { + var self = this; + var map = {}; + BI.each(treeArrays, function (idx, array) { + var key = array.join(self._constants.SPLIT); + map[key] = true; + }); + return map; + }, + + _transMapToArray: function (treeMap) { + var self = this; + var array = []; + BI.each(treeMap, function (key) { + var item = key.split(self._constants.SPLIT); + array.push(item); + }); + return array; + }, + + _checkValue: function (treeNode, checked) { + var key = BI.concat(this._getParentValues(treeNode), this._getNodeValue(treeNode)).join(this._constants.SPLIT); + if(checked) { + this.storeValue[key] = true; + } else { + delete this.storeValue[key]; + } + }, + + setSelectedValue: function (value) { + this.options.paras.selectedValues = value || []; + this.storeValue = this._transArrayToMap(value); + }, + + getValue: function () { + return this._transMapToArray(this.storeValue); + } +}); + +BI.shortcut("bi.list_tree_view", BI.ListTreeView); \ No newline at end of file diff --git a/src/base/tree/ztree/parttree.js b/src/base/tree/ztree/parttree.js index c201f2141..fbd806d14 100644 --- a/src/base/tree/ztree/parttree.js +++ b/src/base/tree/ztree/parttree.js @@ -42,7 +42,14 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var name = this._getNodeValue(treeNode); if (treeNode.checked === true) { - BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + this._buildTree(self.options.paras.selectedValues, BI.concat(parentValues, name)); + o.itemsCreator({ + type: BI.TreeView.REQ_TYPE_ADJUST_DATA, + selectedValues: self.options.paras.selectedValues + }, function (res) { + self.options.paras.selectedValues = res; + BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); + }); } else { // 如果选中的值中不存在该值不处理 // 因为反正是不选中,没必要管 @@ -144,12 +151,6 @@ BI.PartTree = BI.inherit(BI.AsyncTree, { getValue: function () { var o = this.options; var result = BI.PartTree.superclass.getValue.apply(this, arguments); - o.itemsCreator({ - type: BI.TreeView.REQ_TYPE_ADJUST_DATA, - selectedValues: result - }, function (res) { - result = res; - }); return result; }, diff --git a/src/case/tree/ztree/tree.list.display.js b/src/case/tree/ztree/tree.list.display.js new file mode 100644 index 000000000..3be529e13 --- /dev/null +++ b/src/case/tree/ztree/tree.list.display.js @@ -0,0 +1,81 @@ +/** + * guy + * 异步树 + * @class BI.ListListDisplayTree + * @extends BI.TreeView + */ +BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { + _defaultConfig: function () { + return BI.extend(BI.ListDisplayTree.superclass._defaultConfig.apply(this, arguments), { + extraCls: "bi-list-display-tree" + }); + }, + _init: function () { + BI.ListDisplayTree.superclass._init.apply(this, arguments); + }, + + // 配置属性 + _configSetting: function () { + var setting = { + view: { + selectedMulti: false, + dblClickExpand: false, + showIcon: false, + nameIsHTML: true, + showTitle: false, + fontCss: getFont + }, + data: { + key: { + title: "title", + name: "text" + }, + simpleData: { + enable: true + } + }, + callback: { + beforeCollapse: beforeCollapse + } + }; + + function beforeCollapse(treeId, treeNode) { + return false; + } + + function getFont(treeId, node) { + return node.font ? node.font : {color: "#999999"}; + } + + return setting; + }, + + _dealWidthNodes: function (nodes) { + nodes = BI.ListDisplayTree.superclass._dealWidthNodes.apply(this, arguments); + var self = this, o = this.options; + BI.each(nodes, function (i, node) { + node.isParent = node.isParent || node.parent; + if (node.text == null) { + if (node.count > 0) { + node.text = node.value + "(" + BI.i18nText("BI-Basic_Altogether") + node.count + BI.i18nText("BI-Basic_Count") + ")"; + } + } + if(node.isLeaf === true) { + node.font = {color: "#3d4d66"}; + } + }); + return nodes; + }, + + initTree: function (nodes, setting) { + var setting = setting || this._configSetting(); + this.nodes = $.fn.zTree.init(this.tree.element, setting, nodes); + }, + + destroy: function () { + BI.ListDisplayTree.superclass.destroy.apply(this, arguments); + } +}); +BI.ListDisplayTree.EVENT_CHANGE = "EVENT_CHANGE"; + +BI.shortcut("bi.list_display_tree", BI.ListDisplayTree); \ No newline at end of file diff --git a/src/component/treevaluechooser/abstract.treevaluechooser.list.js b/src/component/treevaluechooser/abstract.treevaluechooser.list.js new file mode 100644 index 000000000..2d43295dd --- /dev/null +++ b/src/component/treevaluechooser/abstract.treevaluechooser.list.js @@ -0,0 +1,261 @@ +BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { + + _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: BI.values(result) + }); + + function doCheck(parentValues, node, selected) { + BI.each(selected, function (idx, path) { + BI.each(path, function (id, value) { + var nodeValue = value; + var node = self._getTreeNode(path.slice(0, id), nodeValue); + // 找不到就是新增值 + if (BI.isNull(node)) { + createOneJson({ + id: BI.UUID(), + text: nodeValue, + value: nodeValue, + isLeaf: true + }, BI.UUID()); + } else { + if(!BI.has(result, node.id)) { + createOneJson(node, node.parent && node.parent.id); + } + result[node.id].isLeaf = id === path.length - 1; + } + }); + }); + } + + function createOneJson(node, pId, leaf) { + result[node.id] = { + id: node.id, + pId: pId, + text: node.text, + value: node.value, + open: true, + isLeaf: leaf + }; + } + }, + + _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, result); + } else if (output.length === self._const.perPage) { + var find = nodeSearch(1, [], children[i].value, []); + } + 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, result) { + if (self._isMatch(parentValues, current, keyword)) { + var checked = isSelected(current); + createOneJson(parentValues, current, false, checked, true, result); + return [true, checked]; + } + var newParents = BI.clone(parentValues); + newParents.push(current); + var children = self._getChildren(newParents); + + var can = false, checked = false; + + BI.each(children, function (i, child) { + var state = nodeSearch(deep + 1, newParents, child.value, result); + if (state[1] === true) { + checked = true; + } + if (state[0] === true) { + can = true; + } + }); + if (can === true) { + checked = isSelected(current); + createOneJson(parentValues, current, true, checked, false, result); + } + return [can, checked]; + } + + function createOneJson(parentValues, value, isOpen, checked, 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: false, + 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(value) { + return BI.any(selectedValues, function (idx, array) { + return BI.last(array) === value; + }); + } + + 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; + var result = []; + var times = op.times; + var parentValues = op.parentValues || []; + var selectedValues = op.selectedValues || []; + var valueMap = dealWidthSelectedValue(selectedValues); + var nodes = this._getChildren(parentValues); + for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { + var checked = BI.has(valueMap, nodes[i].value); + 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: checked, + halfCheck: false + }); + } + // 深层嵌套的比较麻烦,这边先实现的是在根节点添加 + 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 dealWidthSelectedValue(selectedValues) { + var valueMap = {}; + BI.each(selectedValues, function (idx, v) { + valueMap[BI.last(v)] = [2, 0]; + }); + return valueMap; + } + }, + + _getAddedValueNode: function (parentValues, selectedValues) { + var nodes = this._getChildren(parentValues); + var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { + return array.length === 1; + })); + return BI.map(BI.difference(values, 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 + }; + }); + } +}); \ No newline at end of file diff --git a/src/component/treevaluechooser/combo.listtreevaluechooser.js b/src/component/treevaluechooser/combo.listtreevaluechooser.js new file mode 100644 index 000000000..0a1d327e4 --- /dev/null +++ b/src/component/treevaluechooser/combo.listtreevaluechooser.js @@ -0,0 +1,54 @@ +/** + * 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 + * + * Created by GUY on 2015/10/29. + * @class BI.ListTreeValueChooserInsertCombo + * @extends BI.Widget + */ +BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { + + _defaultConfig: function () { + return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-list-tree-value-chooser-insert-combo", + width: 200, + height: 24, + items: null, + itemsCreator: BI.emptyFn + }); + }, + + _init: function () { + BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); + var self = this, o = this.options; + if (BI.isNotNull(o.items)) { + this._initData(o.items); + } + this.combo = BI.createWidget({ + type: "bi.multi_tree_list_combo", + element: this, + itemsCreator: BI.bind(this._itemsCreator, this), + valueFormatter: BI.bind(this._valueFormatter, this), + width: o.width, + height: o.height + }); + + this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); + }); + }, + + setValue: function (v) { + this.combo.setValue(v); + }, + + getValue: function () { + return this.combo.getValue(); + }, + + populate: function (items) { + this._initData(items); + this.combo.populate.apply(this.combo, arguments); + } +}); +BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "ListTreeValueChooserInsertCombo.EVENT_CONFIRM"; +BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo); \ No newline at end of file diff --git a/src/css/base/colorchooser/colorpicker/editor.css b/src/css/base/colorchooser/colorpicker/editor.css index 1d04d58c3..493b54450 100644 --- a/src/css/base/colorchooser/colorpicker/editor.css +++ b/src/css/base/colorchooser/colorpicker/editor.css @@ -51,8 +51,8 @@ _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/half_selected.png'); + background: url('images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -97,8 +97,8 @@ _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/half_selected.png'); + background: url('images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { diff --git a/src/css/base/tree/tree.css b/src/css/base/tree/tree.css index 9ae37a8a1..4ba2ec450 100644 --- a/src/css/base/tree/tree.css +++ b/src/css/base/tree/tree.css @@ -19,3 +19,18 @@ opacity: 1; filter: alpha(opacity=100); } + +.bi-list-display-tree .ztree li a, +.bi-list-display-tree .ztree li span { + cursor: default !important; +} +.bi-list-display-tree .ztree li a:hover { + text-decoration: none; +} +.bi-list-display-tree .ztree li a.curSelectedNode { + padding-top: 1px; + border: none; + background-color: inherit; + opacity: 1; + filter: alpha(opacity=100); +} diff --git a/src/css/resource/background.css b/src/css/resource/background.css index 128ccf2ab..788094caa 100644 --- a/src/css/resource/background.css +++ b/src/css/resource/background.css @@ -51,8 +51,8 @@ _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/half_selected.png'); + background: url('images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -97,8 +97,8 @@ _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/half_selected.png'); + background: url('images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { diff --git a/src/less/base/tree/tree.list.display.less b/src/less/base/tree/tree.list.display.less new file mode 100644 index 000000000..e58d3a5dd --- /dev/null +++ b/src/less/base/tree/tree.list.display.less @@ -0,0 +1,17 @@ +@import "../../index"; + +.bi-list-display-tree{ + + & .ztree li a, & .ztree li span{ + cursor: default !important; + } + & .ztree li a:hover{ + text-decoration: none; + } + & .ztree li a.curSelectedNode{ + padding-top: 1px; + border: none; + background-color: inherit; + .opacity(1); + } +} \ No newline at end of file diff --git a/src/less/resource/background.less b/src/less/resource/background.less index c6036b3ff..e1eb69d35 100644 --- a/src/less/resource/background.less +++ b/src/less/resource/background.less @@ -47,7 +47,7 @@ } .ztree li span.button.chk.checkbox_false_part { - .image2xPath(@icon-half-select); + .image2xPath(@icon-checkbox-normal); } .ztree li span.button.chk.checkbox_false_part_focus { @@ -79,7 +79,7 @@ } .ztree.hack li span.button.chk.checkbox_false_part { - .imagePath(@icon-half-select); + .imagePath(@icon-checkbox-normal); } .ztree.hack li span.button.chk.checkbox_false_part_focus { diff --git a/src/widget/multitree/check/multi.tree.check.pane.js b/src/widget/multitree/check/multi.tree.check.pane.js index b33b77daf..b73f8d1ec 100644 --- a/src/widget/multitree/check/multi.tree.check.pane.js +++ b/src/widget/multitree/check/multi.tree.check.pane.js @@ -14,7 +14,10 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { _defaultConfig: function () { return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { baseCls: "bi-multi-tree-check-pane bi-background", - onClickContinueSelect: BI.emptyFn + onClickContinueSelect: BI.emptyFn, + el: { + type: "bi.display_tree" + } }); }, @@ -56,7 +59,7 @@ BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { }] }); - this.display = BI.createWidget({ + this.display = BI.createWidget(opts.el, { type: "bi.display_tree", cls: "bi-multi-tree-display", itemsCreator: function (op, callback) { diff --git a/src/widget/multitree/multi.tree.list.combo.js b/src/widget/multitree/multi.tree.list.combo.js new file mode 100644 index 000000000..8d7f2e9f0 --- /dev/null +++ b/src/widget/multitree/multi.tree.list.combo.js @@ -0,0 +1,295 @@ +/** + * 可以往当前选中节点下添加新值的下拉树 + * @class BI.MultiTreeListCombo + * @extends BI.Single + */ + +BI.MultiTreeListCombo = BI.inherit(BI.Single, { + + constants: { + offset: { + top: 0, + left: 0, + right: 0, + bottom: 25 + } + }, + + _defaultConfig: function () { + return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-list-combo", + itemsCreator: BI.emptyFn, + valueFormatter: BI.emptyFn, + height: 24 + }); + }, + + _init: function () { + BI.MultiTreeListCombo.superclass._init.apply(this, arguments); + + var self = this, o = this.options; + + var isInit = false; + var want2showCounter = false; + + this.storeValue = {value: o.value || []}; + + this.trigger = BI.createWidget({ + type: "bi.multi_select_trigger", + height: o.height, + valueFormatter: o.valueFormatter, + // adapter: this.popup, + masker: { + offset: this.constants.offset + }, + searcher: { + type: "bi.multi_list_tree_searcher", + itemsCreator: o.itemsCreator, + popup: { + type: "bi.multi_tree_search_insert_pane", + el: { + type: "bi.list_part_tree" + }, + listeners: [{ + eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, + action: function () { + self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); + self._assertShowValue(); + // setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 + self.combo.setValue(self.storeValue); + self.trigger.stopEditing(); + } + }] + } + }, + switcher: { + el: { + type: "bi.multi_tree_check_selected_button" + }, + popup: { + type: "bi.multi_tree_check_pane", + el: { + type: "bi.list_display_tree" + }, + itemsCreator: o.itemsCreator + } + }, + value: {value: o.value || {}} + + }); + + this.combo = BI.createWidget({ + type: "bi.combo", + toggle: false, + container: o.container, + el: this.trigger, + adjustLength: 1, + popup: { + type: "bi.multi_tree_popup_view", + ref: function () { + self.popup = this; + self.trigger.setAdapter(this); + }, + el: { + type: "bi.list_async_tree" + }, + listeners: [{ + eventName: BI.MultiTreePopup.EVENT_AFTERINIT, + action: function () { + self.trigger.getCounter().adjustView(); + isInit = true; + if (want2showCounter === true) { + showCounter(); + } + } + }, { + eventName: BI.MultiTreePopup.EVENT_CHANGE, + action: function () { + change = true; + var val = { + type: BI.Selection.Multi, + value: this.hasChecked() ? this.getValue() : [] + }; + self.trigger.getSearcher().setState(val); + self.trigger.getCounter().setButtonChecked(val); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, + action: function () { + self.combo.hideView(); + } + }, { + eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, + action: function () { + clear = true; + self.setValue(); + self._defaultState(); + } + }], + itemsCreator: o.itemsCreator, + onLoaded: function () { + BI.nextTick(function () { + self.trigger.getCounter().adjustView(); + self.trigger.getSearcher().adjustView(); + }); + } + }, + value: {value: o.value || {}}, + hideChecker: function (e) { + return triggerBtn.element.find(e.target).length === 0; + } + }); + + var change = false; + var clear = false; // 标识当前是否点击了清空 + + var isSearching = function () { + return self.trigger.getSearcher().isSearching(); + }; + + var isPopupView = function () { + return self.combo.isViewVisible(); + }; + + this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { + self.storeValue = {value: self.combo.getValue()}; + this.setValue(self.storeValue); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { + self.storeValue = {value: this.getValue()}; + self.combo.setValue(self.storeValue); + BI.nextTick(function () { + if (isPopupView()) { + self.combo.populate(); + } + }); + }); + + function showCounter () { + if (isSearching()) { + self.storeValue = {value: self.trigger.getValue()}; + } else if (isPopupView()) { + self.storeValue = {value: self.combo.getValue()}; + } + self.trigger.setValue(self.storeValue); + } + + this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { + if (want2showCounter === false) { + want2showCounter = true; + } + if (isInit === true) { + want2showCounter = null; + showCounter(); + } + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { + self.combo.toggle(); + }); + this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { + if (!self.combo.isViewVisible()) { + self.combo.showView(); + } + }); + + this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { + var checked = this.getSearcher().hasChecked(); + var val = { + type: BI.Selection.Multi, + value: checked ? {1: 1} : {} + }; + this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); + this.getCounter().setButtonChecked(val); + }); + + this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { + if (isSearching()) { + return; + } + if (change === true) { + self.storeValue = {value: self.combo.getValue()}; + change = false; + } + self.combo.setValue(self.storeValue); + self.populate(); + + }); + this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { + if (isSearching()) { + self.trigger.stopEditing(); + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } else { + if (isPopupView()) { + self.trigger.stopEditing(); + self.storeValue = {value: self.combo.getValue()}; + if (clear === true) { + self.storeValue = {value: []}; + } + self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); + } + } + clear = false; + change = false; + }); + + var triggerBtn = BI.createWidget({ + type: "bi.trigger_icon_button", + width: o.height, + height: o.height, + cls: "multi-select-trigger-icon-button" + }); + triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { + self.trigger.getCounter().hideView(); + if (self.combo.isViewVisible()) { + self.combo.hideView(); + } else { + self.combo.showView(); + } + }); + BI.createWidget({ + type: "bi.absolute", + element: this, + items: [{ + el: this.combo, + left: 0, + right: 0, + top: 0, + bottom: 0 + }, { + el: triggerBtn, + right: 0, + top: 0, + bottom: 0 + }] + }); + }, + + _assertShowValue: function () { + this.trigger.getSearcher().setState(this.storeValue); + this.trigger.getCounter().setButtonChecked(this.storeValue); + }, + + _defaultState: function () { + this.trigger.stopEditing(); + this.combo.hideView(); + }, + + setValue: function (v) { + this.storeValue.value = v || []; + this.combo.setValue({ + value: v || [] + }); + }, + + getValue: function () { + return this.storeValue.value; + }, + + populate: function () { + this.combo.populate.apply(this.combo, arguments); + } +}); + +BI.MultiTreeListCombo.EVENT_CONFIRM = "MultiTreeListCombo.EVENT_CONFIRM"; + +BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo); \ No newline at end of file diff --git a/src/widget/multitree/multi.tree.popup.js b/src/widget/multitree/multi.tree.popup.js index 7a38c7beb..64d54d66b 100644 --- a/src/widget/multitree/multi.tree.popup.js +++ b/src/widget/multitree/multi.tree.popup.js @@ -11,24 +11,27 @@ BI.MultiTreePopup = BI.inherit(BI.Pane, { maxWidth: "auto", minWidth: 100, maxHeight: 400, - onLoaded: BI.emptyFn + onLoaded: BI.emptyFn, + el: { + type: "bi.async_tree" + } }); }, _init: function () { BI.MultiTreePopup.superclass._init.apply(this, arguments); - var self = this, opts = this.options; + var self = this, opts = this.options, v = opts.value; this.selectedValues = {}; - this.tree = BI.createWidget({ + this.tree = BI.createWidget(opts.el, { type: "bi.async_tree", height: 400, cls: "popup-view-tree", itemsCreator: opts.itemsCreator, onLoaded: opts.onLoaded, - value: opts.value || {} + value: v.value || {} }); this.popupView = BI.createWidget({ diff --git a/src/widget/multitree/trigger/multi.tree.search.insert.pane.js b/src/widget/multitree/trigger/multi.tree.search.insert.pane.js index ccad8fede..cc5bff3c9 100644 --- a/src/widget/multitree/trigger/multi.tree.search.insert.pane.js +++ b/src/widget/multitree/trigger/multi.tree.search.insert.pane.js @@ -14,52 +14,65 @@ BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { props: { baseCls: "bi-multi-tree-search-insert-pane bi-card", itemsCreator: BI.emptyFn, - keywordGetter: BI.emptyFn + keywordGetter: BI.emptyFn, + el: { + type: "bi.part_tree" + } }, render: function () { var self = this, opts = this.options; return { - type: "bi.vertical", + type: "bi.absolute", items: [{ - type: "bi.text_button", - invisible: true, - ref: function (_ref) { - self.addTip = _ref; + el: { + type: "bi.text_button", + invisible: true, + ref: function (_ref) { + self.addTip = _ref; + }, + text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), + height: this.constants.height, + cls: "bi-high-light", + handler: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); + } }, - text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), - height: this.constants.height, - cls: "bi-high-light", - hgap: 5, - handler: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); - } + top: 5, + left: 0, + right: 0 }, { - type: "bi.part_tree", - tipText: BI.i18nText("BI-No_Select"), - itemsCreator: function (op, callback) { - op.keyword = opts.keywordGetter(); - opts.itemsCreator(op, function (res) { - callback(res); - self.setKeyword(opts.keywordGetter(), res.items); - }); - }, - ref: function (_ref) { - self.partTree = _ref; - }, - value: opts.value, - listeners: [{ - eventName: BI.Controller.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); - } - }, { - eventName: BI.TreeView.EVENT_CHANGE, - action: function () { - self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); - } - }] + el: BI.extend({ + type: "bi.part_tree", + tipText: BI.i18nText("BI-No_Select"), + itemsCreator: function (op, callback) { + op.keyword = opts.keywordGetter(); + opts.itemsCreator(op, function (res) { + callback(res); + self.setKeyword(opts.keywordGetter(), res.items); + }); + }, + ref: function (_ref) { + self.partTree = _ref; + }, + value: opts.value, + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }, { + eventName: BI.TreeView.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); + } + }] + }, opts.el), + left: 0, + top: 0, + bottom: 0, + right: 0 }] }; }, diff --git a/src/widget/multitree/multi.tree.search.pane.js b/src/widget/multitree/trigger/multi.tree.search.pane.js similarity index 100% rename from src/widget/multitree/multi.tree.search.pane.js rename to src/widget/multitree/trigger/multi.tree.search.pane.js diff --git a/src/widget/multitree/trigger/searcher.list.multi.tree.js b/src/widget/multitree/trigger/searcher.list.multi.tree.js new file mode 100644 index 000000000..acfe1cf45 --- /dev/null +++ b/src/widget/multitree/trigger/searcher.list.multi.tree.js @@ -0,0 +1,158 @@ +/** + * searcher + * Created by guy on 15/11/3. + * @class BI.MultiListTreeSearcher + * @extends Widget + */ +BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-multi-tree-searcher", + itemsCreator: BI.emptyFn, + valueFormatter: function (v) { + return v; + }, + popup: {}, + + adapter: null, + masker: {} + }); + }, + + _init: function () { + BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.editor = BI.createWidget({ + type: "bi.multi_select_editor", + height: o.height, + el: { + type: "bi.simple_state_editor", + height: o.height + } + }); + + this.searcher = BI.createWidget({ + type: "bi.searcher", + element: this, + isAutoSearch: false, + isAutoSync: false, + onSearch: function (op, callback) { + callback({ + keyword: self.editor.getValue() + }); + }, + el: this.editor, + + popup: BI.extend({ + type: "bi.multi_tree_search_pane", + keywordGetter: function () { + return self.editor.getValue(); + }, + itemsCreator: function (op, callback) { + op.keyword = self.editor.getValue(); + o.itemsCreator(op, callback); + }, + value: o.value + }, o.popup), + + adapter: o.adapter, + masker: o.masker + }); + this.searcher.on(BI.Searcher.EVENT_START, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); + }); + this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { + if (this.hasMatched()) { + + } + self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); + }); + this.searcher.on(BI.Searcher.EVENT_STOP, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); + }); + this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { + self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); + }); + if (BI.isNotNull(o.value)) { + this.setState(o.value); + } + }, + + adjustView: function () { + this.searcher.adjustView(); + }, + + setAdapter: function (adapter) { + this.searcher.setAdapter(adapter); + }, + + isSearching: function () { + return this.searcher.isSearching(); + }, + + stopSearch: function () { + this.searcher.stopSearch(); + }, + + getKeyword: function () { + return this.editor.getValue(); + }, + + hasMatched: function () { + return this.searcher.hasMatched(); + }, + + hasChecked: function () { + return this.searcher.getView() && this.searcher.getView().hasChecked(); + }, + + setState: function (ob) { + var o = this.options; + ob || (ob = {}); + ob.value || (ob.value = []); + var count = 0; + if (BI.isNumber(ob)) { + this.editor.setState(ob); + } else if (BI.size(ob.value) === 0) { + this.editor.setState(BI.Selection.None); + } else { + var text = ""; + BI.each(ob.value, function (idx, path) { + var childValue = BI.last(path); + text += (o.valueFormatter(childValue + "") || childValue) + "; "; + count++; + }); + + if (count > 20) { + this.editor.setState(BI.Selection.Multi); + } else { + this.editor.setState(text); + } + } + }, + + setValue: function (ob) { + this.setState(ob); + this.searcher.setValue(ob); + }, + + getKey: function () { + return this.editor.getValue(); + }, + + getValue: function () { + return this.searcher.getValue(); + }, + + populate: function (items) { + this.searcher.populate.apply(this.searcher, arguments); + } +}); + +BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; +BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; +BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; +BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; +BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; +BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher); \ No newline at end of file diff --git a/ui/css/background.css b/ui/css/background.css index c03b30dc3..98501eb71 100644 --- a/ui/css/background.css +++ b/ui/css/background.css @@ -51,8 +51,8 @@ _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('resources?path=/com/fr/web/ui/images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/2x/icon/half_selected.png'); + background: url('resources?path=/com/fr/web/ui/images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -97,8 +97,8 @@ _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('resources?path=/com/fr/web/ui/images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/1x/icon/half_selected.png'); + background: url('resources?path=/com/fr/web/ui/images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { From b0b8c8562053423d16bbf65184d266beaaf23375 Mon Sep 17 00:00:00 2001 From: windy <1374721899@qq.com> Date: Sat, 4 May 2019 17:45:40 +0800 Subject: [PATCH 3/5] =?UTF-8?q?refactor:=20setValue=20&&=20getValue?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/demo.treevaluechoosercombo.js | 13 ++++++ dist/2.0/fineui.ie.js | 12 +++--- dist/2.0/fineui.js | 12 +++--- dist/bundle.ie.js | 12 +++--- dist/bundle.js | 12 +++--- dist/demo.js | 13 ++++++ dist/fineui.css | 43 +++++++++++++++---- dist/fineui.ie.js | 12 +++--- dist/fineui.js | 12 +++--- dist/fineui_without_jquery_polyfill.js | 12 +++--- dist/widget.js | 12 +++--- .../abstract.treevaluechooser.list.js | 6 +-- .../combo.listtreevaluechooser.js | 2 +- .../combo.treevaluechooser.insert.js | 2 +- src/widget/multitree/multi.tree.list.combo.js | 2 +- 15 files changed, 114 insertions(+), 63 deletions(-) diff --git a/demo/js/component/demo.treevaluechoosercombo.js b/demo/js/component/demo.treevaluechoosercombo.js index 1d5075e13..f91b32ceb 100644 --- a/demo/js/component/demo.treevaluechoosercombo.js +++ b/demo/js/component/demo.treevaluechoosercombo.js @@ -18,6 +18,19 @@ Demo.TreeValueChooser = BI.inherit(BI.Widget, { callback(BI.deepClone(Demo.CONSTANTS.TREEITEMS)); } }); + widget.setValue({ + "中国": { + "安徽省": { + "安庆市": {} + } + }, + "newValue": {} + }); + widget1.setValue([ + ["中国", "安徽省"], + ["中国", "安徽省", "安庆市"], + ["newValue"] + ]); return { type: "bi.vertical", items: [{ diff --git a/dist/2.0/fineui.ie.js b/dist/2.0/fineui.ie.js index 5f146657d..9abb3dee0 100644 --- a/dist/2.0/fineui.ie.js +++ b/dist/2.0/fineui.ie.js @@ -73196,7 +73196,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 可以往当前选中节点下添加新值的下拉树 + * 选中节点不影响父子节点状态的下拉树 * @class BI.MultiTreeListCombo * @extends BI.Single */ @@ -84533,20 +84533,20 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { if(!BI.has(result, node.id)) { createOneJson(node, node.parent && node.parent.id); } - result[node.id].isLeaf = id === path.length - 1; + result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); } }); }); } - function createOneJson(node, pId, leaf) { + function createOneJson(node, pId) { result[node.id] = { id: node.id, pId: pId, text: node.text, value: node.value, open: true, - isLeaf: leaf + isLeaf: node.isLeaf }; } }, @@ -84792,7 +84792,7 @@ BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeListCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, @@ -84845,7 +84845,7 @@ BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeInsertCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/dist/2.0/fineui.js b/dist/2.0/fineui.js index 298fefd4a..7a4e470b1 100644 --- a/dist/2.0/fineui.js +++ b/dist/2.0/fineui.js @@ -73600,7 +73600,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 可以往当前选中节点下添加新值的下拉树 + * 选中节点不影响父子节点状态的下拉树 * @class BI.MultiTreeListCombo * @extends BI.Single */ @@ -84937,20 +84937,20 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { if(!BI.has(result, node.id)) { createOneJson(node, node.parent && node.parent.id); } - result[node.id].isLeaf = id === path.length - 1; + result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); } }); }); } - function createOneJson(node, pId, leaf) { + function createOneJson(node, pId) { result[node.id] = { id: node.id, pId: pId, text: node.text, value: node.value, open: true, - isLeaf: leaf + isLeaf: node.isLeaf }; } }, @@ -85196,7 +85196,7 @@ BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeListCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, @@ -85249,7 +85249,7 @@ BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeInsertCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/dist/bundle.ie.js b/dist/bundle.ie.js index 5f146657d..9abb3dee0 100644 --- a/dist/bundle.ie.js +++ b/dist/bundle.ie.js @@ -73196,7 +73196,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 可以往当前选中节点下添加新值的下拉树 + * 选中节点不影响父子节点状态的下拉树 * @class BI.MultiTreeListCombo * @extends BI.Single */ @@ -84533,20 +84533,20 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { if(!BI.has(result, node.id)) { createOneJson(node, node.parent && node.parent.id); } - result[node.id].isLeaf = id === path.length - 1; + result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); } }); }); } - function createOneJson(node, pId, leaf) { + function createOneJson(node, pId) { result[node.id] = { id: node.id, pId: pId, text: node.text, value: node.value, open: true, - isLeaf: leaf + isLeaf: node.isLeaf }; } }, @@ -84792,7 +84792,7 @@ BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeListCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, @@ -84845,7 +84845,7 @@ BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeInsertCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/dist/bundle.js b/dist/bundle.js index 298fefd4a..7a4e470b1 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -73600,7 +73600,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 可以往当前选中节点下添加新值的下拉树 + * 选中节点不影响父子节点状态的下拉树 * @class BI.MultiTreeListCombo * @extends BI.Single */ @@ -84937,20 +84937,20 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { if(!BI.has(result, node.id)) { createOneJson(node, node.parent && node.parent.id); } - result[node.id].isLeaf = id === path.length - 1; + result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); } }); }); } - function createOneJson(node, pId, leaf) { + function createOneJson(node, pId) { result[node.id] = { id: node.id, pId: pId, text: node.text, value: node.value, open: true, - isLeaf: leaf + isLeaf: node.isLeaf }; } }, @@ -85196,7 +85196,7 @@ BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeListCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, @@ -85249,7 +85249,7 @@ BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeInsertCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/dist/demo.js b/dist/demo.js index 9831888e1..9c93f09eb 100644 --- a/dist/demo.js +++ b/dist/demo.js @@ -2713,6 +2713,19 @@ BI.shortcut("demo.center", Demo.Center);Demo.TreeValueChooser = BI.inherit(BI.Wi callback(BI.deepClone(Demo.CONSTANTS.TREEITEMS)); } }); + widget.setValue({ + "中国": { + "安徽省": { + "安庆市": {} + } + }, + "newValue": {} + }); + widget1.setValue([ + ["中国", "安徽省"], + ["中国", "安徽省", "安庆市"], + ["newValue"] + ]); return { type: "bi.vertical", items: [{ diff --git a/dist/fineui.css b/dist/fineui.css index 601aae775..68d3fd322 100644 --- a/dist/fineui.css +++ b/dist/fineui.css @@ -2228,8 +2228,8 @@ textarea { _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/half_selected.png'); + background: url('images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -2274,8 +2274,8 @@ textarea { _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/half_selected.png'); + background: url('images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { @@ -3579,7 +3579,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, opacity: 0; } .bi-checkbox.disabled.active .checkbox-content { - border-color: #e8eaed; + border-color: #d0d4da; } .bi-checkbox.disabled.active .checkbox-content:after { opacity: 1; @@ -3587,6 +3587,16 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-checkbox .checkbox-content { border-color: #9EA6B2; } +.bi-theme-dark .bi-checkbox.active .checkbox-content, +.bi-theme-dark .bi-checkbox:active .checkbox-content { + border-color: #3685f2; +} +.bi-theme-dark .bi-checkbox.disabled .checkbox-content { + background-color: #606479; +} +.bi-theme-dark .bi-checkbox.disabled.active .checkbox-content { + border-color: #606479; +} .bi-file { opacity: 0; filter: alpha(opacity=0); @@ -3765,6 +3775,21 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, opacity: 1; filter: alpha(opacity=100); } + +.bi-list-display-tree .ztree li a, +.bi-list-display-tree .ztree li span { + cursor: default !important; +} +.bi-list-display-tree .ztree li a:hover { + text-decoration: none; +} +.bi-list-display-tree .ztree li a.curSelectedNode { + padding-top: 1px; + border: none; + background-color: inherit; + opacity: 1; + filter: alpha(opacity=100); +} .ztree * { padding: 0; margin: 0; @@ -4548,8 +4573,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree li span.button.chk.checkbox_false_part { - background: url('resources?path=/com/fr/web/ui/images/2x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/2x/icon/half_selected.png'); + background: url('resources?path=/com/fr/web/ui/images/2x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/2x/icon/check_box_normal.png'); background-size: contain; _background: none; } @@ -4594,8 +4619,8 @@ textarea::-webkit-scrollbar-thumb:hover { _background: none; } .ztree.hack li span.button.chk.checkbox_false_part { - background: url('resources?path=/com/fr/web/ui/images/1x/icon/half_selected.png') no-repeat center center; - _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/1x/icon/half_selected.png'); + background: url('resources?path=/com/fr/web/ui/images/1x/icon/check_box_normal.png') no-repeat center center; + _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='resources?path=/com/fr/web/ui/images/1x/icon/check_box_normal.png'); _background: none; } .ztree.hack li span.button.chk.checkbox_false_part_focus { diff --git a/dist/fineui.ie.js b/dist/fineui.ie.js index 5b6fef10d..0321f02b8 100644 --- a/dist/fineui.ie.js +++ b/dist/fineui.ie.js @@ -73441,7 +73441,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 可以往当前选中节点下添加新值的下拉树 + * 选中节点不影响父子节点状态的下拉树 * @class BI.MultiTreeListCombo * @extends BI.Single */ @@ -84778,20 +84778,20 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { if(!BI.has(result, node.id)) { createOneJson(node, node.parent && node.parent.id); } - result[node.id].isLeaf = id === path.length - 1; + result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); } }); }); } - function createOneJson(node, pId, leaf) { + function createOneJson(node, pId) { result[node.id] = { id: node.id, pId: pId, text: node.text, value: node.value, open: true, - isLeaf: leaf + isLeaf: node.isLeaf }; } }, @@ -85037,7 +85037,7 @@ BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeListCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, @@ -85090,7 +85090,7 @@ BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeInsertCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/dist/fineui.js b/dist/fineui.js index 1c0b4dd1d..aa8d4eb60 100644 --- a/dist/fineui.js +++ b/dist/fineui.js @@ -73845,7 +73845,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 可以往当前选中节点下添加新值的下拉树 + * 选中节点不影响父子节点状态的下拉树 * @class BI.MultiTreeListCombo * @extends BI.Single */ @@ -85182,20 +85182,20 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { if(!BI.has(result, node.id)) { createOneJson(node, node.parent && node.parent.id); } - result[node.id].isLeaf = id === path.length - 1; + result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); } }); }); } - function createOneJson(node, pId, leaf) { + function createOneJson(node, pId) { result[node.id] = { id: node.id, pId: pId, text: node.text, value: node.value, open: true, - isLeaf: leaf + isLeaf: node.isLeaf }; } }, @@ -85441,7 +85441,7 @@ BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeListCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, @@ -85494,7 +85494,7 @@ BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeInsertCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/dist/fineui_without_jquery_polyfill.js b/dist/fineui_without_jquery_polyfill.js index 66b47d71c..5a9428899 100644 --- a/dist/fineui_without_jquery_polyfill.js +++ b/dist/fineui_without_jquery_polyfill.js @@ -56236,7 +56236,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 可以往当前选中节点下添加新值的下拉树 + * 选中节点不影响父子节点状态的下拉树 * @class BI.MultiTreeListCombo * @extends BI.Single */ @@ -67573,20 +67573,20 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { if(!BI.has(result, node.id)) { createOneJson(node, node.parent && node.parent.id); } - result[node.id].isLeaf = id === path.length - 1; + result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); } }); }); } - function createOneJson(node, pId, leaf) { + function createOneJson(node, pId) { result[node.id] = { id: node.id, pId: pId, text: node.text, value: node.value, open: true, - isLeaf: leaf + isLeaf: node.isLeaf }; } }, @@ -67832,7 +67832,7 @@ BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeListCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, @@ -67885,7 +67885,7 @@ BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeInsertCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/dist/widget.js b/dist/widget.js index 0a3250a50..56d5fc126 100644 --- a/dist/widget.js +++ b/dist/widget.js @@ -13240,7 +13240,7 @@ BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { BI.MultiTreeInsertCombo.EVENT_CONFIRM = "MultiTreeInsertCombo.EVENT_CONFIRM"; BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** - * 可以往当前选中节点下添加新值的下拉树 + * 选中节点不影响父子节点状态的下拉树 * @class BI.MultiTreeListCombo * @extends BI.Single */ @@ -24577,20 +24577,20 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { if(!BI.has(result, node.id)) { createOneJson(node, node.parent && node.parent.id); } - result[node.id].isLeaf = id === path.length - 1; + result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); } }); }); } - function createOneJson(node, pId, leaf) { + function createOneJson(node, pId) { result[node.id] = { id: node.id, pId: pId, text: node.text, value: node.value, open: true, - isLeaf: leaf + isLeaf: node.isLeaf }; } }, @@ -24836,7 +24836,7 @@ BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeListCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, @@ -24889,7 +24889,7 @@ BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeInsertCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/src/component/treevaluechooser/abstract.treevaluechooser.list.js b/src/component/treevaluechooser/abstract.treevaluechooser.list.js index 2d43295dd..da4d21b74 100644 --- a/src/component/treevaluechooser/abstract.treevaluechooser.list.js +++ b/src/component/treevaluechooser/abstract.treevaluechooser.list.js @@ -33,20 +33,20 @@ BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { if(!BI.has(result, node.id)) { createOneJson(node, node.parent && node.parent.id); } - result[node.id].isLeaf = id === path.length - 1; + result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); } }); }); } - function createOneJson(node, pId, leaf) { + function createOneJson(node, pId) { result[node.id] = { id: node.id, pId: pId, text: node.text, value: node.value, open: true, - isLeaf: leaf + isLeaf: node.isLeaf }; } }, diff --git a/src/component/treevaluechooser/combo.listtreevaluechooser.js b/src/component/treevaluechooser/combo.listtreevaluechooser.js index 0a1d327e4..47792fa63 100644 --- a/src/component/treevaluechooser/combo.listtreevaluechooser.js +++ b/src/component/treevaluechooser/combo.listtreevaluechooser.js @@ -32,7 +32,7 @@ BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeListCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/src/component/treevaluechooser/combo.treevaluechooser.insert.js b/src/component/treevaluechooser/combo.treevaluechooser.insert.js index 530c13f54..aadbdfcf7 100644 --- a/src/component/treevaluechooser/combo.treevaluechooser.insert.js +++ b/src/component/treevaluechooser/combo.treevaluechooser.insert.js @@ -32,7 +32,7 @@ BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { height: o.height }); - this.combo.on(BI.MultiTreeCombo.EVENT_CONFIRM, function () { + this.combo.on(BI.MultiTreeInsertCombo.EVENT_CONFIRM, function () { self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); }); }, diff --git a/src/widget/multitree/multi.tree.list.combo.js b/src/widget/multitree/multi.tree.list.combo.js index 8d7f2e9f0..b5d3df844 100644 --- a/src/widget/multitree/multi.tree.list.combo.js +++ b/src/widget/multitree/multi.tree.list.combo.js @@ -1,5 +1,5 @@ /** - * 可以往当前选中节点下添加新值的下拉树 + * 选中节点不影响父子节点状态的下拉树 * @class BI.MultiTreeListCombo * @extends BI.Single */ From 4c531b5ca5aef568b741feb65e127841ab9f5a77 Mon Sep 17 00:00:00 2001 From: windy <1374721899@qq.com> Date: Sun, 5 May 2019 10:35:14 +0800 Subject: [PATCH 4/5] =?UTF-8?q?KERNEL-530=20refactor:=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 changelog.md diff --git a/changelog.md b/changelog.md new file mode 100644 index 000000000..dc5a44de3 --- /dev/null +++ b/changelog.md @@ -0,0 +1,39 @@ +# 更新日志 +2.0(2019-04) +- 新增`bi.multi_tree_list_combo`控件, 此下拉树勾选节点时不会影响父子节点的勾选状态 +- 新增`bi.multi_tree_insert_combo`控件, 此下拉树可以插入不存在的新值 +- 新增`bi.list_tree_value_chooser_insert_combo`部件, 封装`bi.multi_tree_list_combo`数据处理逻辑 +- 新增`bi.tree_value_chooser_insert_combo`部件, 封装`bi.multi_tree_insert_combo`数据处理逻辑 + +2.0(2019-03) +- 新增`bi.time_combo`时分秒控件和`bi.time_periods`时间选择区间,时间区间无有效值校验 +- Label控件增加highlight参数, 可指定初始化标蓝 + +2.0(2019-01) +- 加载更多的单选下拉系列新增allowNoSelect参数配置, 使得可以不选任意一个值 + +2.0(2018-12) +- 增加Button的点击动画和Combo下拉时下拉图标动画 + + +2.0(2018-11) +- 增加`bi.html`和`bi.html_label`类型,text支持html文本,不支持keyword + + +2.0(2018-10) +- popover增加高度自适应,即open的时候回根据内容高度调整popover的高度 + + +2.0(2018-09) +- 增加Fix对configuable为false的对象的不内部构造响应式数据的性能优化处理,例如: + +> this.model.json = Object.freeze({name: "zhang"}); + +只会对this.model.json进行响应式处理,不会对内部的name进行响应式处理 + + +2.0(2018-08) +- 增加BI.mount方法,支持同构 + +2.0(2019-04) +- 增加BI.DOM.ready方法 \ No newline at end of file From c17aa448b2f742d3e3cff351c506f8a1ec7fec35 Mon Sep 17 00:00:00 2001 From: windy <1374721899@qq.com> Date: Sun, 5 May 2019 11:40:12 +0800 Subject: [PATCH 5/5] update --- changelog.md | 6 ++-- .../component/demo.treevaluechoosercombo.js | 31 +++---------------- src/case/tree/ztree/tree.list.display.js | 5 +-- 3 files changed, 7 insertions(+), 35 deletions(-) diff --git a/changelog.md b/changelog.md index dc5a44de3..3caf08032 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,7 @@ - 新增`bi.multi_tree_insert_combo`控件, 此下拉树可以插入不存在的新值 - 新增`bi.list_tree_value_chooser_insert_combo`部件, 封装`bi.multi_tree_list_combo`数据处理逻辑 - 新增`bi.tree_value_chooser_insert_combo`部件, 封装`bi.multi_tree_insert_combo`数据处理逻辑 +- 增加BI.DOM.ready方法 2.0(2019-03) - 新增`bi.time_combo`时分秒控件和`bi.time_periods`时间选择区间,时间区间无有效值校验 @@ -33,7 +34,4 @@ 2.0(2018-08) -- 增加BI.mount方法,支持同构 - -2.0(2019-04) -- 增加BI.DOM.ready方法 \ No newline at end of file +- 增加BI.mount方法,支持同构 \ No newline at end of file diff --git a/demo/js/component/demo.treevaluechoosercombo.js b/demo/js/component/demo.treevaluechoosercombo.js index f91b32ceb..8fa557ee1 100644 --- a/demo/js/component/demo.treevaluechoosercombo.js +++ b/demo/js/component/demo.treevaluechoosercombo.js @@ -5,41 +5,18 @@ Demo.TreeValueChooser = BI.inherit(BI.Widget, { render: function () { var widget = BI.createWidget({ - type: "bi.tree_value_chooser_insert_combo", + type: "bi.tree_value_chooser_combo", width: 300, // items: BI.deepClone(Demo.CONSTANTS.TREEITEMS), itemsCreator: function (op, callback) { callback(BI.deepClone(Demo.CONSTANTS.TREEITEMS)); } }); - var widget1 = BI.createWidget({ - type: "bi.list_tree_value_chooser_insert_combo", - itemsCreator: function (op, callback) { - callback(BI.deepClone(Demo.CONSTANTS.TREEITEMS)); - } - }); - widget.setValue({ - "中国": { - "安徽省": { - "安庆市": {} - } - }, - "newValue": {} - }); - widget1.setValue([ - ["中国", "安徽省"], - ["中国", "安徽省", "安庆市"], - ["newValue"] - ]); return { type: "bi.vertical", - items: [{ - type: "bi.vertical_adapt", - hgap: 200, - vgap: 10, - items: [widget, widget1] - }] - + hgap: 200, + vgap: 10, + items: [widget] }; } }); diff --git a/src/case/tree/ztree/tree.list.display.js b/src/case/tree/ztree/tree.list.display.js index 3be529e13..d8abc2786 100644 --- a/src/case/tree/ztree/tree.list.display.js +++ b/src/case/tree/ztree/tree.list.display.js @@ -44,7 +44,7 @@ BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { } function getFont(treeId, node) { - return node.font ? node.font : {color: "#999999"}; + return node.isLeaf ? {} : {color: "#999999"}; } return setting; @@ -60,9 +60,6 @@ BI.ListDisplayTree = BI.inherit(BI.ListTreeView, { node.text = node.value + "(" + BI.i18nText("BI-Basic_Altogether") + node.count + BI.i18nText("BI-Basic_Count") + ")"; } } - if(node.isLeaf === true) { - node.font = {color: "#3d4d66"}; - } }); return nodes; },