Browse Source

BI-44287 feat: 可以新增值的树控件一起demo

master
windy 6 years ago
parent
commit
19c248cd78
  1. 2
      demo/js/component/demo.treevaluechoosercombo.js
  2. 12
      dist/2.0/fineui.css
  3. 532
      dist/2.0/fineui.ie.js
  4. 532
      dist/2.0/fineui.js
  5. 12
      dist/base.css
  6. 49
      dist/base.js
  7. 12
      dist/bundle.css
  8. 532
      dist/bundle.ie.js
  9. 532
      dist/bundle.js
  10. 16
      dist/core.js
  11. 2
      dist/demo.js
  12. 16
      dist/fineui.css
  13. 532
      dist/fineui.ie.js
  14. 532
      dist/fineui.js
  15. 502
      dist/fineui_without_jquery_polyfill.js
  16. 491
      dist/widget.js
  17. 8
      src/base/tree/ztree/asynctree.js
  18. 7
      src/base/tree/ztree/parttree.js
  19. 23
      src/base/tree/ztree/treeview.js
  20. 48
      src/component/treevaluechooser/abstract.treevaluechooser.js
  21. 54
      src/component/treevaluechooser/combo.treevaluechooser.insert.js
  22. 286
      src/widget/multitree/multi.tree.insert.combo.js
  23. 106
      src/widget/multitree/trigger/multi.tree.search.insert.pane.js

2
demo/js/component/demo.treevaluechoosercombo.js

