@ -1,2 +1,10 @@ |
|||||||
# fineui-custom-tutorials |
# fineui-custom-tutorials |
||||||
|
|
||||||
|
## bi.custom_tree 教程 |
||||||
|
|
||||||
|
1. [前提知识储备](./docs/一、前提知识储备.md) |
||||||
|
2. [custom_tree的基本结构](./docs/二、custom_tree的基本结构.md) |
||||||
|
3. [实战-普通展开收起的树](./docs/三、实战-普通展开收起的树.md) |
||||||
|
4. [实战-父节点可以选中的树](./docs/四、实战-父节点可以选中的树.md) |
||||||
|
5. [实战-异步分层加载的树](./docs/五、实战-异步分层加载的树.md) |
||||||
|
6. [常见场景的解决方案](./docs/六、常见场景的解决方案.md) |
||||||
|
@ -0,0 +1,52 @@ |
|||||||
|
# 前提知识储备 |
||||||
|
|
||||||
|
利用`bi.custom_tree`自定义树组件,是FineUI的高阶阶段,因此需要深入理解FineUI基础抽象控件的用法. |
||||||
|
在学习的过程中配合源码使用更利于理解 |
||||||
|
|
||||||
|
## BI.BasicButton |
||||||
|
``` |
||||||
|
{ |
||||||
|
isSelected, |
||||||
|
setSelected, |
||||||
|
isOnce, |
||||||
|
doClick, |
||||||
|
getValue, |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## BI.NodeButton |
||||||
|
``` |
||||||
|
{ |
||||||
|
isSelected, |
||||||
|
setSelected, |
||||||
|
isOpened, |
||||||
|
setOpened, |
||||||
|
triggerCollapse, |
||||||
|
triggerExpand, |
||||||
|
doClick, |
||||||
|
getValue, |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## BI.Expander |
||||||
|
``` |
||||||
|
{ |
||||||
|
props:{ |
||||||
|
el:{}, |
||||||
|
popup:{ |
||||||
|
el:{} |
||||||
|
} |
||||||
|
}, |
||||||
|
trigger:"" |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## BI.Loader |
||||||
|
``` |
||||||
|
{ |
||||||
|
populate |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## Events |
||||||
|
`BI.Controller.EVENT_CHANGE` |
@ -0,0 +1,42 @@ |
|||||||
|
# 父节点不可选中的树 |
||||||
|
|
||||||
|
# props结构 |
||||||
|
``` |
||||||
|
{ |
||||||
|
expander: { |
||||||
|
type: "bi.expander", |
||||||
|
isDefaultInit: false, |
||||||
|
el: {}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
}, |
||||||
|
}, |
||||||
|
el: { |
||||||
|
type: "bi.button_tree", |
||||||
|
chooseType: 0, |
||||||
|
layouts: [ |
||||||
|
{ |
||||||
|
type: "bi.vertical", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
items:[] |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
# node实现 |
||||||
|
父节点不可选中,也就是点击父节点就触发展开收起操作,node的实现直接继承BI.NodeButton即可,第一节中提到的NodeButton的关键API大部分都无需override.除了setOpened方法. |
||||||
|
一般在setOpened中处理展开收起按钮的样式改变等 |
||||||
|
``` |
||||||
|
setOpened: function (b) { |
||||||
|
Node.superclass.setOpened.apply(this, arguments); |
||||||
|
// 额外的自定义处理,如加号变成减号,三角箭头由→改为↓ |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
# item实现 |
||||||
|
子节只涉及选中业务,不涉及展开收起业务,所以直接继承BasicButton即可,无需override任何方法 |
||||||
|
|
||||||
|
# 其他公共实现 |
||||||
|
1. 可以手动实现getValue方法,或者在构建items生成value属性 |
||||||
|
2. 选中样式可以采用`bi-list-item`、`bi-list-item-active`、`bi-list-item-active2`、`bi-list-item-none`等样式 |
@ -0,0 +1,127 @@ |
|||||||
|
# custom_tree基本结构 |
||||||
|
|
||||||
|
## custom_tree props |
||||||
|
``` |
||||||
|
{ |
||||||
|
expander: { |
||||||
|
el: {}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree" |
||||||
|
} |
||||||
|
}, |
||||||
|
items: [], |
||||||
|
itemsCreator: BI.emptyFn, |
||||||
|
el: { |
||||||
|
type: "bi.button_tree", |
||||||
|
chooseType: 0, |
||||||
|
layouts: [{ |
||||||
|
type: "bi.vertical" |
||||||
|
}] |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### expander |
||||||
|
expander在custom_tree中的作用是用来控制展开收起行为.参考上一节expander的props定义,custom_tree的props属性中expander字段用来控制expander. |
||||||
|
|
||||||
|
### el |
||||||
|
el对应的是expander中popup属性对应的el字段,用来控制树展开之后的内容是什么 |
||||||
|
|
||||||
|
### items和itemsCreator |
||||||
|
custom_tree实际上就是抽象的把items构建出一份树结构 |
||||||
|
``` |
||||||
|
[ |
||||||
|
{ |
||||||
|
type: "bi.select_tree_expander", |
||||||
|
el: { |
||||||
|
id: "1", |
||||||
|
type: "bi.test_node", |
||||||
|
}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
expander: { |
||||||
|
type: "bi.select_tree_expander", |
||||||
|
isDefaultInit: false, |
||||||
|
el: {}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
}, |
||||||
|
}, |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
id: "1-1", |
||||||
|
type: "bi.test_item", |
||||||
|
}, |
||||||
|
], |
||||||
|
el: { |
||||||
|
type: "bi.loader", |
||||||
|
next: false, |
||||||
|
el: { |
||||||
|
type: "bi.button_tree", |
||||||
|
chooseType: 1, |
||||||
|
layouts: [ |
||||||
|
{ |
||||||
|
type: "bi.vertical", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
isDefaultInit: false, |
||||||
|
id: "1", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
id: "1-1", |
||||||
|
type: "bi.test_item", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: "bi.select_tree_expander", |
||||||
|
el: { |
||||||
|
id: "2", |
||||||
|
type: "bi.test_node", |
||||||
|
}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
expander: { |
||||||
|
type: "bi.select_tree_expander", |
||||||
|
isDefaultInit: false, |
||||||
|
el: {}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
}, |
||||||
|
}, |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
id: "2-1", |
||||||
|
type: "bi.test_item", |
||||||
|
}, |
||||||
|
], |
||||||
|
el: { |
||||||
|
type: "bi.loader", |
||||||
|
next: false, |
||||||
|
el: { |
||||||
|
type: "bi.button_tree", |
||||||
|
chooseType: 1, |
||||||
|
layouts: [ |
||||||
|
{ |
||||||
|
type: "bi.vertical", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
isDefaultInit: false, |
||||||
|
id: "2", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
id: "2-1", |
||||||
|
type: "bi.test_item", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
]; |
||||||
|
``` |
||||||
|
|
||||||
|
看上边格式化出的数据结构.最外层为两个`bi.select_tree_expander`,el是我们指定的父级节点,他的popup是另一层custom_tree嵌套,最终渲染出来的是`bi.loader` |
@ -0,0 +1,37 @@ |
|||||||
|
# 异步分层加载 |
||||||
|
|
||||||
|
## props结构 |
||||||
|
```javascript |
||||||
|
{ |
||||||
|
type: "bi.custom_tree", |
||||||
|
expander: { |
||||||
|
type: "bi.expander", |
||||||
|
isDefaultInit: false, |
||||||
|
el: {}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
}, |
||||||
|
}, |
||||||
|
el: { |
||||||
|
type: "bi.loader", |
||||||
|
next: false, |
||||||
|
el: { |
||||||
|
type: "bi.button_tree", |
||||||
|
chooseType: 0, |
||||||
|
layouts: [ |
||||||
|
{ |
||||||
|
type: "bi.vertical", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
itemsCreator: function(op,callback){ |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
异步加载的props结构,el中变成了`bi.loader`,其中嵌套的el依旧是`bi.button_tree`结构,这就是FineUI嵌套的魅力 |
||||||
|
|
||||||
|
## itemsCreator实现 |
||||||
|
`itemsCreator`回调中第一个参数内容为当前异步,触发展开的节点存储在node属性中,注意初始第一次触发`itemsCreator`的时候因为加载的是树的第一层节点,是没有node信息的. |
||||||
|
`callback`回去的内容为格式化好的下一层节点数据. |
@ -0,0 +1,47 @@ |
|||||||
|
# 常见场景汇总 |
||||||
|
|
||||||
|
## 格式化数据方法 |
||||||
|
1. `BI.Tree.transformToTreeFormat(nodes)` 将id,pId结构的列表形式转化为id,children形式的类树结构 |
||||||
|
2. `BI.Tree.transformToArrayFormat(nodes,pId)` 将id,children形式的类树结构转化为id,pId结构的列表形式 |
||||||
|
3. `BI.Tree.traversal(nodes,callback)` 递归遍历id,children形式的树结构,深度优先 |
||||||
|
|
||||||
|
## layer层级的判断方法 |
||||||
|
通常我们用`layer`属性标明当前节点的层级(第一层为0),对于异步加载的树,我们可以在`itemsCreator`回掉的参数中获取当前父节点的详细信息,子节点的`layer`增加1级即可 |
||||||
|
对于非异步的完整的节点数据,可以采用递归的方式 |
||||||
|
```javascript |
||||||
|
traversalLayers: function (items, layer) { |
||||||
|
var self = this; |
||||||
|
BI.each(items, function (index, item) { |
||||||
|
item.layer = layer; |
||||||
|
if (item.children) { |
||||||
|
self.traversalLayers(item.children, layer + 1) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
``` |
||||||
|
利用`BI.Tree.traversal(nodes,callback)`会更方便(2020-09版本可用) |
||||||
|
```javascript |
||||||
|
traversalLayers: function (items) { |
||||||
|
BI.Tree.traversal(items, function (index, node, pNode) { |
||||||
|
node.layer = pNode ? pNode.layer + 1 : 0 |
||||||
|
}); |
||||||
|
return items |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## 多层级性能优化 |
||||||
|
对于`bi.button_tree`的默认单选逻辑来说,多层级+多节点会出现指数级性能隐患,因此适用于数据量比较小的场景,如果针对部门职务树等超大数据场景,建议采用外部控制选中状态的方式 |
||||||
|
首先`bi.custom_tree`的props中el属性里面嵌套的`bi.button_tree`的`chooseType`要置为-1,即不控制任何选中逻辑. |
||||||
|
而后对`bi.custom_tree`添加事件监听,调用`setValue`由外部赋值 |
||||||
|
```javascript |
||||||
|
listeners: [ |
||||||
|
{ |
||||||
|
eventName: BI.Controller.EVENT_CHANGE, |
||||||
|
action: function (type, value) { |
||||||
|
if (type === BI.Events.CLICK) { |
||||||
|
this.setValue(value); |
||||||
|
} |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
``` |
@ -0,0 +1,54 @@ |
|||||||
|
# 父节可选中的树 |
||||||
|
|
||||||
|
# props结构 |
||||||
|
```javascript |
||||||
|
type: "bi.custom_tree", |
||||||
|
expander: { |
||||||
|
type: "bi.select_tree_expander", |
||||||
|
isDefaultInit: false, |
||||||
|
el: {}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
}, |
||||||
|
}, |
||||||
|
el: { |
||||||
|
type: "bi.button_tree", |
||||||
|
chooseType: 0, |
||||||
|
layouts: [ |
||||||
|
{ |
||||||
|
type: "bi.vertical", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
items: [] |
||||||
|
``` |
||||||
|
bi.expander的el触发的事件不会向上传递,因此要采用bi.select_tree_expander |
||||||
|
bi.select_tree_expander的trigger设置的是"",目的是防止默认的"click"在节点被点击的时候触发展开. |
||||||
|
|
||||||
|
# node实现 |
||||||
|
父节点可选中,只有点击展开收起按钮才可以触发展开收起. |
||||||
|
我们需要override掉`doClick`方法,因为`NodeButton`中默认的`doClick`会调用`setOpened`方法. |
||||||
|
|
||||||
|
之后需要主动监听展开收起按钮的点击事件,依据当前节点的`isOpen()`来调用`triggerCollapse`或`triggerExpand`方法 |
||||||
|
注意展开收起按钮要阻止冒泡,不然点击的时候会触发整个节点的选中 |
||||||
|
```javascript |
||||||
|
setOpened: function (b) { |
||||||
|
Node.superclass.setOpened.apply(this, arguments); |
||||||
|
// 额外的自定义处理,如加号变成减号,三角箭头由→改为↓ |
||||||
|
}, |
||||||
|
|
||||||
|
handleButtonClick: function () { |
||||||
|
this.isOpened() ? this.triggerCollapse() : this.triggerExpand(); |
||||||
|
}, |
||||||
|
|
||||||
|
doClick: function () { |
||||||
|
// 很重要 |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
# item实现 |
||||||
|
子节只涉及选中业务,不涉及展开收起业务,所以直接继承BasicButton即可,无需override任何方法 |
||||||
|
|
||||||
|
# 其他公共实现 |
||||||
|
1. 可以手动实现getValue方法,或者在构建items生成value属性 |
||||||
|
2. 选中样式可以采用`bi-list-item`、`bi-list-item-active`、`bi-list-item-active2`、`bi-list-item-none`等样式 |
@ -0,0 +1,22 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
<title>Document</title> |
||||||
|
<link rel="stylesheet" href="../../node_modules/fineui/dist/fineui.min.css"> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
<div id="wrapper"></div> |
||||||
|
|
||||||
|
<script src="../../node_modules/fineui/dist/fineui.js"></script> |
||||||
|
<script src="../../node_modules/fineui/dist/utils.js"></script> |
||||||
|
|
||||||
|
<script src="./select_tree.item.js"></script> |
||||||
|
<script src="./select_tree.node.js"></script> |
||||||
|
<script src="./select_tree.js"></script> |
||||||
|
</body> |
||||||
|
|
||||||
|
</html> |
@ -0,0 +1,32 @@ |
|||||||
|
|
||||||
|
!(function () { |
||||||
|
var Item = BI.inherit(BI.BasicButton, { |
||||||
|
|
||||||
|
props: { |
||||||
|
baseCls: "bi-list-item-active" |
||||||
|
}, |
||||||
|
|
||||||
|
render: function () { |
||||||
|
var self = this |
||||||
|
return { |
||||||
|
type: "bi.vertical_adapt", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "bi.label", |
||||||
|
textAlign: "left", |
||||||
|
text: this.options.text, |
||||||
|
}, |
||||||
|
lgap: this.options.layer * 24 + 24 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
getValue: function () { |
||||||
|
return this.options.id; |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
BI.shortcut("bi.example.select_custom_tree.item", Item); |
||||||
|
}()) |
@ -0,0 +1,77 @@ |
|||||||
|
var mockData = [ |
||||||
|
{ |
||||||
|
id: "无锡", |
||||||
|
text: "无锡", |
||||||
|
isParent: true, |
||||||
|
layer: 0 |
||||||
|
}, { |
||||||
|
id: "锡山区", |
||||||
|
text: "锡山区", |
||||||
|
pId: "无锡", |
||||||
|
isParent: true, |
||||||
|
layer: 1 |
||||||
|
}, { |
||||||
|
id: "安镇街道", |
||||||
|
text: "安镇街道", |
||||||
|
pId: "锡山区", |
||||||
|
layer: 2 |
||||||
|
}, { |
||||||
|
id: "滨湖区", |
||||||
|
text: "滨湖区", |
||||||
|
pId: "无锡", |
||||||
|
layer: 1 |
||||||
|
}, { |
||||||
|
id: "南京", |
||||||
|
text: "南京", |
||||||
|
isParent: true, |
||||||
|
layer: 0 |
||||||
|
}, { |
||||||
|
id: "建邺区", |
||||||
|
text: "建邺区", |
||||||
|
pId: "南京", |
||||||
|
layer: 1 |
||||||
|
} |
||||||
|
]; |
||||||
|
|
||||||
|
|
||||||
|
var Tree = BI.inherit(BI.Widget, { |
||||||
|
|
||||||
|
render: function () { |
||||||
|
return { |
||||||
|
type: "bi.custom_tree", |
||||||
|
expander: { |
||||||
|
type: "bi.select_tree_expander", |
||||||
|
isDefaultInit: false, |
||||||
|
el: {}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
}, |
||||||
|
}, |
||||||
|
el: { |
||||||
|
type: "bi.button_tree", |
||||||
|
chooseType: 0, |
||||||
|
layouts: [ |
||||||
|
{ |
||||||
|
type: "bi.vertical", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
items: this._formatItems(mockData) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
_formatItems: function (items) { |
||||||
|
return BI.map(items, function (index, item) { |
||||||
|
return BI.extend({ |
||||||
|
type: item.isParent ? "bi.example.select_custom_tree.node" : "bi.example.select_custom_tree.item" |
||||||
|
}, item) |
||||||
|
}) |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
BI.shortcut("bi.example.select_custom_tree", Tree); |
||||||
|
|
||||||
|
BI.createWidget({ |
||||||
|
type: "bi.example.select_custom_tree", |
||||||
|
element: "#wrapper" |
||||||
|
}) |
@ -0,0 +1,57 @@ |
|||||||
|
|
||||||
|
!(function () { |
||||||
|
var Node = BI.inherit(BI.NodeButton, { |
||||||
|
|
||||||
|
props: { |
||||||
|
baseCls: "bi-list-item-active" |
||||||
|
}, |
||||||
|
|
||||||
|
render: function () { |
||||||
|
var self = this |
||||||
|
return { |
||||||
|
type: "bi.vertical_adapt", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "bi.text_button", |
||||||
|
ref: function (_ref) { |
||||||
|
self.icon = _ref |
||||||
|
}, |
||||||
|
stopPropagation: true, |
||||||
|
text: this.options.open ? "-" : "+", |
||||||
|
height: 24, |
||||||
|
width: 24, |
||||||
|
handler: function () { |
||||||
|
self.handleButtonClick() |
||||||
|
} |
||||||
|
}, |
||||||
|
lgap: this.options.layer * 24, |
||||||
|
}, { |
||||||
|
type: "bi.label", |
||||||
|
textAlign: "left", |
||||||
|
text: this.options.text |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
handleButtonClick: function () { |
||||||
|
this.isOpened() ? this.triggerCollapse() : this.triggerExpand(); |
||||||
|
}, |
||||||
|
|
||||||
|
setOpened: function (b) { |
||||||
|
Node.superclass.setOpened.apply(this, arguments); |
||||||
|
this.icon.setText(b ? "-" : "+") |
||||||
|
}, |
||||||
|
|
||||||
|
doClick: function () { |
||||||
|
// 很重要
|
||||||
|
}, |
||||||
|
|
||||||
|
getValue: function () { |
||||||
|
return this.options.id; |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
BI.shortcut("bi.example.select_custom_tree.node", Node); |
||||||
|
}()) |
@ -0,0 +1,23 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
<title>Document</title> |
||||||
|
<link rel="stylesheet" href="../../node_modules/fineui/dist/fineui.min.css"> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
<div id="wrapper"></div> |
||||||
|
|
||||||
|
<script src="../../node_modules/fineui/dist/fineui.js"></script> |
||||||
|
<script src="../../node_modules/fineui/dist/utils.js"></script> |
||||||
|
|
||||||
|
|
||||||
|
<script src="./single_tree.item.js"></script> |
||||||
|
<script src="./single_tree.node.js"></script> |
||||||
|
<script src="./single_tree.js"></script> |
||||||
|
</body> |
||||||
|
|
||||||
|
</html> |
@ -0,0 +1,32 @@ |
|||||||
|
|
||||||
|
!(function () { |
||||||
|
var Item = BI.inherit(BI.BasicButton, { |
||||||
|
|
||||||
|
props: { |
||||||
|
baseCls: "bi-list-item-active" |
||||||
|
}, |
||||||
|
|
||||||
|
render: function () { |
||||||
|
var self = this |
||||||
|
return { |
||||||
|
type: "bi.vertical_adapt", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "bi.label", |
||||||
|
textAlign: "left", |
||||||
|
text: this.options.text, |
||||||
|
}, |
||||||
|
lgap: this.options.layer * 24 + 24 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
getValue: function () { |
||||||
|
return this.options.id; |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
BI.shortcut("bi.example.single_custom_tree.item", Item); |
||||||
|
}()) |
@ -0,0 +1,86 @@ |
|||||||
|
var mockData = [ |
||||||
|
{ |
||||||
|
id: "无锡", |
||||||
|
text: "无锡", |
||||||
|
isParent: true, |
||||||
|
}, { |
||||||
|
id: "锡山区", |
||||||
|
text: "锡山区", |
||||||
|
pId: "无锡", |
||||||
|
isParent: true, |
||||||
|
}, { |
||||||
|
id: "安镇街道", |
||||||
|
text: "安镇街道", |
||||||
|
pId: "锡山区", |
||||||
|
}, { |
||||||
|
id: "滨湖区", |
||||||
|
text: "滨湖区", |
||||||
|
pId: "无锡", |
||||||
|
}, { |
||||||
|
id: "南京", |
||||||
|
text: "南京", |
||||||
|
isParent: true, |
||||||
|
}, { |
||||||
|
id: "建邺区", |
||||||
|
text: "建邺区", |
||||||
|
pId: "南京", |
||||||
|
} |
||||||
|
]; |
||||||
|
|
||||||
|
|
||||||
|
var Tree = BI.inherit(BI.Widget, { |
||||||
|
|
||||||
|
render: function () { |
||||||
|
return { |
||||||
|
type: "bi.custom_tree", |
||||||
|
expander: { |
||||||
|
type: "bi.expander", |
||||||
|
isDefaultInit: false, |
||||||
|
el: {}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
}, |
||||||
|
}, |
||||||
|
el: { |
||||||
|
type: "bi.button_tree", |
||||||
|
chooseType: 0, |
||||||
|
layouts: [ |
||||||
|
{ |
||||||
|
type: "bi.vertical", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
items: this._formatItems(mockData) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
_formatItems: function (items) { |
||||||
|
|
||||||
|
var nodes = BI.map(items, function (index, item) { |
||||||
|
return BI.extend({ |
||||||
|
type: item.isParent ? "bi.example.single_custom_tree.node" : "bi.example.single_custom_tree.item" |
||||||
|
}, item) |
||||||
|
}) |
||||||
|
|
||||||
|
return this.traversalLayers(BI.Tree.transformToTreeFormat(nodes), 0); |
||||||
|
}, |
||||||
|
|
||||||
|
|
||||||
|
traversalLayers: function (items, layer) { |
||||||
|
var self = this; |
||||||
|
BI.each(items, function (index, item) { |
||||||
|
item.layer = layer; |
||||||
|
if (item.children) { |
||||||
|
self.traversalLayers(item.children, layer + 1) |
||||||
|
} |
||||||
|
}) |
||||||
|
return items; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
BI.shortcut("bi.example.single_custom_tree", Tree); |
||||||
|
|
||||||
|
BI.createWidget({ |
||||||
|
type: "bi.example.single_custom_tree", |
||||||
|
element: "#wrapper" |
||||||
|
}) |
@ -0,0 +1,45 @@ |
|||||||
|
|
||||||
|
!(function () { |
||||||
|
var Node = BI.inherit(BI.NodeButton, { |
||||||
|
|
||||||
|
props: { |
||||||
|
baseCls: "bi-list-item" |
||||||
|
}, |
||||||
|
|
||||||
|
render: function () { |
||||||
|
var self = this |
||||||
|
return { |
||||||
|
type: "bi.vertical_adapt", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "bi.label", |
||||||
|
ref: function (_ref) { |
||||||
|
self.icon = _ref |
||||||
|
}, |
||||||
|
text: this.options.open ? "-" : "+", |
||||||
|
height: 24, |
||||||
|
width: 24, |
||||||
|
}, |
||||||
|
lgap: this.options.layer * 24, |
||||||
|
}, { |
||||||
|
type: "bi.label", |
||||||
|
textAlign: "left", |
||||||
|
text: this.options.text |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
setOpened: function (b) { |
||||||
|
Node.superclass.setOpened.apply(this, arguments); |
||||||
|
this.icon.setText(b ? "-" : "+") |
||||||
|
}, |
||||||
|
|
||||||
|
getValue: function () { |
||||||
|
return this.options.id; |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
BI.shortcut("bi.example.single_custom_tree.node", Node); |
||||||
|
}()) |
@ -0,0 +1,23 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
<title>Document</title> |
||||||
|
<link rel="stylesheet" href="../../node_modules/fineui/dist/fineui.min.css"> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
<div id="wrapper"></div> |
||||||
|
|
||||||
|
<script src="../../node_modules/fineui/dist/fineui.js"></script> |
||||||
|
<script src="../../node_modules/fineui/dist/utils.js"></script> |
||||||
|
|
||||||
|
|
||||||
|
<script src="./sync_tree.item.js"></script> |
||||||
|
<script src="./sync_tree.node.js"></script> |
||||||
|
<script src="./sync_tree.js"></script> |
||||||
|
</body> |
||||||
|
|
||||||
|
</html> |
@ -0,0 +1,32 @@ |
|||||||
|
|
||||||
|
!(function () { |
||||||
|
var Item = BI.inherit(BI.BasicButton, { |
||||||
|
|
||||||
|
props: { |
||||||
|
baseCls: "bi-list-item-active" |
||||||
|
}, |
||||||
|
|
||||||
|
render: function () { |
||||||
|
var self = this |
||||||
|
return { |
||||||
|
type: "bi.vertical_adapt", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "bi.label", |
||||||
|
textAlign: "left", |
||||||
|
text: this.options.text, |
||||||
|
}, |
||||||
|
lgap: this.options.layer * 24 + 24 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
getValue: function () { |
||||||
|
return this.options.id; |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
BI.shortcut("bi.example.sync_custom_tree.item", Item); |
||||||
|
}()) |
@ -0,0 +1,106 @@ |
|||||||
|
var mockData = [ |
||||||
|
{ |
||||||
|
id: "无锡", |
||||||
|
text: "无锡", |
||||||
|
isParent: true, |
||||||
|
layer: 0 |
||||||
|
}, { |
||||||
|
id: "锡山区", |
||||||
|
text: "锡山区", |
||||||
|
pId: "无锡", |
||||||
|
isParent: true, |
||||||
|
layer: 1 |
||||||
|
}, { |
||||||
|
id: "安镇街道", |
||||||
|
text: "安镇街道", |
||||||
|
pId: "锡山区", |
||||||
|
layer: 2 |
||||||
|
}, { |
||||||
|
id: "滨湖区", |
||||||
|
text: "滨湖区", |
||||||
|
pId: "无锡", |
||||||
|
layer: 1 |
||||||
|
}, { |
||||||
|
id: "南京", |
||||||
|
text: "南京", |
||||||
|
isParent: true, |
||||||
|
layer: 0 |
||||||
|
}, { |
||||||
|
id: "建邺区", |
||||||
|
text: "建邺区", |
||||||
|
pId: "南京", |
||||||
|
layer: 1 |
||||||
|
} |
||||||
|
]; |
||||||
|
|
||||||
|
|
||||||
|
var Tree = BI.inherit(BI.Widget, { |
||||||
|
|
||||||
|
render: function () { |
||||||
|
return { |
||||||
|
type: "bi.custom_tree", |
||||||
|
expander: { |
||||||
|
type: "bi.expander", |
||||||
|
isDefaultInit: false, |
||||||
|
el: {}, |
||||||
|
popup: { |
||||||
|
type: "bi.custom_tree", |
||||||
|
}, |
||||||
|
}, |
||||||
|
el: { |
||||||
|
type: "bi.loader", |
||||||
|
next: false, |
||||||
|
el: { |
||||||
|
type: "bi.button_tree", |
||||||
|
chooseType: -1, |
||||||
|
layouts: [ |
||||||
|
{ |
||||||
|
type: "bi.vertical", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
itemsCreator: BI.bind(this._itemsCreator, this), |
||||||
|
listeners: [ |
||||||
|
{ |
||||||
|
eventName: BI.Controller.EVENT_CHANGE, |
||||||
|
action: function (type, value) { |
||||||
|
if (type === BI.Events.CLICK) { |
||||||
|
this.setValue(value); |
||||||
|
} |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
_formatItems: function (items) { |
||||||
|
return BI.map(items, function (index, item) { |
||||||
|
return BI.extend({ |
||||||
|
type: item.isParent ? "bi.example.sync_custom_tree.node" : "bi.example.sync_custom_tree.item" |
||||||
|
}, item) |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
_itemsCreator: function (op, callback) { |
||||||
|
var items = []; |
||||||
|
if (!op.node) { // 初次回调的时候是没有节点信息的
|
||||||
|
items = BI.filter(mockData, function (index, item) { |
||||||
|
return BI.isNull(item.pId); |
||||||
|
}) |
||||||
|
} else { |
||||||
|
var id = op.node.id; |
||||||
|
items = BI.filter(mockData, function (index, item) { |
||||||
|
return item.pId === id; |
||||||
|
}) |
||||||
|
} |
||||||
|
callback(this._formatItems(items)) |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
BI.shortcut("bi.example.sync_custom_tree", Tree); |
||||||
|
|
||||||
|
BI.createWidget({ |
||||||
|
type: "bi.example.sync_custom_tree", |
||||||
|
element: "#wrapper" |
||||||
|
}) |
@ -0,0 +1,45 @@ |
|||||||
|
|
||||||
|
!(function () { |
||||||
|
var Node = BI.inherit(BI.NodeButton, { |
||||||
|
|
||||||
|
props: { |
||||||
|
baseCls: "bi-list-item" |
||||||
|
}, |
||||||
|
|
||||||
|
render: function () { |
||||||
|
var self = this |
||||||
|
return { |
||||||
|
type: "bi.vertical_adapt", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "bi.label", |
||||||
|
ref: function (_ref) { |
||||||
|
self.icon = _ref |
||||||
|
}, |
||||||
|
text: this.options.open ? "-" : "+", |
||||||
|
height: 24, |
||||||
|
width: 24, |
||||||
|
}, |
||||||
|
lgap: this.options.layer * 24, |
||||||
|
}, { |
||||||
|
type: "bi.label", |
||||||
|
textAlign: "left", |
||||||
|
text: this.options.text |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
setOpened: function (b) { |
||||||
|
Node.superclass.setOpened.apply(this, arguments); |
||||||
|
this.icon.setText(b ? "-" : "+") |
||||||
|
}, |
||||||
|
|
||||||
|
getValue: function () { |
||||||
|
return this.options.id; |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
BI.shortcut("bi.example.sync_custom_tree.node", Node); |
||||||
|
}()) |
@ -0,0 +1,35 @@ |
|||||||
|
{ |
||||||
|
"env": { |
||||||
|
"browser": true, |
||||||
|
"node": true, |
||||||
|
"es6": true |
||||||
|
}, |
||||||
|
"globals": { |
||||||
|
"window": true, |
||||||
|
"$": true, |
||||||
|
"WebUI": true, |
||||||
|
"BI": true, |
||||||
|
"Data": true, |
||||||
|
"Fix": true, |
||||||
|
"module": true, |
||||||
|
"Demo": true, |
||||||
|
"_global": true |
||||||
|
}, |
||||||
|
"parser": "@typescript-eslint/parser", |
||||||
|
"parserOptions": { |
||||||
|
"project": "./tsconfig.json", |
||||||
|
"ecmaVersion": 6, |
||||||
|
"sourceType": "module", |
||||||
|
"ecmaFeatures": { |
||||||
|
"modules": true |
||||||
|
} |
||||||
|
}, |
||||||
|
"plugins": ["@typescript-eslint/eslint-plugin"], |
||||||
|
"overrides": [{ |
||||||
|
"files": ["src/*.js","src/**/*.js", "demo/*.js", "demo/**/*.js", "i18n/**/*.js", "i18n/*.js", "test/**/*.js", "test/*.js"], |
||||||
|
"extends": "plugin:@fui/es5" |
||||||
|
}, { |
||||||
|
"files": ["webpack/*.js", "types/*.ts", "typescript/*.ts","typescript/**/*.ts", "./*.js", "lib/**/*.js", "lib/*.js"], |
||||||
|
"extends": "plugin:@fui/typescript" |
||||||
|
}] |
||||||
|
} |
@ -0,0 +1,201 @@ |
|||||||
|
Apache License |
||||||
|
Version 2.0, January 2004 |
||||||
|
http://www.apache.org/licenses/ |
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||||
|
|
||||||
|
1. Definitions. |
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction, |
||||||
|
and distribution as defined by Sections 1 through 9 of this document. |
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by |
||||||
|
the copyright owner that is granting the License. |
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all |
||||||
|
other entities that control, are controlled by, or are under common |
||||||
|
control with that entity. For the purposes of this definition, |
||||||
|
"control" means (i) the power, direct or indirect, to cause the |
||||||
|
direction or management of such entity, whether by contract or |
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity. |
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity |
||||||
|
exercising permissions granted by this License. |
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications, |
||||||
|
including but not limited to software source code, documentation |
||||||
|
source, and configuration files. |
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical |
||||||
|
transformation or translation of a Source form, including but |
||||||
|
not limited to compiled object code, generated documentation, |
||||||
|
and conversions to other media types. |
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or |
||||||
|
Object form, made available under the License, as indicated by a |
||||||
|
copyright notice that is included in or attached to the work |
||||||
|
(an example is provided in the Appendix below). |
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object |
||||||
|
form, that is based on (or derived from) the Work and for which the |
||||||
|
editorial revisions, annotations, elaborations, or other modifications |
||||||
|
represent, as a whole, an original work of authorship. For the purposes |
||||||
|
of this License, Derivative Works shall not include works that remain |
||||||
|
separable from, or merely link (or bind by name) to the interfaces of, |
||||||
|
the Work and Derivative Works thereof. |
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including |
||||||
|
the original version of the Work and any modifications or additions |
||||||
|
to that Work or Derivative Works thereof, that is intentionally |
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner |
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of |
||||||
|
the copyright owner. For the purposes of this definition, "submitted" |
||||||
|
means any form of electronic, verbal, or written communication sent |
||||||
|
to the Licensor or its representatives, including but not limited to |
||||||
|
communication on electronic mailing lists, source code control systems, |
||||||
|
and issue tracking systems that are managed by, or on behalf of, the |
||||||
|
Licensor for the purpose of discussing and improving the Work, but |
||||||
|
excluding communication that is conspicuously marked or otherwise |
||||||
|
designated in writing by the copyright owner as "Not a Contribution." |
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||||
|
on behalf of whom a Contribution has been received by Licensor and |
||||||
|
subsequently incorporated within the Work. |
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of |
||||||
|
this License, each Contributor hereby grants to You a perpetual, |
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||||
|
copyright license to reproduce, prepare Derivative Works of, |
||||||
|
publicly display, publicly perform, sublicense, and distribute the |
||||||
|
Work and such Derivative Works in Source or Object form. |
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of |
||||||
|
this License, each Contributor hereby grants to You a perpetual, |
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||||
|
(except as stated in this section) patent license to make, have made, |
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||||
|
where such license applies only to those patent claims licensable |
||||||
|
by such Contributor that are necessarily infringed by their |
||||||
|
Contribution(s) alone or by combination of their Contribution(s) |
||||||
|
with the Work to which such Contribution(s) was submitted. If You |
||||||
|
institute patent litigation against any entity (including a |
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||||
|
or a Contribution incorporated within the Work constitutes direct |
||||||
|
or contributory patent infringement, then any patent licenses |
||||||
|
granted to You under this License for that Work shall terminate |
||||||
|
as of the date such litigation is filed. |
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the |
||||||
|
Work or Derivative Works thereof in any medium, with or without |
||||||
|
modifications, and in Source or Object form, provided that You |
||||||
|
meet the following conditions: |
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or |
||||||
|
Derivative Works a copy of this License; and |
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices |
||||||
|
stating that You changed the files; and |
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works |
||||||
|
that You distribute, all copyright, patent, trademark, and |
||||||
|
attribution notices from the Source form of the Work, |
||||||
|
excluding those notices that do not pertain to any part of |
||||||
|
the Derivative Works; and |
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its |
||||||
|
distribution, then any Derivative Works that You distribute must |
||||||
|
include a readable copy of the attribution notices contained |
||||||
|
within such NOTICE file, excluding those notices that do not |
||||||
|
pertain to any part of the Derivative Works, in at least one |
||||||
|
of the following places: within a NOTICE text file distributed |
||||||
|
as part of the Derivative Works; within the Source form or |
||||||
|
documentation, if provided along with the Derivative Works; or, |
||||||
|
within a display generated by the Derivative Works, if and |
||||||
|
wherever such third-party notices normally appear. The contents |
||||||
|
of the NOTICE file are for informational purposes only and |
||||||
|
do not modify the License. You may add Your own attribution |
||||||
|
notices within Derivative Works that You distribute, alongside |
||||||
|
or as an addendum to the NOTICE text from the Work, provided |
||||||
|
that such additional attribution notices cannot be construed |
||||||
|
as modifying the License. |
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and |
||||||
|
may provide additional or different license terms and conditions |
||||||
|
for use, reproduction, or distribution of Your modifications, or |
||||||
|
for any such Derivative Works as a whole, provided Your use, |
||||||
|
reproduction, and distribution of the Work otherwise complies with |
||||||
|
the conditions stated in this License. |
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||||
|
any Contribution intentionally submitted for inclusion in the Work |
||||||
|
by You to the Licensor shall be under the terms and conditions of |
||||||
|
this License, without any additional terms or conditions. |
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify |
||||||
|
the terms of any separate license agreement you may have executed |
||||||
|
with Licensor regarding such Contributions. |
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade |
||||||
|
names, trademarks, service marks, or product names of the Licensor, |
||||||
|
except as required for reasonable and customary use in describing the |
||||||
|
origin of the Work and reproducing the content of the NOTICE file. |
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or |
||||||
|
agreed to in writing, Licensor provides the Work (and each |
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||||
|
implied, including, without limitation, any warranties or conditions |
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||||
|
appropriateness of using or redistributing the Work and assume any |
||||||
|
risks associated with Your exercise of permissions under this License. |
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory, |
||||||
|
whether in tort (including negligence), contract, or otherwise, |
||||||
|
unless required by applicable law (such as deliberate and grossly |
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be |
||||||
|
liable to You for damages, including any direct, indirect, special, |
||||||
|
incidental, or consequential damages of any character arising as a |
||||||
|
result of this License or out of the use or inability to use the |
||||||
|
Work (including but not limited to damages for loss of goodwill, |
||||||
|
work stoppage, computer failure or malfunction, or any and all |
||||||
|
other commercial damages or losses), even if such Contributor |
||||||
|
has been advised of the possibility of such damages. |
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing |
||||||
|
the Work or Derivative Works thereof, You may choose to offer, |
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity, |
||||||
|
or other liability obligations and/or rights consistent with this |
||||||
|
License. However, in accepting such obligations, You may act only |
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf |
||||||
|
of any other Contributor, and only if You agree to indemnify, |
||||||
|
defend, and hold each Contributor harmless for any liability |
||||||
|
incurred by, or claims asserted against, such Contributor by reason |
||||||
|
of your accepting any such warranty or additional liability. |
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS |
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work. |
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following |
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}" |
||||||
|
replaced with your own identifying information. (Don't include |
||||||
|
the brackets!) The text should be enclosed in the appropriate |
||||||
|
comment syntax for the file format. We also recommend that a |
||||||
|
file or class name and description of purpose be included on the |
||||||
|
same "printed page" as the copyright notice for easier |
||||||
|
identification within third-party archives. |
||||||
|
|
||||||
|
Copyright©2015-present 帆软软件有限公司 |
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
you may not use this file except in compliance with the License. |
||||||
|
You may obtain a copy of the License at |
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software |
||||||
|
distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
See the License for the specific language governing permissions and |
||||||
|
limitations under the License. |
@ -0,0 +1,15 @@ |
|||||||
|
FineUI |
||||||
|
============ |
||||||
|
[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) |
||||||
|
> UI Framework used in FineBI and FineReport |
||||||
|
|
||||||
|
For more details, see the website [http://www.fanruan.com](http://www.fanruan.com). |
||||||
|
|
||||||
|
Documentation |
||||||
|
============= |
||||||
|
|
||||||
|
http://fanruan.design/doc.html?post=0169cf558d |
||||||
|
|
||||||
|
License |
||||||
|
============ |
||||||
|
Please refer to [LICENSE](https://github.com/fanruan/fineui/blob/master/LICENSE) file. |
@ -0,0 +1 @@ |
|||||||
|
module.exports = require('@fui/babel-preset-fineui').configs.ie8; |
@ -0,0 +1 @@ |
|||||||
|
module.exports = require('@fui/babel-preset-fineui').configs.base; |
@ -0,0 +1,171 @@ |
|||||||
|
# 更新日志 |
||||||
|
2.0(2020-08) |
||||||
|
- bi.sign_editor支持显示值居左/居中/居右显示 |
||||||
|
- bi.iframe新增EVENT_LOADED事件 |
||||||
|
- 修复了searcher在允许搜索的情况下输入空格直接退出搜索的问题 |
||||||
|
- 修复了复选下拉系列'点按空格添加完全匹配项'添加的是显示值而非实际值的问题 |
||||||
|
- search_text_value_combo支持水印 |
||||||
|
- BI.makeObject 方法支持传入iteratee |
||||||
|
|
||||||
|
2.0(2020-07) |
||||||
|
- 修复了日期类型控件先展开切换日期月份面板,再设置区间使得该月份不合法,查看该月份面板灰化不对的问题 |
||||||
|
- bi.file文件上传控件accept属性与 [input accept Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept) 统一 |
||||||
|
- 修复了日期类型控件设置一个不在minDate和maxDate之间的日期值时,面板灰化与翻页按钮状态不对的问题 |
||||||
|
- BI.OB的on方法返回一个解除监听的函数 |
||||||
|
- 修复了grid_view执行_unMount时不调用子组件的_unMount的问题 |
||||||
|
- combo新增belowMouse属性,允许popup在点击处弹出 |
||||||
|
- combo新增hideWhenAnotherComboOpen属性,开启则其他combo下拉时当前combo收起 |
||||||
|
- 修复了datePicker在setValue的时候没有动态刷新可用月份的问题 |
||||||
|
- 同步复选下拉及其面板新增getAllValue获取所有已选值 |
||||||
|
- 同步复选下拉树及其面板新增getAllValue获取完整的选中树节点 |
||||||
|
- 修复date_picker最大值最小值与面板展示判断问题 |
||||||
|
- 复选下拉树和下拉列表添加showView和hideVIew方法 |
||||||
|
- number_editor支持自动检测数值与范围是否合法 |
||||||
|
- 修复了颜色选择器设置值为null的时候,trigger和popup表现不一致的问题 |
||||||
|
|
||||||
|
2.0(2020-06) |
||||||
|
- 修复了复选下拉树半选节点的子节点未加载的时候,点选该半选节点是取消选中的问题 |
||||||
|
- 下拉树系列支持isNeedAdjustWidth以动态变化宽度 |
||||||
|
- 修复了新增值的下拉控件传递valueFormatter搜索完全匹配项提示新增 |
||||||
|
- 修复了选色控件历史记录没有选中的问题的问题 |
||||||
|
- 修复了单选下拉框新增值的时候没有发事件的问题 |
||||||
|
- 修复了单选标红combo类setValue为空字符串会标红的问题 |
||||||
|
- BI.history提供与注册路由对应的卸载路由方法unRoute |
||||||
|
- 修复了单选标红combo类setValue为空和空数组行为不一致的问题 |
||||||
|
- 单选列表支持新增选项 |
||||||
|
- 增加组件shortcut未定义的错误提示 |
||||||
|
|
||||||
|
2.0(2020-05) |
||||||
|
- 修复调用BI.history.navigate(XXX, {trigger: false})时, XXX包含中文空格等字符仍然触发回调的问题 |
||||||
|
- 新增BI.after和BI.before方法 |
||||||
|
- 修复bi.button设置宽度并配置iconCls后,文本很长的情况下显示截断的问题 |
||||||
|
- 填加bi-user-select-enable和bi-user-select-disable通用类名 |
||||||
|
- 修复树系列多层半选状态下,勾选祖先节点,后代节点不受影响的问题 |
||||||
|
- 修复上传控件多个title问题 |
||||||
|
|
||||||
|
2.0(2020-04) |
||||||
|
- 修复树列表通过空格回到初始面板没有刷新的问题 |
||||||
|
- 下拉树系列添加下拉popup弹出前事件 |
||||||
|
- 修复了复选下拉勾选值和搜索结果中含有父子串关系时提示不正确的问题 |
||||||
|
- searcher提供可配是否支持搜索空格的allSearchBlank |
||||||
|
- 修复了复选下拉全选状态下使用空格添加值trigger显示更新不对的问题 |
||||||
|
- 复选下拉树展开节点提供分页加载和滚动加载两种方式 |
||||||
|
- 修复了复选下拉列表初始化的时候发送执行两次itemsCreator的问题 |
||||||
|
- 修复了virtual_list重新populate无效的问题 |
||||||
|
- 复选下拉框新增值的时候外抛事件 |
||||||
|
- 空格不再编码成  |
||||||
|
- 支持文本区域水印可滚动 |
||||||
|
|
||||||
|
2.0(2020-03) |
||||||
|
- 修复了IE9下使用bi.file上传包含特殊字符的excel出错的问题 |
||||||
|
- 修复了下拉类型控件不允许编辑的时候没有title的问题 |
||||||
|
- 修复了连续多次调用BI.Msg.alert后只有最后弹出的可以关闭的问题 |
||||||
|
- 修复了time_combo设置格式为%M:%S后value设置大于30分钟的值时标红的问题 |
||||||
|
- 复选下拉树系列展开节点性能优化 |
||||||
|
|
||||||
|
2.0(2020-02) |
||||||
|
- 拓展BI.concat,使其可以拼接多个数组 |
||||||
|
- 修复勾选节点不影响父子节点勾选状态的树搜索选中getValue不正常的问题 |
||||||
|
|
||||||
|
2.0(2020-01) |
||||||
|
- 修复单值系滑块滑动松手后发两次EVENT_CHANGE的问题 |
||||||
|
|
||||||
|
2.0(2019-12) |
||||||
|
- 修复多层级单选下拉树主动设置container后搜索面板弹出问题 |
||||||
|
- bi.search_editor支持搜索中间含有空格的字符串 |
||||||
|
- 修复了监听日期下拉框before_popup_view事件,调用setMinDate无效的问题 |
||||||
|
- 修复了数值滑块逆向排列滑块后populate显示效果不对的问题 |
||||||
|
- 不影响父节点勾选状态的复选树支持自定义水印和默认值 |
||||||
|
- 修复text组件重新设置文本后标红丢失问题 |
||||||
|
- 添加无全选按钮的复选下拉框组件 |
||||||
|
|
||||||
|
2.0(2019-11) |
||||||
|
- 日期系列新增setMinDate和setMaxDate接口 |
||||||
|
- 修复了同步复选树设置节点默认open后, 叶子节点无法选中的问题 |
||||||
|
- 修复了连续多音字搜索可能导致结果异常或者标红异常的问题 |
||||||
|
- 新增BI.set(object, path, value)方法 |
||||||
|
- getSearchResult兼容了对null值的处理 |
||||||
|
- 增加了异步单选下拉树请求完数据后加载完节点后会自动调整宽高的逻辑 |
||||||
|
|
||||||
|
2.0(2019-10) |
||||||
|
- 修改了下拉树展开图标模糊的问题 |
||||||
|
- 修复了下拉树搜索高亮字符与正常字符间存在间距的问题 |
||||||
|
- 复选下拉系列的计数器从trigger中拆分, 作为独立的部分 |
||||||
|
- 增加BI.createElement方法 |
||||||
|
- 统一了单选下拉和复选下拉添加自定义值的交互效果 |
||||||
|
|
||||||
|
2.0(2019-09) |
||||||
|
- [视觉]popover弹出框增加圆角 |
||||||
|
- 文本列表通过复制粘贴的形式选中值的时候发送事件 |
||||||
|
- 修复tree_value_chooser选中节点的唯一子节点后搜索该子节点,无法取消选中的问题 |
||||||
|
- button的bubble创建的popup在收起的时候会destroy |
||||||
|
- 修复了dynamic_date_pane在切换静态时间和动态时间的时候不会发事件的问题 |
||||||
|
|
||||||
|
2.0(2019-08) |
||||||
|
- 修复valueChooser系列不支持value属性的问题 |
||||||
|
- 更新了若干icon-font的样式 |
||||||
|
- 修复了单选树同步搜索状态下父节点前可能没有展开符号的问题 |
||||||
|
- 单选树可展示并选中不存在的值 |
||||||
|
- 树类型下拉新增可搜索实际值的配置 |
||||||
|
- 可编辑的combo新增水印配置 |
||||||
|
- 单选下拉树同步状态下内置搜索 |
||||||
|
|
||||||
|
2.0(2019-07) |
||||||
|
- 修改了下拉框控件默认值的配色 |
||||||
|
- input及其派生编辑控件在PAUSE事件之前会触发CHANGE事件 |
||||||
|
|
||||||
|
2.0(2019-06) |
||||||
|
- 单选下拉树支持搜索与异步加载节点 |
||||||
|
- 提供了AES加密方法 |
||||||
|
|
||||||
|
2.0(2019-05) |
||||||
|
- editor类控件新增EVENT_CHANGE_CONFIRM事件 |
||||||
|
- 复选下拉控件和树下拉控件支持trigger是否可编辑 |
||||||
|
- 时分秒控件支持自定义时间显示格式和是否可编辑 |
||||||
|
- 日期/时间/日期区间/时间区间支持自定义日期选择范围和是否可编辑 |
||||||
|
- 日期/时间/日期区间/时间区间支持自定义日期显示格式和是否可编辑 |
||||||
|
- 增加less函数: 字体资源添加函数addFontRes和字体激活函数activeFont |
||||||
|
|
||||||
|
> @fontList: "dec", "report"; |
||||||
|
> .addFontRes("dec"); |
||||||
|
> .addFontRes("report"); |
||||||
|
> .activateFont(@fontList); |
||||||
|
|
||||||
|
以上即可使用自定义的dec,report字体和fineui的资源字体 |
||||||
|
|
||||||
|
2.0(2019-04) |
||||||
|
- 新增`bi.multi_tree_list_combo`控件, 此下拉树勾选节点时不会影响父子节点的勾选状态 |
||||||
|
- 新增`bi.multi_tree_insert_combo`控件, 此下拉树可以插入不存在的新值 |
||||||
|
- 新增`bi.list_tree_value_chooser_insert_combo`部件, 封装`bi.multi_tree_list_combo`数据处理逻辑 |
||||||
|
- 新增`bi.tree_value_chooser_insert_combo`部件, 封装`bi.multi_tree_insert_combo`数据处理逻辑 |
||||||
|
- 增加BI.DOM.ready方法 |
||||||
|
|
||||||
|
2.0(2019-03) |
||||||
|
- 新增`bi.time_combo`时分秒控件和`bi.time_periods`时间选择区间,时间区间无有效值校验 |
||||||
|
- Label控件增加highlight参数, 可指定初始化标蓝 |
||||||
|
|
||||||
|
2.0(2019-01) |
||||||
|
- 加载更多的单选下拉系列新增allowNoSelect参数配置, 使得可以不选任意一个值 |
||||||
|
|
||||||
|
2.0(2018-12) |
||||||
|
- 增加Button的点击动画和Combo下拉时下拉图标动画 |
||||||
|
|
||||||
|
|
||||||
|
2.0(2018-11) |
||||||
|
- 增加`bi.html`和`bi.html_label`类型,text支持html文本,不支持keyword |
||||||
|
|
||||||
|
|
||||||
|
2.0(2018-10) |
||||||
|
- popover增加高度自适应,即open的时候回根据内容高度调整popover的高度 |
||||||
|
|
||||||
|
|
||||||
|
2.0(2018-09) |
||||||
|
- 增加Fix对configuable为false的对象的不内部构造响应式数据的性能优化处理,例如: |
||||||
|
|
||||||
|
> this.model.json = Object.freeze({name: "zhang"}); |
||||||
|
|
||||||
|
只会对this.model.json进行响应式处理,不会对内部的name进行响应式处理 |
||||||
|
|
||||||
|
|
||||||
|
2.0(2018-08) |
||||||
|
- 增加BI.mount方法,支持同构 |
@ -0,0 +1,31 @@ |
|||||||
|
#### fineui.js |
||||||
|
|
||||||
|
整个fineui打包文件,不包括配置文件 |
||||||
|
|
||||||
|
#### fineui.css |
||||||
|
|
||||||
|
整个fineui打包文件,不包括资源文件 |
||||||
|
|
||||||
|
#### config.js |
||||||
|
|
||||||
|
配置文件,这只是一个案例,集成进系统的时候需要进行配置 |
||||||
|
|
||||||
|
#### resource.css |
||||||
|
|
||||||
|
app.css background.css icon.css font.css的合并文件,集成进系统的时候需要进行配置 |
||||||
|
|
||||||
|
#### router.js |
||||||
|
|
||||||
|
#### 路由文件,使用fineui路由的时候才需要引入 |
||||||
|
|
||||||
|
#### bundle.js bundle.css |
||||||
|
|
||||||
|
所有文件的合并文件, 主要给在线demo和文档用的 |
||||||
|
|
||||||
|
#### core_without_normalize.css |
||||||
|
|
||||||
|
不带标准化的core.css文件,只引入通用css样式的时候才需要 |
||||||
|
|
||||||
|
#### chart.js |
||||||
|
|
||||||
|
封装好的一层图表api |
After Width: | Height: | Size: 357 KiB |
After Width: | Height: | Size: 771 B |
After Width: | Height: | Size: 725 B |
After Width: | Height: | Size: 637 B |
After Width: | Height: | Size: 608 B |
After Width: | Height: | Size: 617 B |
After Width: | Height: | Size: 744 B |
After Width: | Height: | Size: 45 B |
After Width: | Height: | Size: 652 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 301 B |
After Width: | Height: | Size: 200 B |
After Width: | Height: | Size: 192 B |
After Width: | Height: | Size: 199 B |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 353 B |
After Width: | Height: | Size: 202 B |
After Width: | Height: | Size: 341 B |
After Width: | Height: | Size: 205 B |
After Width: | Height: | Size: 202 B |
After Width: | Height: | Size: 535 B |
After Width: | Height: | Size: 448 B |
After Width: | Height: | Size: 456 B |
After Width: | Height: | Size: 200 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 250 B |
After Width: | Height: | Size: 238 B |
After Width: | Height: | Size: 179 B |
After Width: | Height: | Size: 214 B |
After Width: | Height: | Size: 231 B |
After Width: | Height: | Size: 217 B |
After Width: | Height: | Size: 102 B |
After Width: | Height: | Size: 144 B |
After Width: | Height: | Size: 162 B |
After Width: | Height: | Size: 148 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 228 B |
After Width: | Height: | Size: 225 B |
After Width: | Height: | Size: 203 B |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 200 B |
After Width: | Height: | Size: 199 B |
After Width: | Height: | Size: 388 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 398 B |
After Width: | Height: | Size: 384 B |