@ -5,7 +5,7 @@ Demo.TreeValueChooser = BI.inherit(BI.Widget, {
render: function () { render: function () {
var widget = BI.createWidget({ var widget = BI.createWidget({
type: "bi.tree_value_chooser_combo", type: "bi.tree_value_chooser_insert_combo",
width: 300, width: 300,
// items: BI.deepClone(Demo.CONSTANTS.TREEITEMS), // items: BI.deepClone(Demo.CONSTANTS.TREEITEMS),
itemsCreator: function (op, callback) { itemsCreator: function (op, callback) {

12
dist/2.0/fineui.css vendored

@ -3579,7 +3579,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before,
opacity: 0; opacity: 0;
} }
.bi-checkbox.disabled.active .checkbox-content { .bi-checkbox.disabled.active .checkbox-content {
border-color: #e8eaed; border-color: #d0d4da;
} }
.bi-checkbox.disabled.active .checkbox-content:after { .bi-checkbox.disabled.active .checkbox-content:after {
opacity: 1; opacity: 1;
@ -3587,6 +3587,16 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before,
.bi-theme-dark .bi-checkbox .checkbox-content { .bi-theme-dark .bi-checkbox .checkbox-content {
border-color: #9EA6B2; 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 { .bi-file {
opacity: 0; opacity: 0;
filter: alpha(opacity=0); filter: alpha(opacity=0);

532
dist/2.0/fineui.ie.js vendored

@ -37190,8 +37190,8 @@ BI.TreeView = BI.inherit(BI.Pane, {
async: { async: {
enable: true, enable: true,
url: getUrl, url: getUrl,
autoParam: ["id", "name"], autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras) // 静态参数
}, },
check: { check: {
enable: true enable: true
@ -37199,16 +37199,16 @@ BI.TreeView = BI.inherit(BI.Pane, {
data: { data: {
key: { key: {
title: "title", title: "title",
name: "text" name: "text" // 节点的name属性替换成text
}, },
simpleData: { simpleData: {
enable: true enable: true // 可以穿id,pid属性的对象数组
} }
}, },
view: { view: {
showIcon: false, showIcon: false,
expandSpeed: "", expandSpeed: "",
nameIsHTML: true, nameIsHTML: true, // 节点可以用html标签代替
dblClickExpand: false dblClickExpand: false
}, },
callback: { callback: {
@ -37231,6 +37231,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
if(status.half === true && status.checked === true) { if(status.half === true && status.checked === true) {
checked = false; checked = false;
} }
// 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调
self.nodes.checkNode(treeNode, !checked, true, true); self.nodes.checkNode(treeNode, !checked, true, true);
} }
@ -37253,7 +37254,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
return true; return true;
} }
BI.Msg.toast("Please Wait。", "warning"); BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件
return false; return false;
} }
@ -37291,9 +37292,9 @@ BI.TreeView = BI.inherit(BI.Pane, {
function ajaxGetNodes (treeNode, reloadType) { function ajaxGetNodes (treeNode, reloadType) {
var zTree = self.nodes; var zTree = self.nodes;
if (reloadType == "refresh") { 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) { function beforeCheck (treeId, treeNode) {
@ -37371,15 +37372,18 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
var parent = node.parentValues || self._getParentValues(node); var parent = node.parentValues || self._getParentValues(node);
var path = parent.concat(this._getNodeValue(node)); var path = parent.concat(this._getNodeValue(node));
// 当前节点是全选的,因为上面的判断已经排除了不选和半选
if (BI.isNotEmptyArray(node.children) || checkState.half === false) { if (BI.isNotEmptyArray(node.children) || checkState.half === false) {
this._buildTree(map, path); this._buildTree(map, path);
return; return;
} }
// 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况)
var storeValues = BI.deepClone(this.options.paras.selectedValues); var storeValues = BI.deepClone(this.options.paras.selectedValues);
var treeNode = this._getTree(storeValues, path); var treeNode = this._getTree(storeValues, path);
this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode);
}, },
// 获取的是以values最后一个节点为根的子树
_getTree: function (map, values) { _getTree: function (map, values) {
var cur = map; var cur = map;
BI.any(values, function (i, value) { BI.any(values, function (i, value) {
@ -37391,6 +37395,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
return cur; return cur;
}, },
// 以values为path一路向里补充map, 并在末尾节点添加key: value节点
_addTreeNode: function (map, values, key, value) { _addTreeNode: function (map, values, key, value) {
var cur = map; var cur = map;
BI.each(values, function (i, value) { BI.each(values, function (i, value) {
@ -37418,7 +37423,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
var self = this; var self = this;
var hashMap = {}; var hashMap = {};
var rootNoots = this.nodes.getNodes(); var rootNoots = this.nodes.getNodes();
track(rootNoots); track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点
function track (nodes) { function track (nodes) {
BI.each(nodes, function (i, node) { BI.each(nodes, function (i, node) {
var checkState = node.getCheckStatus(); var checkState = node.getCheckStatus();
@ -37666,7 +37671,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
var self = this; var self = this;
var setting = { var setting = {
async: { async: {
enable: false, enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras)
}, },
check: { check: {
@ -37756,6 +37761,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
return setting; return setting;
}, },
// 用来更新this.options.paras.selectedValues, 和ztree内部无关
_selectTreeNode: function (treeId, treeNode) { _selectTreeNode: function (treeId, treeNode) {
var self = this, o = this.options; var self = this, o = this.options;
var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode));
@ -37801,7 +37807,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
function callback (nodes, hasNext) { function callback (nodes, hasNext) {
self.nodes.addNodes(treeNode, nodes); self.nodes.addNodes(treeNode, nodes);
// 展开节点是没有分页的
if (hasNext === true) { if (hasNext === true) {
BI.delay(function () { BI.delay(function () {
times++; 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) { _join: function (valueA, valueB) {
var self = this; var self = this;
var map = {}; var map = {};
@ -37912,6 +37921,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments);
} else { } else {
// 如果选中的值中不存在该值不处理 // 如果选中的值中不存在该值不处理
// 因为反正是不选中,没必要管
var t = this.options.paras.selectedValues; var t = this.options.paras.selectedValues;
var p = parentValues.concat(name); var p = parentValues.concat(name);
for (var i = 0, len = p.length; i < len; i++) { for (var i = 0, len = p.length; i < len; i++) {
@ -37919,6 +37929,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
if (t == null) { if (t == null) {
return; return;
} }
// 选中中国-江苏, 搜索南京,取消勾选
if (BI.isEmpty(t)) { if (BI.isEmpty(t)) {
break; break;
} }
@ -37982,9 +37993,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
} }
var hasNext = !!d.hasNext, nodes = d.items || []; var hasNext = !!d.hasNext, nodes = d.items || [];
o.paras.lastSearchValue = d.lastSearchValue; 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.setTipVisible(nodes.length <= 0);
self.loaded(); self.loaded();
if (!hasNext) { if (!hasNext) {
@ -38890,7 +38900,8 @@ BI.Combo = BI.inherit(BI.Widget, {
}, },
showView: function (e) { showView: function (e) {
if (this.isEnabled() && this.combo.isEnabled()) { // 减少popup 调整宽高的次数
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) {
this._popupView(e); this._popupView(e);
} }
}, },
@ -72488,6 +72499,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, {
BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM";
BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** 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 * @class BI.MultiTreePopup
* @extends BI.Pane * @extends BI.Pane
@ -72724,6 +73020,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, {
BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** 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 * searcher
* Created by guy on 15/11/3. * Created by guy on 15/11/3.
* @class BI.MultiTreeSearcher * @class BI.MultiTreeSearcher
@ -82600,10 +83001,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
} }
BI.each(selected, function (k) { BI.each(selected, function (k) {
var node = self._getTreeNode(parentValues, k); var node = self._getTreeNode(parentValues, k);
var newParents = BI.clone(parentValues); // 找不到就是新增值
newParents.push(node.value); if(BI.isNull(node)) {
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); createOneJson({
doCheck(newParents, node, selected[k]); 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 result = [];
var keyword = op.keyword || ""; var keyword = op.keyword || "";
var selectedValues = op.selectedValues; var selectedValues = op.selectedValues;
var lastSearchValue = op.lastSearchValue || ""; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引
var output = search(); var output = search();
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
@ -82900,6 +83310,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
break; 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; return output;
} }
@ -83029,6 +83448,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
halfCheck: state[1] halfCheck: state[1]
}); });
} }
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加
if (parentValues.length === 0 && times === 1) {
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result);
}
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
items: result, 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) { _getNode: function (selectedValues, parentValues) {
var pNode = selectedValues; var pNode = selectedValues;
for (var i = 0, len = parentValues.length; i < len; i++) { 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; 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. * Created by GUY on 2015/10/29.

532
dist/2.0/fineui.js vendored

@ -37594,8 +37594,8 @@ BI.TreeView = BI.inherit(BI.Pane, {
async: { async: {
enable: true, enable: true,
url: getUrl, url: getUrl,
autoParam: ["id", "name"], autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras) // 静态参数
}, },
check: { check: {
enable: true enable: true
@ -37603,16 +37603,16 @@ BI.TreeView = BI.inherit(BI.Pane, {
data: { data: {
key: { key: {
title: "title", title: "title",
name: "text" name: "text" // 节点的name属性替换成text
}, },
simpleData: { simpleData: {
enable: true enable: true // 可以穿id,pid属性的对象数组
} }
}, },
view: { view: {
showIcon: false, showIcon: false,
expandSpeed: "", expandSpeed: "",
nameIsHTML: true, nameIsHTML: true, // 节点可以用html标签代替
dblClickExpand: false dblClickExpand: false
}, },
callback: { callback: {
@ -37635,6 +37635,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
if(status.half === true && status.checked === true) { if(status.half === true && status.checked === true) {
checked = false; checked = false;
} }
// 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调
self.nodes.checkNode(treeNode, !checked, true, true); self.nodes.checkNode(treeNode, !checked, true, true);
} }
@ -37657,7 +37658,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
return true; return true;
} }
BI.Msg.toast("Please Wait。", "warning"); BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件
return false; return false;
} }
@ -37695,9 +37696,9 @@ BI.TreeView = BI.inherit(BI.Pane, {
function ajaxGetNodes (treeNode, reloadType) { function ajaxGetNodes (treeNode, reloadType) {
var zTree = self.nodes; var zTree = self.nodes;
if (reloadType == "refresh") { 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) { function beforeCheck (treeId, treeNode) {
@ -37775,15 +37776,18 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
var parent = node.parentValues || self._getParentValues(node); var parent = node.parentValues || self._getParentValues(node);
var path = parent.concat(this._getNodeValue(node)); var path = parent.concat(this._getNodeValue(node));
// 当前节点是全选的,因为上面的判断已经排除了不选和半选
if (BI.isNotEmptyArray(node.children) || checkState.half === false) { if (BI.isNotEmptyArray(node.children) || checkState.half === false) {
this._buildTree(map, path); this._buildTree(map, path);
return; return;
} }
// 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况)
var storeValues = BI.deepClone(this.options.paras.selectedValues); var storeValues = BI.deepClone(this.options.paras.selectedValues);
var treeNode = this._getTree(storeValues, path); var treeNode = this._getTree(storeValues, path);
this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode);
}, },
// 获取的是以values最后一个节点为根的子树
_getTree: function (map, values) { _getTree: function (map, values) {
var cur = map; var cur = map;
BI.any(values, function (i, value) { BI.any(values, function (i, value) {
@ -37795,6 +37799,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
return cur; return cur;
}, },
// 以values为path一路向里补充map, 并在末尾节点添加key: value节点
_addTreeNode: function (map, values, key, value) { _addTreeNode: function (map, values, key, value) {
var cur = map; var cur = map;
BI.each(values, function (i, value) { BI.each(values, function (i, value) {
@ -37822,7 +37827,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
var self = this; var self = this;
var hashMap = {}; var hashMap = {};
var rootNoots = this.nodes.getNodes(); var rootNoots = this.nodes.getNodes();
track(rootNoots); track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点
function track (nodes) { function track (nodes) {
BI.each(nodes, function (i, node) { BI.each(nodes, function (i, node) {
var checkState = node.getCheckStatus(); var checkState = node.getCheckStatus();
@ -38070,7 +38075,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
var self = this; var self = this;
var setting = { var setting = {
async: { async: {
enable: false, enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras)
}, },
check: { check: {
@ -38160,6 +38165,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
return setting; return setting;
}, },
// 用来更新this.options.paras.selectedValues, 和ztree内部无关
_selectTreeNode: function (treeId, treeNode) { _selectTreeNode: function (treeId, treeNode) {
var self = this, o = this.options; var self = this, o = this.options;
var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode));
@ -38205,7 +38211,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
function callback (nodes, hasNext) { function callback (nodes, hasNext) {
self.nodes.addNodes(treeNode, nodes); self.nodes.addNodes(treeNode, nodes);
// 展开节点是没有分页的
if (hasNext === true) { if (hasNext === true) {
BI.delay(function () { BI.delay(function () {
times++; 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) { _join: function (valueA, valueB) {
var self = this; var self = this;
var map = {}; var map = {};
@ -38316,6 +38325,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments);
} else { } else {
// 如果选中的值中不存在该值不处理 // 如果选中的值中不存在该值不处理
// 因为反正是不选中,没必要管
var t = this.options.paras.selectedValues; var t = this.options.paras.selectedValues;
var p = parentValues.concat(name); var p = parentValues.concat(name);
for (var i = 0, len = p.length; i < len; i++) { for (var i = 0, len = p.length; i < len; i++) {
@ -38323,6 +38333,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
if (t == null) { if (t == null) {
return; return;
} }
// 选中中国-江苏, 搜索南京,取消勾选
if (BI.isEmpty(t)) { if (BI.isEmpty(t)) {
break; break;
} }
@ -38386,9 +38397,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
} }
var hasNext = !!d.hasNext, nodes = d.items || []; var hasNext = !!d.hasNext, nodes = d.items || [];
o.paras.lastSearchValue = d.lastSearchValue; 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.setTipVisible(nodes.length <= 0);
self.loaded(); self.loaded();
if (!hasNext) { if (!hasNext) {
@ -39294,7 +39304,8 @@ BI.Combo = BI.inherit(BI.Widget, {
}, },
showView: function (e) { showView: function (e) {
if (this.isEnabled() && this.combo.isEnabled()) { // 减少popup 调整宽高的次数
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) {
this._popupView(e); this._popupView(e);
} }
}, },
@ -72892,6 +72903,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, {
BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM";
BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** 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 * @class BI.MultiTreePopup
* @extends BI.Pane * @extends BI.Pane
@ -73128,6 +73424,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, {
BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** 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 * searcher
* Created by guy on 15/11/3. * Created by guy on 15/11/3.
* @class BI.MultiTreeSearcher * @class BI.MultiTreeSearcher
@ -83004,10 +83405,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
} }
BI.each(selected, function (k) { BI.each(selected, function (k) {
var node = self._getTreeNode(parentValues, k); var node = self._getTreeNode(parentValues, k);
var newParents = BI.clone(parentValues); // 找不到就是新增值
newParents.push(node.value); if(BI.isNull(node)) {
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); createOneJson({
doCheck(newParents, node, selected[k]); 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 result = [];
var keyword = op.keyword || ""; var keyword = op.keyword || "";
var selectedValues = op.selectedValues; var selectedValues = op.selectedValues;
var lastSearchValue = op.lastSearchValue || ""; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引
var output = search(); var output = search();
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
@ -83304,6 +83714,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
break; 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; return output;
} }
@ -83433,6 +83852,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
halfCheck: state[1] halfCheck: state[1]
}); });
} }
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加
if (parentValues.length === 0 && times === 1) {
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result);
}
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
items: result, 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) { _getNode: function (selectedValues, parentValues) {
var pNode = selectedValues; var pNode = selectedValues;
for (var i = 0, len = parentValues.length; i < len; i++) { 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; 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. * Created by GUY on 2015/10/29.

12
dist/base.css vendored

@ -1423,7 +1423,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before,
opacity: 0; opacity: 0;
} }
.bi-checkbox.disabled.active .checkbox-content { .bi-checkbox.disabled.active .checkbox-content {
border-color: #e8eaed; border-color: #d0d4da;
} }
.bi-checkbox.disabled.active .checkbox-content:after { .bi-checkbox.disabled.active .checkbox-content:after {
opacity: 1; opacity: 1;
@ -1431,6 +1431,16 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before,
.bi-theme-dark .bi-checkbox .checkbox-content { .bi-theme-dark .bi-checkbox .checkbox-content {
border-color: #9EA6B2; 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 { .bi-file {
opacity: 0; opacity: 0;
filter: alpha(opacity=0); filter: alpha(opacity=0);

49
dist/base.js vendored

@ -1727,8 +1727,8 @@ BI.TreeView = BI.inherit(BI.Pane, {
async: { async: {
enable: true, enable: true,
url: getUrl, url: getUrl,
autoParam: ["id", "name"], autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras) // 静态参数
}, },
check: { check: {
enable: true enable: true
@ -1736,16 +1736,16 @@ BI.TreeView = BI.inherit(BI.Pane, {
data: { data: {
key: { key: {
title: "title", title: "title",
name: "text" name: "text" // 节点的name属性替换成text
}, },
simpleData: { simpleData: {
enable: true enable: true // 可以穿id,pid属性的对象数组
} }
}, },
view: { view: {
showIcon: false, showIcon: false,
expandSpeed: "", expandSpeed: "",
nameIsHTML: true, nameIsHTML: true, // 节点可以用html标签代替
dblClickExpand: false dblClickExpand: false
}, },
callback: { callback: {
@ -1768,6 +1768,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
if(status.half === true && status.checked === true) { if(status.half === true && status.checked === true) {
checked = false; checked = false;
} }
// 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调
self.nodes.checkNode(treeNode, !checked, true, true); self.nodes.checkNode(treeNode, !checked, true, true);
} }
@ -1790,7 +1791,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
return true; return true;
} }
BI.Msg.toast("Please Wait。", "warning"); BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件
return false; return false;
} }
@ -1828,9 +1829,9 @@ BI.TreeView = BI.inherit(BI.Pane, {
function ajaxGetNodes (treeNode, reloadType) { function ajaxGetNodes (treeNode, reloadType) {
var zTree = self.nodes; var zTree = self.nodes;
if (reloadType == "refresh") { 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) { function beforeCheck (treeId, treeNode) {
@ -1908,15 +1909,18 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
var parent = node.parentValues || self._getParentValues(node); var parent = node.parentValues || self._getParentValues(node);
var path = parent.concat(this._getNodeValue(node)); var path = parent.concat(this._getNodeValue(node));
// 当前节点是全选的,因为上面的判断已经排除了不选和半选
if (BI.isNotEmptyArray(node.children) || checkState.half === false) { if (BI.isNotEmptyArray(node.children) || checkState.half === false) {
this._buildTree(map, path); this._buildTree(map, path);
return; return;
} }
// 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况)
var storeValues = BI.deepClone(this.options.paras.selectedValues); var storeValues = BI.deepClone(this.options.paras.selectedValues);
var treeNode = this._getTree(storeValues, path); var treeNode = this._getTree(storeValues, path);
this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode);
}, },
// 获取的是以values最后一个节点为根的子树
_getTree: function (map, values) { _getTree: function (map, values) {
var cur = map; var cur = map;
BI.any(values, function (i, value) { BI.any(values, function (i, value) {
@ -1928,6 +1932,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
return cur; return cur;
}, },
// 以values为path一路向里补充map, 并在末尾节点添加key: value节点
_addTreeNode: function (map, values, key, value) { _addTreeNode: function (map, values, key, value) {
var cur = map; var cur = map;
BI.each(values, function (i, value) { BI.each(values, function (i, value) {
@ -1955,7 +1960,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
var self = this; var self = this;
var hashMap = {}; var hashMap = {};
var rootNoots = this.nodes.getNodes(); var rootNoots = this.nodes.getNodes();
track(rootNoots); track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点
function track (nodes) { function track (nodes) {
BI.each(nodes, function (i, node) { BI.each(nodes, function (i, node) {
var checkState = node.getCheckStatus(); var checkState = node.getCheckStatus();
@ -2203,7 +2208,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
var self = this; var self = this;
var setting = { var setting = {
async: { async: {
enable: false, enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras)
}, },
check: { check: {
@ -2293,6 +2298,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
return setting; return setting;
}, },
// 用来更新this.options.paras.selectedValues, 和ztree内部无关
_selectTreeNode: function (treeId, treeNode) { _selectTreeNode: function (treeId, treeNode) {
var self = this, o = this.options; var self = this, o = this.options;
var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode));
@ -2338,7 +2344,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
function callback (nodes, hasNext) { function callback (nodes, hasNext) {
self.nodes.addNodes(treeNode, nodes); self.nodes.addNodes(treeNode, nodes);
// 展开节点是没有分页的
if (hasNext === true) { if (hasNext === true) {
BI.delay(function () { BI.delay(function () {
times++; 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) { _join: function (valueA, valueB) {
var self = this; var self = this;
var map = {}; var map = {};
@ -2449,6 +2458,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments);
} else { } else {
// 如果选中的值中不存在该值不处理 // 如果选中的值中不存在该值不处理
// 因为反正是不选中,没必要管
var t = this.options.paras.selectedValues; var t = this.options.paras.selectedValues;
var p = parentValues.concat(name); var p = parentValues.concat(name);
for (var i = 0, len = p.length; i < len; i++) { for (var i = 0, len = p.length; i < len; i++) {
@ -2456,6 +2466,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
if (t == null) { if (t == null) {
return; return;
} }
// 选中中国-江苏, 搜索南京,取消勾选
if (BI.isEmpty(t)) { if (BI.isEmpty(t)) {
break; break;
} }
@ -2519,9 +2530,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
} }
var hasNext = !!d.hasNext, nodes = d.items || []; var hasNext = !!d.hasNext, nodes = d.items || [];
o.paras.lastSearchValue = d.lastSearchValue; 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.setTipVisible(nodes.length <= 0);
self.loaded(); self.loaded();
if (!hasNext) { if (!hasNext) {
@ -3427,7 +3437,8 @@ BI.Combo = BI.inherit(BI.Widget, {
}, },
showView: function (e) { showView: function (e) {
if (this.isEnabled() && this.combo.isEnabled()) { // 减少popup 调整宽高的次数
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) {
this._popupView(e); this._popupView(e);
} }
}, },
@ -6149,7 +6160,7 @@ BI.PopupView = BI.inherit(BI.Widget, {
var tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0, var tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0,
tabHeight = this.tab ? (this.tab.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); 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.resetHeight ? this.view.resetHeight(resetHeight) :
this.view.element.css({"max-height": resetHeight + "px"}); this.view.element.css({"max-height": resetHeight + "px"});
}, },
@ -10067,8 +10078,10 @@ BI.Input = BI.inherit(BI.Single, {
}) })
.on("input propertychange", function (e) { .on("input propertychange", function (e) {
// 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了 // 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了
// 这个事件在input的属性发生改变的时候就会触发(class的变化也算) // 其中propertychange在元素属性发生改变的时候就会触发 是为了兼容IE8
if (BI.isNotNull(keyCode)) { // 通过keyCode判断会漏掉输入法点击输入(右键粘贴暂缓)
var originalEvent = e.originalEvent;
if (BI.isNull(originalEvent.propertyName) || originalEvent.propertyName === "value") {
keyCode = null; keyCode = null;
inputEventValid = true; inputEventValid = true;
self._keydown_ = true; self._keydown_ = true;

12
dist/bundle.css vendored

@ -3579,7 +3579,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before,
opacity: 0; opacity: 0;
} }
.bi-checkbox.disabled.active .checkbox-content { .bi-checkbox.disabled.active .checkbox-content {
border-color: #e8eaed; border-color: #d0d4da;
} }
.bi-checkbox.disabled.active .checkbox-content:after { .bi-checkbox.disabled.active .checkbox-content:after {
opacity: 1; opacity: 1;
@ -3587,6 +3587,16 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before,
.bi-theme-dark .bi-checkbox .checkbox-content { .bi-theme-dark .bi-checkbox .checkbox-content {
border-color: #9EA6B2; 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 { .bi-file {
opacity: 0; opacity: 0;
filter: alpha(opacity=0); filter: alpha(opacity=0);

532
dist/bundle.ie.js vendored

@ -37190,8 +37190,8 @@ BI.TreeView = BI.inherit(BI.Pane, {
async: { async: {
enable: true, enable: true,
url: getUrl, url: getUrl,
autoParam: ["id", "name"], autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras) // 静态参数
}, },
check: { check: {
enable: true enable: true
@ -37199,16 +37199,16 @@ BI.TreeView = BI.inherit(BI.Pane, {
data: { data: {
key: { key: {
title: "title", title: "title",
name: "text" name: "text" // 节点的name属性替换成text
}, },
simpleData: { simpleData: {
enable: true enable: true // 可以穿id,pid属性的对象数组
} }
}, },
view: { view: {
showIcon: false, showIcon: false,
expandSpeed: "", expandSpeed: "",
nameIsHTML: true, nameIsHTML: true, // 节点可以用html标签代替
dblClickExpand: false dblClickExpand: false
}, },
callback: { callback: {
@ -37231,6 +37231,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
if(status.half === true && status.checked === true) { if(status.half === true && status.checked === true) {
checked = false; checked = false;
} }
// 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调
self.nodes.checkNode(treeNode, !checked, true, true); self.nodes.checkNode(treeNode, !checked, true, true);
} }
@ -37253,7 +37254,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
return true; return true;
} }
BI.Msg.toast("Please Wait。", "warning"); BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件
return false; return false;
} }
@ -37291,9 +37292,9 @@ BI.TreeView = BI.inherit(BI.Pane, {
function ajaxGetNodes (treeNode, reloadType) { function ajaxGetNodes (treeNode, reloadType) {
var zTree = self.nodes; var zTree = self.nodes;
if (reloadType == "refresh") { 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) { function beforeCheck (treeId, treeNode) {
@ -37371,15 +37372,18 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
var parent = node.parentValues || self._getParentValues(node); var parent = node.parentValues || self._getParentValues(node);
var path = parent.concat(this._getNodeValue(node)); var path = parent.concat(this._getNodeValue(node));
// 当前节点是全选的,因为上面的判断已经排除了不选和半选
if (BI.isNotEmptyArray(node.children) || checkState.half === false) { if (BI.isNotEmptyArray(node.children) || checkState.half === false) {
this._buildTree(map, path); this._buildTree(map, path);
return; return;
} }
// 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况)
var storeValues = BI.deepClone(this.options.paras.selectedValues); var storeValues = BI.deepClone(this.options.paras.selectedValues);
var treeNode = this._getTree(storeValues, path); var treeNode = this._getTree(storeValues, path);
this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode);
}, },
// 获取的是以values最后一个节点为根的子树
_getTree: function (map, values) { _getTree: function (map, values) {
var cur = map; var cur = map;
BI.any(values, function (i, value) { BI.any(values, function (i, value) {
@ -37391,6 +37395,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
return cur; return cur;
}, },
// 以values为path一路向里补充map, 并在末尾节点添加key: value节点
_addTreeNode: function (map, values, key, value) { _addTreeNode: function (map, values, key, value) {
var cur = map; var cur = map;
BI.each(values, function (i, value) { BI.each(values, function (i, value) {
@ -37418,7 +37423,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
var self = this; var self = this;
var hashMap = {}; var hashMap = {};
var rootNoots = this.nodes.getNodes(); var rootNoots = this.nodes.getNodes();
track(rootNoots); track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点
function track (nodes) { function track (nodes) {
BI.each(nodes, function (i, node) { BI.each(nodes, function (i, node) {
var checkState = node.getCheckStatus(); var checkState = node.getCheckStatus();
@ -37666,7 +37671,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
var self = this; var self = this;
var setting = { var setting = {
async: { async: {
enable: false, enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras)
}, },
check: { check: {
@ -37756,6 +37761,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
return setting; return setting;
}, },
// 用来更新this.options.paras.selectedValues, 和ztree内部无关
_selectTreeNode: function (treeId, treeNode) { _selectTreeNode: function (treeId, treeNode) {
var self = this, o = this.options; var self = this, o = this.options;
var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode));
@ -37801,7 +37807,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
function callback (nodes, hasNext) { function callback (nodes, hasNext) {
self.nodes.addNodes(treeNode, nodes); self.nodes.addNodes(treeNode, nodes);
// 展开节点是没有分页的
if (hasNext === true) { if (hasNext === true) {
BI.delay(function () { BI.delay(function () {
times++; 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) { _join: function (valueA, valueB) {
var self = this; var self = this;
var map = {}; var map = {};
@ -37912,6 +37921,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments);
} else { } else {
// 如果选中的值中不存在该值不处理 // 如果选中的值中不存在该值不处理
// 因为反正是不选中,没必要管
var t = this.options.paras.selectedValues; var t = this.options.paras.selectedValues;
var p = parentValues.concat(name); var p = parentValues.concat(name);
for (var i = 0, len = p.length; i < len; i++) { for (var i = 0, len = p.length; i < len; i++) {
@ -37919,6 +37929,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
if (t == null) { if (t == null) {
return; return;
} }
// 选中中国-江苏, 搜索南京,取消勾选
if (BI.isEmpty(t)) { if (BI.isEmpty(t)) {
break; break;
} }
@ -37982,9 +37993,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
} }
var hasNext = !!d.hasNext, nodes = d.items || []; var hasNext = !!d.hasNext, nodes = d.items || [];
o.paras.lastSearchValue = d.lastSearchValue; 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.setTipVisible(nodes.length <= 0);
self.loaded(); self.loaded();
if (!hasNext) { if (!hasNext) {
@ -38890,7 +38900,8 @@ BI.Combo = BI.inherit(BI.Widget, {
}, },
showView: function (e) { showView: function (e) {
if (this.isEnabled() && this.combo.isEnabled()) { // 减少popup 调整宽高的次数
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) {
this._popupView(e); this._popupView(e);
} }
}, },
@ -72488,6 +72499,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, {
BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM";
BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** 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 * @class BI.MultiTreePopup
* @extends BI.Pane * @extends BI.Pane
@ -72724,6 +73020,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, {
BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** 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 * searcher
* Created by guy on 15/11/3. * Created by guy on 15/11/3.
* @class BI.MultiTreeSearcher * @class BI.MultiTreeSearcher
@ -82600,10 +83001,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
} }
BI.each(selected, function (k) { BI.each(selected, function (k) {
var node = self._getTreeNode(parentValues, k); var node = self._getTreeNode(parentValues, k);
var newParents = BI.clone(parentValues); // 找不到就是新增值
newParents.push(node.value); if(BI.isNull(node)) {
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); createOneJson({
doCheck(newParents, node, selected[k]); 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 result = [];
var keyword = op.keyword || ""; var keyword = op.keyword || "";
var selectedValues = op.selectedValues; var selectedValues = op.selectedValues;
var lastSearchValue = op.lastSearchValue || ""; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引
var output = search(); var output = search();
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
@ -82900,6 +83310,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
break; 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; return output;
} }
@ -83029,6 +83448,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
halfCheck: state[1] halfCheck: state[1]
}); });
} }
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加
if (parentValues.length === 0 && times === 1) {
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result);
}
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
items: result, 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) { _getNode: function (selectedValues, parentValues) {
var pNode = selectedValues; var pNode = selectedValues;
for (var i = 0, len = parentValues.length; i < len; i++) { 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; 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. * Created by GUY on 2015/10/29.

532
dist/bundle.js vendored

@ -37594,8 +37594,8 @@ BI.TreeView = BI.inherit(BI.Pane, {
async: { async: {
enable: true, enable: true,
url: getUrl, url: getUrl,
autoParam: ["id", "name"], autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras) // 静态参数
}, },
check: { check: {
enable: true enable: true
@ -37603,16 +37603,16 @@ BI.TreeView = BI.inherit(BI.Pane, {
data: { data: {
key: { key: {
title: "title", title: "title",
name: "text" name: "text" // 节点的name属性替换成text
}, },
simpleData: { simpleData: {
enable: true enable: true // 可以穿id,pid属性的对象数组
} }
}, },
view: { view: {
showIcon: false, showIcon: false,
expandSpeed: "", expandSpeed: "",
nameIsHTML: true, nameIsHTML: true, // 节点可以用html标签代替
dblClickExpand: false dblClickExpand: false
}, },
callback: { callback: {
@ -37635,6 +37635,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
if(status.half === true && status.checked === true) { if(status.half === true && status.checked === true) {
checked = false; checked = false;
} }
// 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调
self.nodes.checkNode(treeNode, !checked, true, true); self.nodes.checkNode(treeNode, !checked, true, true);
} }
@ -37657,7 +37658,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
return true; return true;
} }
BI.Msg.toast("Please Wait。", "warning"); BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件
return false; return false;
} }
@ -37695,9 +37696,9 @@ BI.TreeView = BI.inherit(BI.Pane, {
function ajaxGetNodes (treeNode, reloadType) { function ajaxGetNodes (treeNode, reloadType) {
var zTree = self.nodes; var zTree = self.nodes;
if (reloadType == "refresh") { 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) { function beforeCheck (treeId, treeNode) {
@ -37775,15 +37776,18 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
var parent = node.parentValues || self._getParentValues(node); var parent = node.parentValues || self._getParentValues(node);
var path = parent.concat(this._getNodeValue(node)); var path = parent.concat(this._getNodeValue(node));
// 当前节点是全选的,因为上面的判断已经排除了不选和半选
if (BI.isNotEmptyArray(node.children) || checkState.half === false) { if (BI.isNotEmptyArray(node.children) || checkState.half === false) {
this._buildTree(map, path); this._buildTree(map, path);
return; return;
} }
// 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况)
var storeValues = BI.deepClone(this.options.paras.selectedValues); var storeValues = BI.deepClone(this.options.paras.selectedValues);
var treeNode = this._getTree(storeValues, path); var treeNode = this._getTree(storeValues, path);
this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode);
}, },
// 获取的是以values最后一个节点为根的子树
_getTree: function (map, values) { _getTree: function (map, values) {
var cur = map; var cur = map;
BI.any(values, function (i, value) { BI.any(values, function (i, value) {
@ -37795,6 +37799,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
return cur; return cur;
}, },
// 以values为path一路向里补充map, 并在末尾节点添加key: value节点
_addTreeNode: function (map, values, key, value) { _addTreeNode: function (map, values, key, value) {
var cur = map; var cur = map;
BI.each(values, function (i, value) { BI.each(values, function (i, value) {
@ -37822,7 +37827,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
var self = this; var self = this;
var hashMap = {}; var hashMap = {};
var rootNoots = this.nodes.getNodes(); var rootNoots = this.nodes.getNodes();
track(rootNoots); track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点
function track (nodes) { function track (nodes) {
BI.each(nodes, function (i, node) { BI.each(nodes, function (i, node) {
var checkState = node.getCheckStatus(); var checkState = node.getCheckStatus();
@ -38070,7 +38075,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
var self = this; var self = this;
var setting = { var setting = {
async: { async: {
enable: false, enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras)
}, },
check: { check: {
@ -38160,6 +38165,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
return setting; return setting;
}, },
// 用来更新this.options.paras.selectedValues, 和ztree内部无关
_selectTreeNode: function (treeId, treeNode) { _selectTreeNode: function (treeId, treeNode) {
var self = this, o = this.options; var self = this, o = this.options;
var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode));
@ -38205,7 +38211,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
function callback (nodes, hasNext) { function callback (nodes, hasNext) {
self.nodes.addNodes(treeNode, nodes); self.nodes.addNodes(treeNode, nodes);
// 展开节点是没有分页的
if (hasNext === true) { if (hasNext === true) {
BI.delay(function () { BI.delay(function () {
times++; 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) { _join: function (valueA, valueB) {
var self = this; var self = this;
var map = {}; var map = {};
@ -38316,6 +38325,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments);
} else { } else {
// 如果选中的值中不存在该值不处理 // 如果选中的值中不存在该值不处理
// 因为反正是不选中,没必要管
var t = this.options.paras.selectedValues; var t = this.options.paras.selectedValues;
var p = parentValues.concat(name); var p = parentValues.concat(name);
for (var i = 0, len = p.length; i < len; i++) { for (var i = 0, len = p.length; i < len; i++) {
@ -38323,6 +38333,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
if (t == null) { if (t == null) {
return; return;
} }
// 选中中国-江苏, 搜索南京,取消勾选
if (BI.isEmpty(t)) { if (BI.isEmpty(t)) {
break; break;
} }
@ -38386,9 +38397,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
} }
var hasNext = !!d.hasNext, nodes = d.items || []; var hasNext = !!d.hasNext, nodes = d.items || [];
o.paras.lastSearchValue = d.lastSearchValue; 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.setTipVisible(nodes.length <= 0);
self.loaded(); self.loaded();
if (!hasNext) { if (!hasNext) {
@ -39294,7 +39304,8 @@ BI.Combo = BI.inherit(BI.Widget, {
}, },
showView: function (e) { showView: function (e) {
if (this.isEnabled() && this.combo.isEnabled()) { // 减少popup 调整宽高的次数
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) {
this._popupView(e); this._popupView(e);
} }
}, },
@ -72892,6 +72903,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, {
BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM";
BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** 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 * @class BI.MultiTreePopup
* @extends BI.Pane * @extends BI.Pane
@ -73128,6 +73424,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, {
BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** 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 * searcher
* Created by guy on 15/11/3. * Created by guy on 15/11/3.
* @class BI.MultiTreeSearcher * @class BI.MultiTreeSearcher
@ -83004,10 +83405,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
} }
BI.each(selected, function (k) { BI.each(selected, function (k) {
var node = self._getTreeNode(parentValues, k); var node = self._getTreeNode(parentValues, k);
var newParents = BI.clone(parentValues); // 找不到就是新增值
newParents.push(node.value); if(BI.isNull(node)) {
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); createOneJson({
doCheck(newParents, node, selected[k]); 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 result = [];
var keyword = op.keyword || ""; var keyword = op.keyword || "";
var selectedValues = op.selectedValues; var selectedValues = op.selectedValues;
var lastSearchValue = op.lastSearchValue || ""; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引
var output = search(); var output = search();
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
@ -83304,6 +83714,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
break; 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; return output;
} }
@ -83433,6 +83852,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
halfCheck: state[1] halfCheck: state[1]
}); });
} }
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加
if (parentValues.length === 0 && times === 1) {
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result);
}
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
items: result, 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) { _getNode: function (selectedValues, parentValues) {
var pNode = selectedValues; var pNode = selectedValues;
for (var i = 0, len = parentValues.length; i < len; i++) { 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; 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. * Created by GUY on 2015/10/29.

16
dist/core.js vendored

@ -19976,7 +19976,7 @@ BI.prepares.push(function () {
var i, direct; var i, direct;
var leftRight = [], topBottom = []; var leftRight = [], topBottom = [];
var isNeedAdaptHeight = false, tbFirst = false, lrFirst = false; 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++) { for (i = 0; i < directions.length; i++) {
direct = directions[i]; direct = directions[i];
switch (direct) { switch (direct) {
@ -20086,39 +20086,45 @@ BI.prepares.push(function () {
} }
} }
// 此处为四个方向放不下时挑空间最大的方向去放置, 也就是说我设置了弹出方向为"bottom,left",
// 最后发现实际弹出方向可能是"top,left",那么此时外界获取popup的方向应该是"top,left"
switch (directions[0]) { switch (directions[0]) {
case "left": case "left":
case "right": case "right":
if (BI.DOM.isRightSpaceLarger(combo)) { if (BI.DOM.isRightSpaceLarger(combo)) {
left = BI.DOM.getRightAdaptPosition(combo, popup, extraWidth).left; left = BI.DOM.getRightAdaptPosition(combo, popup, extraWidth).left;
firstDir = "right";
} else { } else {
left = BI.DOM.getLeftAdaptPosition(combo, popup, extraWidth).left; left = BI.DOM.getLeftAdaptPosition(combo, popup, extraWidth).left;
firstDir = "left";
} }
if (topBottom[0] === "bottom") { if (topBottom[0] === "bottom") {
pos = BI.DOM.getTopAlignPosition(combo, popup, extraHeight, needAdaptHeight); pos = BI.DOM.getTopAlignPosition(combo, popup, extraHeight, needAdaptHeight);
pos.left = left; pos.left = left;
pos.dir = directions[0] + ",bottom"; pos.dir = firstDir + ",bottom";
return pos; return pos;
} }
pos = BI.DOM.getBottomAlignPosition(combo, popup, extraHeight, needAdaptHeight); pos = BI.DOM.getBottomAlignPosition(combo, popup, extraHeight, needAdaptHeight);
pos.left = left; pos.left = left;
pos.dir = directions[0] + ",top"; pos.dir = firstDir + ",top";
return pos; return pos;
default : default :
if (BI.DOM.isBottomSpaceLarger(combo)) { if (BI.DOM.isBottomSpaceLarger(combo)) {
pos = BI.DOM.getBottomAdaptPosition(combo, popup, extraHeight, needAdaptHeight); pos = BI.DOM.getBottomAdaptPosition(combo, popup, extraHeight, needAdaptHeight);
firstDir = "bottom";
} else { } else {
pos = BI.DOM.getTopAdaptPosition(combo, popup, extraHeight, needAdaptHeight); pos = BI.DOM.getTopAdaptPosition(combo, popup, extraHeight, needAdaptHeight);
firstDir = "top";
} }
if (leftRight[0] === "right") { if (leftRight[0] === "right") {
left = BI.DOM.getLeftAlignPosition(combo, popup, extraWidth, needAdaptHeight).left; left = BI.DOM.getLeftAlignPosition(combo, popup, extraWidth, needAdaptHeight).left;
pos.left = left; pos.left = left;
pos.dir = directions[0] + ",right"; pos.dir = firstDir + ",right";
return pos; return pos;
} }
left = BI.DOM.getRightAlignPosition(combo, popup, extraWidth).left; left = BI.DOM.getRightAlignPosition(combo, popup, extraWidth).left;
pos.left = left; pos.left = left;
pos.dir = directions[0] + ",left"; pos.dir = firstDir + ",left";
return pos; return pos;
} }
}, },

2
dist/demo.js vendored

@ -2700,7 +2700,7 @@ BI.shortcut("demo.center", Demo.Center);Demo.TreeValueChooser = BI.inherit(BI.Wi
render: function () { render: function () {
var widget = BI.createWidget({ var widget = BI.createWidget({
type: "bi.tree_value_chooser_combo", type: "bi.tree_value_chooser_insert_combo",
width: 300, width: 300,
// items: BI.deepClone(Demo.CONSTANTS.TREEITEMS), // items: BI.deepClone(Demo.CONSTANTS.TREEITEMS),
itemsCreator: function (op, callback) { itemsCreator: function (op, callback) {

16
dist/fineui.css vendored

@ -3572,12 +3572,14 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before,
border-color: #ffffff; border-color: #ffffff;
opacity: 1; opacity: 1;
} }
.bi-checkbox.disabled .checkbox-content {
background-color: #d0d4da;
}
.bi-checkbox.disabled .checkbox-content:after { .bi-checkbox.disabled .checkbox-content:after {
opacity: 0; opacity: 0;
} }
.bi-checkbox.disabled.active .checkbox-content { .bi-checkbox.disabled.active .checkbox-content {
border-color: #e8eaed; border-color: #d0d4da;
background-color: #d0d4da;
} }
.bi-checkbox.disabled.active .checkbox-content:after { .bi-checkbox.disabled.active .checkbox-content:after {
opacity: 1; opacity: 1;
@ -3585,6 +3587,16 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before,
.bi-theme-dark .bi-checkbox .checkbox-content { .bi-theme-dark .bi-checkbox .checkbox-content {
border-color: #9EA6B2; 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 { .bi-file {
opacity: 0; opacity: 0;
filter: alpha(opacity=0); filter: alpha(opacity=0);

532
dist/fineui.ie.js vendored

@ -37435,8 +37435,8 @@ BI.TreeView = BI.inherit(BI.Pane, {
async: { async: {
enable: true, enable: true,
url: getUrl, url: getUrl,
autoParam: ["id", "name"], autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras) // 静态参数
}, },
check: { check: {
enable: true enable: true
@ -37444,16 +37444,16 @@ BI.TreeView = BI.inherit(BI.Pane, {
data: { data: {
key: { key: {
title: "title", title: "title",
name: "text" name: "text" // 节点的name属性替换成text
}, },
simpleData: { simpleData: {
enable: true enable: true // 可以穿id,pid属性的对象数组
} }
}, },
view: { view: {
showIcon: false, showIcon: false,
expandSpeed: "", expandSpeed: "",
nameIsHTML: true, nameIsHTML: true, // 节点可以用html标签代替
dblClickExpand: false dblClickExpand: false
}, },
callback: { callback: {
@ -37476,6 +37476,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
if(status.half === true && status.checked === true) { if(status.half === true && status.checked === true) {
checked = false; checked = false;
} }
// 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调
self.nodes.checkNode(treeNode, !checked, true, true); self.nodes.checkNode(treeNode, !checked, true, true);
} }
@ -37498,7 +37499,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
return true; return true;
} }
BI.Msg.toast("Please Wait。", "warning"); BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件
return false; return false;
} }
@ -37536,9 +37537,9 @@ BI.TreeView = BI.inherit(BI.Pane, {
function ajaxGetNodes (treeNode, reloadType) { function ajaxGetNodes (treeNode, reloadType) {
var zTree = self.nodes; var zTree = self.nodes;
if (reloadType == "refresh") { 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) { function beforeCheck (treeId, treeNode) {
@ -37616,15 +37617,18 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
var parent = node.parentValues || self._getParentValues(node); var parent = node.parentValues || self._getParentValues(node);
var path = parent.concat(this._getNodeValue(node)); var path = parent.concat(this._getNodeValue(node));
// 当前节点是全选的,因为上面的判断已经排除了不选和半选
if (BI.isNotEmptyArray(node.children) || checkState.half === false) { if (BI.isNotEmptyArray(node.children) || checkState.half === false) {
this._buildTree(map, path); this._buildTree(map, path);
return; return;
} }
// 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况)
var storeValues = BI.deepClone(this.options.paras.selectedValues); var storeValues = BI.deepClone(this.options.paras.selectedValues);
var treeNode = this._getTree(storeValues, path); var treeNode = this._getTree(storeValues, path);
this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode);
}, },
// 获取的是以values最后一个节点为根的子树
_getTree: function (map, values) { _getTree: function (map, values) {
var cur = map; var cur = map;
BI.any(values, function (i, value) { BI.any(values, function (i, value) {
@ -37636,6 +37640,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
return cur; return cur;
}, },
// 以values为path一路向里补充map, 并在末尾节点添加key: value节点
_addTreeNode: function (map, values, key, value) { _addTreeNode: function (map, values, key, value) {
var cur = map; var cur = map;
BI.each(values, function (i, value) { BI.each(values, function (i, value) {
@ -37663,7 +37668,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
var self = this; var self = this;
var hashMap = {}; var hashMap = {};
var rootNoots = this.nodes.getNodes(); var rootNoots = this.nodes.getNodes();
track(rootNoots); track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点
function track (nodes) { function track (nodes) {
BI.each(nodes, function (i, node) { BI.each(nodes, function (i, node) {
var checkState = node.getCheckStatus(); var checkState = node.getCheckStatus();
@ -37911,7 +37916,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
var self = this; var self = this;
var setting = { var setting = {
async: { async: {
enable: false, enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras)
}, },
check: { check: {
@ -38001,6 +38006,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
return setting; return setting;
}, },
// 用来更新this.options.paras.selectedValues, 和ztree内部无关
_selectTreeNode: function (treeId, treeNode) { _selectTreeNode: function (treeId, treeNode) {
var self = this, o = this.options; var self = this, o = this.options;
var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode));
@ -38046,7 +38052,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
function callback (nodes, hasNext) { function callback (nodes, hasNext) {
self.nodes.addNodes(treeNode, nodes); self.nodes.addNodes(treeNode, nodes);
// 展开节点是没有分页的
if (hasNext === true) { if (hasNext === true) {
BI.delay(function () { BI.delay(function () {
times++; 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) { _join: function (valueA, valueB) {
var self = this; var self = this;
var map = {}; var map = {};
@ -38157,6 +38166,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments);
} else { } else {
// 如果选中的值中不存在该值不处理 // 如果选中的值中不存在该值不处理
// 因为反正是不选中,没必要管
var t = this.options.paras.selectedValues; var t = this.options.paras.selectedValues;
var p = parentValues.concat(name); var p = parentValues.concat(name);
for (var i = 0, len = p.length; i < len; i++) { for (var i = 0, len = p.length; i < len; i++) {
@ -38164,6 +38174,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
if (t == null) { if (t == null) {
return; return;
} }
// 选中中国-江苏, 搜索南京,取消勾选
if (BI.isEmpty(t)) { if (BI.isEmpty(t)) {
break; break;
} }
@ -38227,9 +38238,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
} }
var hasNext = !!d.hasNext, nodes = d.items || []; var hasNext = !!d.hasNext, nodes = d.items || [];
o.paras.lastSearchValue = d.lastSearchValue; 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.setTipVisible(nodes.length <= 0);
self.loaded(); self.loaded();
if (!hasNext) { if (!hasNext) {
@ -39135,7 +39145,8 @@ BI.Combo = BI.inherit(BI.Widget, {
}, },
showView: function (e) { showView: function (e) {
if (this.isEnabled() && this.combo.isEnabled()) { // 减少popup 调整宽高的次数
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) {
this._popupView(e); this._popupView(e);
} }
}, },
@ -72733,6 +72744,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, {
BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM";
BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** 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 * @class BI.MultiTreePopup
* @extends BI.Pane * @extends BI.Pane
@ -72969,6 +73265,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, {
BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** 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 * searcher
* Created by guy on 15/11/3. * Created by guy on 15/11/3.
* @class BI.MultiTreeSearcher * @class BI.MultiTreeSearcher
@ -82845,10 +83246,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
} }
BI.each(selected, function (k) { BI.each(selected, function (k) {
var node = self._getTreeNode(parentValues, k); var node = self._getTreeNode(parentValues, k);
var newParents = BI.clone(parentValues); // 找不到就是新增值
newParents.push(node.value); if(BI.isNull(node)) {
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); createOneJson({
doCheck(newParents, node, selected[k]); 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 result = [];
var keyword = op.keyword || ""; var keyword = op.keyword || "";
var selectedValues = op.selectedValues; var selectedValues = op.selectedValues;
var lastSearchValue = op.lastSearchValue || ""; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引
var output = search(); var output = search();
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
@ -83145,6 +83555,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
break; 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; return output;
} }
@ -83274,6 +83693,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
halfCheck: state[1] halfCheck: state[1]
}); });
} }
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加
if (parentValues.length === 0 && times === 1) {
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result);
}
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
items: result, 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) { _getNode: function (selectedValues, parentValues) {
var pNode = selectedValues; var pNode = selectedValues;
for (var i = 0, len = parentValues.length; i < len; i++) { 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; 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. * Created by GUY on 2015/10/29.

532
dist/fineui.js vendored

@ -37839,8 +37839,8 @@ BI.TreeView = BI.inherit(BI.Pane, {
async: { async: {
enable: true, enable: true,
url: getUrl, url: getUrl,
autoParam: ["id", "name"], autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras) // 静态参数
}, },
check: { check: {
enable: true enable: true
@ -37848,16 +37848,16 @@ BI.TreeView = BI.inherit(BI.Pane, {
data: { data: {
key: { key: {
title: "title", title: "title",
name: "text" name: "text" // 节点的name属性替换成text
}, },
simpleData: { simpleData: {
enable: true enable: true // 可以穿id,pid属性的对象数组
} }
}, },
view: { view: {
showIcon: false, showIcon: false,
expandSpeed: "", expandSpeed: "",
nameIsHTML: true, nameIsHTML: true, // 节点可以用html标签代替
dblClickExpand: false dblClickExpand: false
}, },
callback: { callback: {
@ -37880,6 +37880,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
if(status.half === true && status.checked === true) { if(status.half === true && status.checked === true) {
checked = false; checked = false;
} }
// 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调
self.nodes.checkNode(treeNode, !checked, true, true); self.nodes.checkNode(treeNode, !checked, true, true);
} }
@ -37902,7 +37903,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
return true; return true;
} }
BI.Msg.toast("Please Wait。", "warning"); BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件
return false; return false;
} }
@ -37940,9 +37941,9 @@ BI.TreeView = BI.inherit(BI.Pane, {
function ajaxGetNodes (treeNode, reloadType) { function ajaxGetNodes (treeNode, reloadType) {
var zTree = self.nodes; var zTree = self.nodes;
if (reloadType == "refresh") { 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) { function beforeCheck (treeId, treeNode) {
@ -38020,15 +38021,18 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
var parent = node.parentValues || self._getParentValues(node); var parent = node.parentValues || self._getParentValues(node);
var path = parent.concat(this._getNodeValue(node)); var path = parent.concat(this._getNodeValue(node));
// 当前节点是全选的,因为上面的判断已经排除了不选和半选
if (BI.isNotEmptyArray(node.children) || checkState.half === false) { if (BI.isNotEmptyArray(node.children) || checkState.half === false) {
this._buildTree(map, path); this._buildTree(map, path);
return; return;
} }
// 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况)
var storeValues = BI.deepClone(this.options.paras.selectedValues); var storeValues = BI.deepClone(this.options.paras.selectedValues);
var treeNode = this._getTree(storeValues, path); var treeNode = this._getTree(storeValues, path);
this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode);
}, },
// 获取的是以values最后一个节点为根的子树
_getTree: function (map, values) { _getTree: function (map, values) {
var cur = map; var cur = map;
BI.any(values, function (i, value) { BI.any(values, function (i, value) {
@ -38040,6 +38044,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
return cur; return cur;
}, },
// 以values为path一路向里补充map, 并在末尾节点添加key: value节点
_addTreeNode: function (map, values, key, value) { _addTreeNode: function (map, values, key, value) {
var cur = map; var cur = map;
BI.each(values, function (i, value) { BI.each(values, function (i, value) {
@ -38067,7 +38072,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
var self = this; var self = this;
var hashMap = {}; var hashMap = {};
var rootNoots = this.nodes.getNodes(); var rootNoots = this.nodes.getNodes();
track(rootNoots); track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点
function track (nodes) { function track (nodes) {
BI.each(nodes, function (i, node) { BI.each(nodes, function (i, node) {
var checkState = node.getCheckStatus(); var checkState = node.getCheckStatus();
@ -38315,7 +38320,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
var self = this; var self = this;
var setting = { var setting = {
async: { async: {
enable: false, enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras)
}, },
check: { check: {
@ -38405,6 +38410,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
return setting; return setting;
}, },
// 用来更新this.options.paras.selectedValues, 和ztree内部无关
_selectTreeNode: function (treeId, treeNode) { _selectTreeNode: function (treeId, treeNode) {
var self = this, o = this.options; var self = this, o = this.options;
var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode));
@ -38450,7 +38456,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
function callback (nodes, hasNext) { function callback (nodes, hasNext) {
self.nodes.addNodes(treeNode, nodes); self.nodes.addNodes(treeNode, nodes);
// 展开节点是没有分页的
if (hasNext === true) { if (hasNext === true) {
BI.delay(function () { BI.delay(function () {
times++; 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) { _join: function (valueA, valueB) {
var self = this; var self = this;
var map = {}; var map = {};
@ -38561,6 +38570,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments);
} else { } else {
// 如果选中的值中不存在该值不处理 // 如果选中的值中不存在该值不处理
// 因为反正是不选中,没必要管
var t = this.options.paras.selectedValues; var t = this.options.paras.selectedValues;
var p = parentValues.concat(name); var p = parentValues.concat(name);
for (var i = 0, len = p.length; i < len; i++) { for (var i = 0, len = p.length; i < len; i++) {
@ -38568,6 +38578,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
if (t == null) { if (t == null) {
return; return;
} }
// 选中中国-江苏, 搜索南京,取消勾选
if (BI.isEmpty(t)) { if (BI.isEmpty(t)) {
break; break;
} }
@ -38631,9 +38642,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
} }
var hasNext = !!d.hasNext, nodes = d.items || []; var hasNext = !!d.hasNext, nodes = d.items || [];
o.paras.lastSearchValue = d.lastSearchValue; 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.setTipVisible(nodes.length <= 0);
self.loaded(); self.loaded();
if (!hasNext) { if (!hasNext) {
@ -39539,7 +39549,8 @@ BI.Combo = BI.inherit(BI.Widget, {
}, },
showView: function (e) { showView: function (e) {
if (this.isEnabled() && this.combo.isEnabled()) { // 减少popup 调整宽高的次数
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) {
this._popupView(e); this._popupView(e);
} }
}, },
@ -73137,6 +73148,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, {
BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM";
BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** 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 * @class BI.MultiTreePopup
* @extends BI.Pane * @extends BI.Pane
@ -73373,6 +73669,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, {
BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** 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 * searcher
* Created by guy on 15/11/3. * Created by guy on 15/11/3.
* @class BI.MultiTreeSearcher * @class BI.MultiTreeSearcher
@ -83249,10 +83650,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
} }
BI.each(selected, function (k) { BI.each(selected, function (k) {
var node = self._getTreeNode(parentValues, k); var node = self._getTreeNode(parentValues, k);
var newParents = BI.clone(parentValues); // 找不到就是新增值
newParents.push(node.value); if(BI.isNull(node)) {
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); createOneJson({
doCheck(newParents, node, selected[k]); 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 result = [];
var keyword = op.keyword || ""; var keyword = op.keyword || "";
var selectedValues = op.selectedValues; var selectedValues = op.selectedValues;
var lastSearchValue = op.lastSearchValue || ""; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引
var output = search(); var output = search();
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
@ -83549,6 +83959,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
break; 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; return output;
} }
@ -83678,6 +84097,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
halfCheck: state[1] halfCheck: state[1]
}); });
} }
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加
if (parentValues.length === 0 && times === 1) {
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result);
}
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
items: result, 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) { _getNode: function (selectedValues, parentValues) {
var pNode = selectedValues; var pNode = selectedValues;
for (var i = 0, len = parentValues.length; i < len; i++) { 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; 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. * Created by GUY on 2015/10/29.

502
dist/fineui_without_jquery_polyfill.js vendored

@ -27057,7 +27057,8 @@ BI.Combo = BI.inherit(BI.Widget, {
}, },
showView: function (e) { showView: function (e) {
if (this.isEnabled() && this.combo.isEnabled()) { // 减少popup 调整宽高的次数
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) {
this._popupView(e); this._popupView(e);
} }
}, },
@ -29779,7 +29780,7 @@ BI.PopupView = BI.inherit(BI.Widget, {
var tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0, var tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0,
tabHeight = this.tab ? (this.tab.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); 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.resetHeight ? this.view.resetHeight(resetHeight) :
this.view.element.css({"max-height": resetHeight + "px"}); this.view.element.css({"max-height": resetHeight + "px"});
}, },
@ -33072,8 +33073,10 @@ BI.Input = BI.inherit(BI.Single, {
}) })
.on("input propertychange", function (e) { .on("input propertychange", function (e) {
// 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了 // 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了
// 这个事件在input的属性发生改变的时候就会触发(class的变化也算) // 其中propertychange在元素属性发生改变的时候就会触发 是为了兼容IE8
if (BI.isNotNull(keyCode)) { // 通过keyCode判断会漏掉输入法点击输入(右键粘贴暂缓)
var originalEvent = e.originalEvent;
if (BI.isNull(originalEvent.propertyName) || originalEvent.propertyName === "value") {
keyCode = null; keyCode = null;
inputEventValid = true; inputEventValid = true;
self._keydown_ = true; self._keydown_ = true;
@ -55945,6 +55948,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, {
BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM";
BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** 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 * @class BI.MultiTreePopup
* @extends BI.Pane * @extends BI.Pane
@ -56181,6 +56469,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, {
BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** 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 * searcher
* Created by guy on 15/11/3. * Created by guy on 15/11/3.
* @class BI.MultiTreeSearcher * @class BI.MultiTreeSearcher
@ -66057,10 +66450,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
} }
BI.each(selected, function (k) { BI.each(selected, function (k) {
var node = self._getTreeNode(parentValues, k); var node = self._getTreeNode(parentValues, k);
var newParents = BI.clone(parentValues); // 找不到就是新增值
newParents.push(node.value); if(BI.isNull(node)) {
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); createOneJson({
doCheck(newParents, node, selected[k]); 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 result = [];
var keyword = op.keyword || ""; var keyword = op.keyword || "";
var selectedValues = op.selectedValues; var selectedValues = op.selectedValues;
var lastSearchValue = op.lastSearchValue || ""; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引
var output = search(); var output = search();
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
@ -66357,6 +66759,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
break; 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; return output;
} }
@ -66486,6 +66897,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
halfCheck: state[1] halfCheck: state[1]
}); });
} }
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加
if (parentValues.length === 0 && times === 1) {
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result);
}
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
items: result, 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) { _getNode: function (selectedValues, parentValues) {
var pNode = selectedValues; var pNode = selectedValues;
for (var i = 0, len = parentValues.length; i < len; i++) { 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; 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. * Created by GUY on 2015/10/29.

491
dist/widget.js vendored

@ -12952,6 +12952,291 @@ BI.MultiTreeCombo = BI.inherit(BI.Single, {
BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM"; BI.MultiTreeCombo.EVENT_CONFIRM = "MultiTreeCombo.EVENT_CONFIRM";
BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** 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 * @class BI.MultiTreePopup
* @extends BI.Pane * @extends BI.Pane
@ -13188,6 +13473,111 @@ BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, {
BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** 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 * searcher
* Created by guy on 15/11/3. * Created by guy on 15/11/3.
* @class BI.MultiTreeSearcher * @class BI.MultiTreeSearcher
@ -23064,10 +23454,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
} }
BI.each(selected, function (k) { BI.each(selected, function (k) {
var node = self._getTreeNode(parentValues, k); var node = self._getTreeNode(parentValues, k);
var newParents = BI.clone(parentValues); // 找不到就是新增值
newParents.push(node.value); if(BI.isNull(node)) {
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); createOneJson({
doCheck(newParents, node, selected[k]); 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 result = [];
var keyword = op.keyword || ""; var keyword = op.keyword || "";
var selectedValues = op.selectedValues; var selectedValues = op.selectedValues;
var lastSearchValue = op.lastSearchValue || ""; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引
var output = search(); var output = search();
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
@ -23364,6 +23763,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
break; 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; return output;
} }
@ -23493,6 +23901,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
halfCheck: state[1] halfCheck: state[1]
}); });
} }
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加
if (parentValues.length === 0 && times === 1) {
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result);
}
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
items: result, 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) { _getNode: function (selectedValues, parentValues) {
var pNode = selectedValues; var pNode = selectedValues;
for (var i = 0, len = parentValues.length; i < len; i++) { 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; 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. * Created by GUY on 2015/10/29.

8
src/base/tree/ztree/asynctree.js

@ -18,7 +18,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
var self = this; var self = this;
var setting = { var setting = {
async: { async: {
enable: false, enable: false, // 很明显这棵树把异步请求关掉了,所有的异步请求都是手动控制的
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras)
}, },
check: { check: {
@ -108,6 +108,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
return setting; return setting;
}, },
// 用来更新this.options.paras.selectedValues, 和ztree内部无关
_selectTreeNode: function (treeId, treeNode) { _selectTreeNode: function (treeId, treeNode) {
var self = this, o = this.options; var self = this, o = this.options;
var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode)); var parentValues = BI.deepClone(treeNode.parentValues || self._getParentValues(treeNode));
@ -153,7 +154,7 @@ BI.AsyncTree = BI.inherit(BI.TreeView, {
function callback (nodes, hasNext) { function callback (nodes, hasNext) {
self.nodes.addNodes(treeNode, nodes); self.nodes.addNodes(treeNode, nodes);
// 展开节点是没有分页的
if (hasNext === true) { if (hasNext === true) {
BI.delay(function () { BI.delay(function () {
times++; 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) { _join: function (valueA, valueB) {
var self = this; var self = this;
var map = {}; var map = {};

7
src/base/tree/ztree/parttree.js

@ -45,6 +45,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments); BI.AsyncTree.superclass._selectTreeNode.apply(self, arguments);
} else { } else {
// 如果选中的值中不存在该值不处理 // 如果选中的值中不存在该值不处理
// 因为反正是不选中,没必要管
var t = this.options.paras.selectedValues; var t = this.options.paras.selectedValues;
var p = parentValues.concat(name); var p = parentValues.concat(name);
for (var i = 0, len = p.length; i < len; i++) { for (var i = 0, len = p.length; i < len; i++) {
@ -52,6 +53,7 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
if (t == null) { if (t == null) {
return; return;
} }
// 选中中国-江苏, 搜索南京,取消勾选
if (BI.isEmpty(t)) { if (BI.isEmpty(t)) {
break; break;
} }
@ -115,9 +117,8 @@ BI.PartTree = BI.inherit(BI.AsyncTree, {
} }
var hasNext = !!d.hasNext, nodes = d.items || []; var hasNext = !!d.hasNext, nodes = d.items || [];
o.paras.lastSearchValue = d.lastSearchValue; 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.setTipVisible(nodes.length <= 0);
self.loaded(); self.loaded();
if (!hasNext) { if (!hasNext) {

23
src/base/tree/ztree/treeview.js

@ -71,8 +71,8 @@ BI.TreeView = BI.inherit(BI.Pane, {
async: { async: {
enable: true, enable: true,
url: getUrl, url: getUrl,
autoParam: ["id", "name"], autoParam: ["id", "name"], // 节点展开异步请求自动提交id和name
otherParam: BI.cjkEncodeDO(paras) otherParam: BI.cjkEncodeDO(paras) // 静态参数
}, },
check: { check: {
enable: true enable: true
@ -80,16 +80,16 @@ BI.TreeView = BI.inherit(BI.Pane, {
data: { data: {
key: { key: {
title: "title", title: "title",
name: "text" name: "text" // 节点的name属性替换成text
}, },
simpleData: { simpleData: {
enable: true enable: true // 可以穿id,pid属性的对象数组
} }
}, },
view: { view: {
showIcon: false, showIcon: false,
expandSpeed: "", expandSpeed: "",
nameIsHTML: true, nameIsHTML: true, // 节点可以用html标签代替
dblClickExpand: false dblClickExpand: false
}, },
callback: { callback: {
@ -112,6 +112,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
if(status.half === true && status.checked === true) { if(status.half === true && status.checked === true) {
checked = false; checked = false;
} }
// 更新此node的check状态, 影响父子关联,并调用beforeCheck和onCheck回调
self.nodes.checkNode(treeNode, !checked, true, true); self.nodes.checkNode(treeNode, !checked, true, true);
} }
@ -134,7 +135,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
return true; return true;
} }
BI.Msg.toast("Please Wait。", "warning"); BI.Msg.toast("Please Wait。", "warning"); // 不展开节点,也不触发onExpand事件
return false; return false;
} }
@ -172,9 +173,9 @@ BI.TreeView = BI.inherit(BI.Pane, {
function ajaxGetNodes (treeNode, reloadType) { function ajaxGetNodes (treeNode, reloadType) {
var zTree = self.nodes; var zTree = self.nodes;
if (reloadType == "refresh") { 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) { function beforeCheck (treeId, treeNode) {
@ -252,15 +253,18 @@ BI.TreeView = BI.inherit(BI.Pane, {
} }
var parent = node.parentValues || self._getParentValues(node); var parent = node.parentValues || self._getParentValues(node);
var path = parent.concat(this._getNodeValue(node)); var path = parent.concat(this._getNodeValue(node));
// 当前节点是全选的,因为上面的判断已经排除了不选和半选
if (BI.isNotEmptyArray(node.children) || checkState.half === false) { if (BI.isNotEmptyArray(node.children) || checkState.half === false) {
this._buildTree(map, path); this._buildTree(map, path);
return; return;
} }
// 剩下的就是半选不展开的节点,因为不知道里面是什么情况,所以借助selectedValues(这个是完整的选中情况)
var storeValues = BI.deepClone(this.options.paras.selectedValues); var storeValues = BI.deepClone(this.options.paras.selectedValues);
var treeNode = this._getTree(storeValues, path); var treeNode = this._getTree(storeValues, path);
this._addTreeNode(map, parent, this._getNodeValue(node), treeNode); this._addTreeNode(map, parent, this._getNodeValue(node), treeNode);
}, },
// 获取的是以values最后一个节点为根的子树
_getTree: function (map, values) { _getTree: function (map, values) {
var cur = map; var cur = map;
BI.any(values, function (i, value) { BI.any(values, function (i, value) {
@ -272,6 +276,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
return cur; return cur;
}, },
// 以values为path一路向里补充map, 并在末尾节点添加key: value节点
_addTreeNode: function (map, values, key, value) { _addTreeNode: function (map, values, key, value) {
var cur = map; var cur = map;
BI.each(values, function (i, value) { BI.each(values, function (i, value) {
@ -299,7 +304,7 @@ BI.TreeView = BI.inherit(BI.Pane, {
var self = this; var self = this;
var hashMap = {}; var hashMap = {};
var rootNoots = this.nodes.getNodes(); var rootNoots = this.nodes.getNodes();
track(rootNoots); track(rootNoots); // 可以看到这个方法没有递归调用,所以在_getHalfSelectedValues中需要关心全选的节点
function track (nodes) { function track (nodes) {
BI.each(nodes, function (i, node) { BI.each(nodes, function (i, node) {
var checkState = node.getCheckStatus(); var checkState = node.getCheckStatus();

48
src/component/treevaluechooser/abstract.treevaluechooser.js

@ -92,10 +92,19 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
} }
BI.each(selected, function (k) { BI.each(selected, function (k) {
var node = self._getTreeNode(parentValues, k); var node = self._getTreeNode(parentValues, k);
var newParents = BI.clone(parentValues); // 找不到就是新增值
newParents.push(node.value); if(BI.isNull(node)) {
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); createOneJson({
doCheck(newParents, node, selected[k]); 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 result = [];
var keyword = op.keyword || ""; var keyword = op.keyword || "";
var selectedValues = op.selectedValues; var selectedValues = op.selectedValues;
var lastSearchValue = op.lastSearchValue || ""; var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引
var output = search(); var output = search();
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
@ -392,6 +401,15 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
break; 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; return output;
} }
@ -521,6 +539,10 @@ BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, {
halfCheck: state[1] halfCheck: state[1]
}); });
} }
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加
if (parentValues.length === 0 && times === 1) {
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result);
}
BI.nextTick(function () { BI.nextTick(function () {
callback({ callback({
items: result, 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) { _getNode: function (selectedValues, parentValues) {
var pNode = selectedValues; var pNode = selectedValues;
for (var i = 0, len = parentValues.length; i < len; i++) { for (var i = 0, len = parentValues.length; i < len; i++) {

54
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);

286
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);

106
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);
Loading…
Cancel
Save