This commit is contained in:
maplemei 2019-11-19 20:13:50 +08:00
parent e02db53b89
commit 1e9d58f0e6
93 changed files with 8300 additions and 8236 deletions

View File

@ -2,7 +2,7 @@
root = true root = true
[*] [*]
indent_style = space indent_style = tab
indent_size = 4 indent_size = 4
end_of_line = lf end_of_line = lf
charset = utf-8 charset = utf-8

View File

@ -1,5 +1,22 @@
## 更新日志 ## 更新日志
### 1.1.0.Beta
*2019-11-19*
- 历时半个月, 也算是一次大的版本更新, 此版本仅为测试版本, 升级需谨慎
#### 新增
- 树形组件
#### 调整
- 移除分组中的optgroup模式
- 调整代码文件夹结构
- 调整preact版本
### 1.0.13 ### 1.0.13
*2019-11-07* *2019-11-07*

View File

@ -3,13 +3,26 @@
#### 介绍 #### 介绍
始于Layui, 下拉选择框的多选解决方案 始于Layui, 下拉选择框的多选解决方案
前身`formSelectes`, 移除了对`jquery`的依赖, 提高渲染速度 前身[前往formSelectes](https://github.com/hnzzmsf/layui-formSelects), 由于渲染速度慢, 代码冗余, 被放弃了
`xm-select`使用了新的开发方式, 利用preact进行渲染, 大幅度提高渲染速度, 并且可以灵活拓展
[xm-select演示站点](https://maplemei.gitee.io/xm-select/) [xm-select演示站点](https://maplemei.gitee.io/xm-select/)
> 历史版本 > 支持功能
[前往formSelectes](https://github.com/hnzzmsf/layui-formSelects) - [x] 国际化 - 中文/英文
- [x] 多选
- [x] 单选
- [x] 重复选
- [x] 分组
- [x] 工具条
- [x] 创建条目
- [x] 显示模式
- [x] 搜索模式 (本地数据过滤, 远程搜索)
- [x] 分页模式
- [x] 下拉树
- [x] 下拉任意 - 可以自己写html
> 联系方式 > 联系方式
@ -94,3 +107,33 @@ QQ群: 660408068
// ... // ...
</script> </script>
``` ```
#### 相关
> 支持IE吗
简单适配IE10以上的版本, 如有其它兼容性问题, 请加群反馈
> 为什么没有css文件
已经内置到js代码中了, 直接引入`xm-select.js`即可使用
> 开源 != 无私
有问题请自己多动手尝试^_^
> 成长之路
```
maplemei, 一个90后, 热爱前端的程序猿
16年接触了 贤心大大 的 layui, 开始走向了前端的不归之路
17年尝试自己写了一个基于layui的省市区联动插件, 同年底开发了layui select多选第一版
18年6月发布了formSelects
19年6月发布了xm-select
其实每个版本的更新都是自己对前端的一个新的认知, 也是一个新的学习之路
目前作者几乎不怎么使用layui, 已经走向了vue, react的新途 , xm-select的维护是对layui的一种情怀 ^_^
```

View File

@ -10,7 +10,7 @@ const isProd = process.env.NODE_ENV === 'prod';
const webpackConfig = { const webpackConfig = {
entry: { entry: {
'xm-select': "./src/index.js", 'xm-select': "./src/main.js",
'static/docs': "./docs/entry.js", 'static/docs': "./docs/entry.js",
}, },
output: { output: {

2
dist/static/2.js vendored

File diff suppressed because one or more lines are too long

2
dist/static/3.js vendored

File diff suppressed because one or more lines are too long

10
dist/static/docs.js vendored

File diff suppressed because one or more lines are too long

2
dist/xm-select.js vendored

File diff suppressed because one or more lines are too long

View File

@ -177,53 +177,55 @@
.content { .content {
padding-top: 50px; padding-top: 50px;
&> { pre{
h3 { tab-size: 4;
margin: 55px 0 20px; }
&>h3 {
margin: 55px 0 20px;
}
&>ul:not(.timeline) {
margin: 10px 0;
padding: 0 0 0 20px;
font-size: 14px;
color: #5e6d82;
line-height: 2em;
}
&>table {
border-collapse: collapse;
width: 100%;
background-color: #fff;
font-size: 14px;
margin-bottom: 45px;
line-height: 1.5em;
strong {
font-weight: normal;
} }
table { td,
border-collapse: collapse; th {
width: 100%; border-bottom: 1px solid #dcdfe6;
background-color: #fff; padding: 15px;
font-size: 14px; max-width: 250px;
margin-bottom: 45px;
line-height: 1.5em;
strong {
font-weight: normal;
}
td,
th {
border-bottom: 1px solid #dcdfe6;
padding: 15px;
max-width: 250px;
}
th {
text-align: left;
white-space: nowrap;
color: #909399;
font-weight: normal;
}
td {
color: #606266;
}
th:first-child,
td:first-child {
padding-left: 10px;
}
} }
ul:not(.timeline) { th {
margin: 10px 0; text-align: left;
padding: 0 0 0 20px; white-space: nowrap;
font-size: 14px; color: #909399;
color: #5e6d82; font-weight: normal;
line-height: 2em; }
td {
color: #606266;
}
th:first-child,
td:first-child {
padding-left: 10px;
} }
} }
} }

View File

@ -4,173 +4,173 @@
} }
html, body { html, body {
margin: 0; margin: 0;
padding: 0; padding: 0;
height: 100%; height: 100%;
font-family: 'Helvetica Neue',Helvetica,'PingFang SC','Hiragino Sans GB','Microsoft YaHei',SimSun,sans-serif; font-family: 'Helvetica Neue',Helvetica,'PingFang SC','Hiragino Sans GB','Microsoft YaHei',SimSun,sans-serif;
font-weight: 400; font-weight: 400;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent;
&.is-component { &.is-component {
overflow: hidden; overflow: hidden;
} }
} }
#app { #app {
height: 100%; height: 100%;
&.is-component { &.is-component {
overflow-y: hidden; overflow-y: hidden;
.main-cnt { .main-cnt {
padding: 0; padding: 0;
margin-top: 0; margin-top: 0;
height: 100%; height: 100%;
min-height: auto; min-height: auto;
} }
.headerWrapper { .headerWrapper {
position: fixed; position: fixed;
width: 100%; width: 100%;
left: 0; left: 0;
top: 0; top: 0;
z-index: 1500; z-index: 1500;
.container { .container {
padding: 0; padding: 0;
} }
} }
} }
} }
a { a {
color: #409EFF; color: #409EFF;
text-decoration: none; text-decoration: none;
} }
code { code {
background-color: #f9fafc; background-color: #f9fafc;
padding: 0 4px; padding: 0 4px;
border: 1px solid #eaeefb; border: 1px solid #eaeefb;
border-radius: 4px; border-radius: 4px;
} }
button, input, select, textarea { button, input, select, textarea {
font-family: inherit; font-family: inherit;
font-size: inherit; font-size: inherit;
line-height: inherit; line-height: inherit;
color: inherit; color: inherit;
} }
.hljs { .hljs {
line-height: 1.8; line-height: 1.8;
font-family: Menlo, Monaco, Consolas, Courier, monospace; font-family: Menlo, Monaco, Consolas, Courier, monospace;
font-size: 12px; font-size: 12px;
padding: 18px 24px; padding: 18px 24px;
background-color: #fafafa; background-color: #fafafa;
border: solid 1px #eaeefb; border: solid 1px #eaeefb;
margin-bottom: 25px; margin-bottom: 25px;
border-radius: 4px; border-radius: 4px;
-webkit-font-smoothing: auto; -webkit-font-smoothing: auto;
} }
.main-cnt { .main-cnt {
margin-top: -80px; margin-top: -80px;
padding: 80px 0 340px; padding: 80px 0 340px;
box-sizing: border-box; box-sizing: border-box;
min-height: 100%; min-height: 100%;
} }
.container, .container,
.page-container { .page-container {
width: 1140px; width: 1140px;
padding: 0; padding: 0;
margin: 0 auto; margin: 0 auto;
} }
.page-container { .page-container {
padding-top: 55px; padding-top: 55px;
h2 { h2 {
font-size: 28px; font-size: 28px;
color: #1f2d3d; color: #1f2d3d;
margin: 0; margin: 0;
} }
h3 { h3 {
font-size: 22px; font-size: 22px;
} }
h2, h3, h4, h5 { h2, h3, h4, h5 {
font-weight: normal; font-weight: normal;
color: #1f2f3d; color: #1f2f3d;
&:hover a { &:hover a {
opacity: .4; opacity: .4;
} }
a { a {
float: left; float: left;
margin-left: -20px; margin-left: -20px;
opacity: 0; opacity: 0;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
opacity: .4; opacity: .4;
} }
} }
} }
p { p {
font-size: 14px; font-size: 14px;
color: #5e6d82; color: #5e6d82;
line-height: 1.5em; line-height: 1.5em;
} }
.tip { .tip {
padding: 8px 16px; padding: 8px 16px;
background-color: #ECF8FF; background-color: #ECF8FF;
border-radius: 4px; border-radius: 4px;
border-left: #50bfff 5px solid; border-left: #50bfff 5px solid;
margin: 20px 0; margin: 20px 0;
code { code {
background-color: rgba(255, 255, 255, .7); background-color: rgba(255, 255, 255, .7);
color: #445368; color: #445368;
} }
} }
.warning { .warning {
padding: 8px 16px; padding: 8px 16px;
background-color: #fff6f7; background-color: #fff6f7;
border-radius: 4px; border-radius: 4px;
border-left: #FE6C6F 5px solid; border-left: #FE6C6F 5px solid;
margin: 20px 0; margin: 20px 0;
code { code {
background-color: rgba(255, 255, 255, .7); background-color: rgba(255, 255, 255, .7);
color: #445368; color: #445368;
} }
} }
} }
.demo { .demo {
margin: 20px 0; margin: 20px 0;
} }
@media (max-width: 1140px) { @media (max-width: 1140px) {
.container, .container,
.page-container { .page-container {
width: 100%; width: 100%;
} }
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.container, .container,
.page-container { .page-container {
padding: 0 20px; padding: 0 20px;
} }
#app.is-component .headerWrapper .container { #app.is-component .headerWrapper .container {
padding: 0 12px; padding: 0 12px;
} }
} }
.xm-select-demo{ .xm-select-demo{
@ -240,6 +240,15 @@ button, input, select, textarea {
padding: 0 10px; padding: 0 10px;
} }
table{ table{
margin-bottom: 10px !important; margin-bottom: -1px !important;
} }
} }
.demo-ZP03{
.layui-laydate-footer{
padding: 0;
}
xm-select .scroll-body{
text-align: center;
}
}

View File

@ -24,7 +24,7 @@ const router = new VueRouter({
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
if (to.path) { if (to.path) {
_hmt.push(['_trackPageview', to.fullPath]); _hmt.push(['_trackPageview', '/#' + to.fullPath]);
} }
next(); next();
}); });

View File

@ -13,12 +13,12 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```

View File

@ -10,18 +10,18 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
language: 'en', language: 'en',
data: [] data: []
}) })
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '[xid=demo2]', el: '[xid=demo2]',
language: 'en', language: 'en',
data: [ data: [
{name: 'apple', value: 1}, {name: 'apple', value: 1},
{name: 'banana', value: 2}, {name: 'banana', value: 2},
{name: 'orange', value: 3}, {name: 'orange', value: 3},
] ]
}) })
</script> </script>
``` ```

View File

@ -10,13 +10,13 @@
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
data: [ data: [
{name: '水果', value: 1, selected: true, disabled: true}, {name: '水果', value: 1, selected: true, disabled: true},
{name: '蔬菜', value: 2, selected: true}, {name: '蔬菜', value: 2, selected: true},
{name: '桌子', value: 3, disabled: true}, {name: '桌子', value: 3, disabled: true},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```
@ -32,14 +32,14 @@ var demo2 = xmSelect.render({
<script> <script>
var demo5 = xmSelect.render({ var demo5 = xmSelect.render({
el: '#demo1', el: '#demo1',
initValue: [4], initValue: [4],
data: [ data: [
{name: '水果', value: 1, selected: true, disabled: true}, {name: '水果', value: 1, selected: true, disabled: true},
{name: '蔬菜', value: 2, selected: true}, {name: '蔬菜', value: 2, selected: true},
{name: '桌子', value: 3, disabled: true}, {name: '桌子', value: 3, disabled: true},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```

View File

@ -10,14 +10,14 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
tips: '你喜欢什么水果呢?', tips: '你喜欢什么水果呢?',
data: [ data: [
{name: '水果', value: 1}, {name: '水果', value: 1},
{name: '蔬菜', value: 2}, {name: '蔬菜', value: 2},
{name: '桌子', value: 3}, {name: '桌子', value: 3},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```
@ -32,9 +32,9 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
empty: '呀, 没有数据呢', empty: '呀, 没有数据呢',
data: [ ] data: [ ]
}) })
</script> </script>
``` ```
@ -49,15 +49,15 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
filterable: true, filterable: true,
searchTips: '你想吃什么水果吧', searchTips: '你想吃什么水果吧',
data: [ data: [
{name: '水果', value: 1}, {name: '水果', value: 1},
{name: '蔬菜', value: 2}, {name: '蔬菜', value: 2},
{name: '桌子', value: 3}, {name: '桌子', value: 3},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```

View File

@ -10,14 +10,14 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
filterable: true, filterable: true,
data: [ data: [
{name: '水果', value: 1}, {name: '水果', value: 1},
{name: '蔬菜', value: 2}, {name: '蔬菜', value: 2},
{name: '桌子', value: 3}, {name: '桌子', value: 3},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```
@ -32,23 +32,23 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
filterable: true, filterable: true,
filterMethod: function(val, item, index, prop){ filterMethod: function(val, item, index, prop){
if(val == item.value){//把value相同的搜索出来 if(val == item.value){//把value相同的搜索出来
return true; return true;
} }
if(item.name.indexOf(val) != -1){//名称中包含的搜索出来 if(item.name.indexOf(val) != -1){//名称中包含的搜索出来
return true; return true;
} }
return false;//不知道的就不管了 return false;//不知道的就不管了
}, },
data: [ data: [
{name: '水果', value: 1}, {name: '水果', value: 1},
{name: '蔬菜', value: 2}, {name: '蔬菜', value: 2},
{name: '桌子', value: 3}, {name: '桌子', value: 3},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```
@ -65,15 +65,15 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
filterable: true, filterable: true,
delay: 2000, delay: 2000,
data: [ data: [
{name: '水果', value: 1}, {name: '水果', value: 1},
{name: '蔬菜', value: 2}, {name: '蔬菜', value: 2},
{name: '桌子', value: 3}, {name: '桌子', value: 3},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```
@ -96,22 +96,22 @@ var demo3 = xmSelect.render({
<script> <script>
var demo4 = xmSelect.render({ var demo4 = xmSelect.render({
el: '#demo4', el: '#demo4',
filterable: true, filterable: true,
remoteSearch: true, remoteSearch: true,
remoteMethod: function(val, cb, show){ remoteMethod: function(val, cb, show){
//这里模拟3s后返回数据 //这里模拟3s后返回数据
setTimeout(function(){ setTimeout(function(){
//需要回传一个数组 //需要回传一个数组
cb([ cb([
{name: '水果' + val, value: val + 1}, {name: '水果' + val, value: val + 1},
{name: '蔬菜' + val, value: val + 2, selected: true}, {name: '蔬菜' + val, value: val + 2, selected: true},
{name: '桌子' + val, value: val + 3}, {name: '桌子' + val, value: val + 3},
{name: '北京' + val, value: val + 4}, {name: '北京' + val, value: val + 4},
]) ])
}, 3000) }, 3000)
}, },
data: [] data: []
}) })
</script> </script>
``` ```
@ -134,24 +134,24 @@ var demo4 = xmSelect.render({
<script> <script>
var demo5 = xmSelect.render({ var demo5 = xmSelect.render({
el: '#demo5', el: '#demo5',
filterable: true, filterable: true,
remoteSearch: true, remoteSearch: true,
remoteMethod: function(val, cb, show){ remoteMethod: function(val, cb, show){
axios({ axios({
method: 'get', method: 'get',
url: 'https://www.fastmock.site/mock/98228b1f16b7e5112d6c0c87921eabc1/xmSelect/search', url: 'https://www.fastmock.site/mock/98228b1f16b7e5112d6c0c87921eabc1/xmSelect/search',
params: { params: {
keyword: val, keyword: val,
} }
}).then(response => { }).then(response => {
var res = response.data; var res = response.data;
cb(res.data) cb(res.data)
}).catch(err => { }).catch(err => {
cb([]); cb([]);
}); });
}, },
data: [] data: []
}) })
</script> </script>
``` ```
@ -166,17 +166,17 @@ var demo5 = xmSelect.render({
<script> <script>
var demo6 = xmSelect.render({ var demo6 = xmSelect.render({
el: '#demo6', el: '#demo6',
filterable: true, filterable: true,
filterDone: function(val, list){ filterDone: function(val, list){
alert(`搜索完毕, 搜索关键词: ${val}, 过滤数据: ${list.length}个`) alert(`搜索完毕, 搜索关键词: ${val}, 过滤数据: ${list.length}个`)
}, },
data: [ data: [
{name: '水果', value: 1}, {name: '水果', value: 1},
{name: '蔬菜', value: 2}, {name: '蔬菜', value: 2},
{name: '桌子', value: 3}, {name: '桌子', value: 3},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```

View File

@ -11,14 +11,14 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
direction: 'auto', direction: 'auto',
data: [ data: [
{name: '水果', value: 1}, {name: '水果', value: 1},
{name: '蔬菜', value: 2}, {name: '蔬菜', value: 2},
{name: '桌子', value: 3}, {name: '桌子', value: 3},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```
@ -33,14 +33,14 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
direction: 'up', direction: 'up',
data: [ data: [
{name: '水果', value: 1}, {name: '水果', value: 1},
{name: '蔬菜', value: 2}, {name: '蔬菜', value: 2},
{name: '桌子', value: 3}, {name: '桌子', value: 3},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```
@ -55,14 +55,14 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
direction: 'down', direction: 'down',
data: [ data: [
{name: '水果', value: 1}, {name: '水果', value: 1},
{name: '蔬菜', value: 2}, {name: '蔬菜', value: 2},
{name: '桌子', value: 3}, {name: '桌子', value: 3},
{name: '北京', value: 4}, {name: '北京', value: 4},
] ]
}) })
</script> </script>
``` ```

View File

@ -10,17 +10,17 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
style: { style: {
marginLeft: '200px', marginLeft: '200px',
borderRadius: '50px', borderRadius: '50px',
height: '50px', height: '50px',
}, },
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -36,13 +36,13 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
height: '50px', height: '50px',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```

View File

@ -4,8 +4,8 @@
``` ```
xmSelect.render({ xmSelect.render({
//... //...
paging: true, paging: true,
}) })
``` ```
@ -15,21 +15,21 @@ xmSelect.render({
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
paging: true, paging: true,
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
{name: '赵六', value: 4}, {name: '赵六', value: 4},
{name: '苹果', value: 5}, {name: '苹果', value: 5},
{name: '香蕉', value: 6}, {name: '香蕉', value: 6},
{name: '凤梨', value: 7}, {name: '凤梨', value: 7},
{name: '葡萄', value: 8}, {name: '葡萄', value: 8},
{name: '樱桃', value: 9}, {name: '樱桃', value: 9},
{name: '车厘子', value: 10}, {name: '车厘子', value: 10},
{name: '火龙果', value: 11}, {name: '火龙果', value: 11},
] ]
}) })
</script> </script>
``` ```
@ -42,9 +42,9 @@ var demo1 = xmSelect.render({
``` ```
xmSelect.render({ xmSelect.render({
//... //...
paging: true, paging: true,
pageSize: 3, pageSize: 3,
}) })
``` ```
@ -54,22 +54,22 @@ xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
paging: true, paging: true,
pageSize: 3, pageSize: 3,
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
{name: '赵六', value: 4}, {name: '赵六', value: 4},
{name: '苹果', value: 5}, {name: '苹果', value: 5},
{name: '香蕉', value: 6}, {name: '香蕉', value: 6},
{name: '凤梨', value: 7}, {name: '凤梨', value: 7},
{name: '葡萄', value: 8}, {name: '葡萄', value: 8},
{name: '樱桃', value: 9}, {name: '樱桃', value: 9},
{name: '车厘子', value: 10}, {name: '车厘子', value: 10},
{name: '火龙果', value: 11}, {name: '火龙果', value: 11},
] ]
}) })
</script> </script>
``` ```
@ -80,10 +80,10 @@ var demo2 = xmSelect.render({
``` ```
xmSelect.render({ xmSelect.render({
//... //...
paging: true, paging: true,
pageSize: 5, pageSize: 5,
filterable: true, filterable: true,
}) })
``` ```
@ -97,36 +97,36 @@ xmSelect.render({
<script> <script>
var data = []; var data = [];
for(var i = 0 ; i < 100 ; i++ ){ for(var i = 0 ; i < 100 ; i++ ){
data.push({ data.push({
name: '测试数据' + i, name: '测试数据' + i,
value: i, value: i,
}) })
} }
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
paging: true, paging: true,
pageSize: 5, pageSize: 5,
filterable: true, filterable: true,
data data
}) })
document.getElementById('demo3-5').onclick = function(){ document.getElementById('demo3-5').onclick = function(){
demo3.update({ demo3.update({
pageSize: 5 pageSize: 5
}) })
} }
document.getElementById('demo3-10').onclick = function(){ document.getElementById('demo3-10').onclick = function(){
demo3.update({ demo3.update({
pageSize: 10 pageSize: 10
}) })
} }
document.getElementById('demo3-20').onclick = function(){ document.getElementById('demo3-20').onclick = function(){
demo3.update({ demo3.update({
pageSize: 20 pageSize: 20
}) })
} }
</script> </script>
@ -138,11 +138,11 @@ document.getElementById('demo3-20').onclick = function(){
``` ```
xmSelect.render({ xmSelect.render({
//... //...
paging: true, paging: true,
pageSize: 3, pageSize: 3,
filterable: true, filterable: true,
pageEmptyShow: false, pageEmptyShow: false,
}) })
``` ```
@ -152,24 +152,24 @@ xmSelect.render({
<script> <script>
var demo4 = xmSelect.render({ var demo4 = xmSelect.render({
el: '#demo4', el: '#demo4',
paging: true, paging: true,
pageSize: 3, pageSize: 3,
filterable: true, filterable: true,
pageEmptyShow: false, pageEmptyShow: false,
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
{name: '赵六', value: 4}, {name: '赵六', value: 4},
{name: '苹果', value: 5}, {name: '苹果', value: 5},
{name: '香蕉', value: 6}, {name: '香蕉', value: 6},
{name: '凤梨', value: 7}, {name: '凤梨', value: 7},
{name: '葡萄', value: 8}, {name: '葡萄', value: 8},
{name: '樱桃', value: 9}, {name: '樱桃', value: 9},
{name: '车厘子', value: 10}, {name: '车厘子', value: 10},
{name: '火龙果', value: 11}, {name: '火龙果', value: 11},
] ]
}) })
</script> </script>
``` ```

View File

@ -9,13 +9,13 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
radio: true, radio: true,
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -30,14 +30,14 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
radio: true, radio: true,
clickClose: true, clickClose: true,
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -52,27 +52,27 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
radio: true, radio: true,
clickClose: true, clickClose: true,
model: { model: {
label: { label: {
type: 'text', type: 'text',
text: { text: {
//左边拼接的字符 //左边拼接的字符
left: '', left: '',
//右边拼接的字符 //右边拼接的字符
right: '', right: '',
//中间的分隔符 //中间的分隔符
separator: ', ', separator: ', ',
}, },
} }
}, },
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```

View File

@ -9,13 +9,13 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
repeat: true, repeat: true,
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -30,14 +30,14 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
repeat: true, repeat: true,
clickClose: true, clickClose: true,
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -52,31 +52,31 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
repeat: true, repeat: true,
model: { model: {
label: { label: {
type: 'count', type: 'count',
count: { count: {
template: function(data, sels){ template: function(data, sels){
var res = {}; var res = {};
sels.forEach(item => { sels.forEach(item => {
var name = item.name; var name = item.name;
!res[name] && (res[name] = 0); !res[name] && (res[name] = 0);
res[name] += 1; res[name] += 1;
}); });
return Object.keys(res).map(key => { return Object.keys(res).map(key => {
return `${key} (${res[key]})` return `${key} (${res[key]})`
}).join(','); }).join(',');
} }
}, },
} }
}, },
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```

View File

@ -13,22 +13,22 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
prop: { prop: {
name: 'label', name: 'label',
value: 'id', value: 'id',
}, },
data: [ data: [
{label: '张三', id: 1, group: 1}, {label: '张三', id: 1, group: 1},
{label: '李四', id: 2, group: 1}, {label: '李四', id: 2, group: 1},
{label: '王五', id: 3, group: 2}, {label: '王五', id: 3, group: 2},
] ]
}) })
document.getElementById('demo1-getValue').onclick = function(){ document.getElementById('demo1-getValue').onclick = function(){
//获取当前多选选中的值 //获取当前多选选中的值
var selectArr = demo1.getValue(); var selectArr = demo1.getValue();
document.getElementById('demo1-value').innerHTML = JSON.stringify(selectArr, null, 2); document.getElementById('demo1-value').innerHTML = JSON.stringify(selectArr, null, 2);
} }
</script> </script>
``` ```

View File

@ -8,12 +8,12 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -28,15 +28,15 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
theme: { theme: {
color: '#e54d42', color: '#e54d42',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -51,15 +51,15 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
theme: { theme: {
color: '#f37b1d', color: '#f37b1d',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -74,15 +74,15 @@ var demo3 = xmSelect.render({
<script> <script>
var demo4 = xmSelect.render({ var demo4 = xmSelect.render({
el: '#demo4', el: '#demo4',
theme: { theme: {
color: '#fbbd08', color: '#fbbd08',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -97,15 +97,15 @@ var demo4 = xmSelect.render({
<script> <script>
var demo5 = xmSelect.render({ var demo5 = xmSelect.render({
el: '#demo5', el: '#demo5',
theme: { theme: {
color: '#8dc63f', color: '#8dc63f',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -120,15 +120,15 @@ var demo5 = xmSelect.render({
<script> <script>
var demo6 = xmSelect.render({ var demo6 = xmSelect.render({
el: '#demo6', el: '#demo6',
theme: { theme: {
color: '#1cbbb4', color: '#1cbbb4',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -143,15 +143,15 @@ var demo6 = xmSelect.render({
<script> <script>
var demo7 = xmSelect.render({ var demo7 = xmSelect.render({
el: '#demo7', el: '#demo7',
theme: { theme: {
color: '#0081ff', color: '#0081ff',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -166,15 +166,15 @@ var demo7 = xmSelect.render({
<script> <script>
var demo8 = xmSelect.render({ var demo8 = xmSelect.render({
el: '#demo8', el: '#demo8',
theme: { theme: {
color: '#6739b6', color: '#6739b6',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -189,15 +189,15 @@ var demo8 = xmSelect.render({
<script> <script>
var demo9 = xmSelect.render({ var demo9 = xmSelect.render({
el: '#demo9', el: '#demo9',
theme: { theme: {
color: '#9c26b0', color: '#9c26b0',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -212,15 +212,15 @@ var demo9 = xmSelect.render({
<script> <script>
var demo10 = xmSelect.render({ var demo10 = xmSelect.render({
el: '#demo10', el: '#demo10',
theme: { theme: {
color: '#e03997', color: '#e03997',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -235,15 +235,15 @@ var demo10 = xmSelect.render({
<script> <script>
var demo11 = xmSelect.render({ var demo11 = xmSelect.render({
el: '#demo11', el: '#demo11',
theme: { theme: {
color: '#a5673f', color: '#a5673f',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -258,15 +258,15 @@ var demo11 = xmSelect.render({
<script> <script>
var demo12 = xmSelect.render({ var demo12 = xmSelect.render({
el: '#demo12', el: '#demo12',
theme: { theme: {
color: '#8799a3', color: '#8799a3',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -281,15 +281,15 @@ var demo12 = xmSelect.render({
<script> <script>
var demo13 = xmSelect.render({ var demo13 = xmSelect.render({
el: '#demo13', el: '#demo13',
theme: { theme: {
color: '#aaaaaa', color: '#aaaaaa',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -304,15 +304,15 @@ var demo13 = xmSelect.render({
<script> <script>
var demo14 = xmSelect.render({ var demo14 = xmSelect.render({
el: '#demo14', el: '#demo14',
theme: { theme: {
color: '#333333', color: '#333333',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```

View File

@ -11,27 +11,27 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
document.getElementById('demo1-open').onclick = function(){ document.getElementById('demo1-open').onclick = function(){
//这里延迟1S, 是因为, 点击下拉框外边的位置 会出发关闭事件, 所以延迟演示效果 //这里延迟1S, 是因为, 点击下拉框外边的位置 会出发关闭事件, 所以延迟演示效果
setTimeout(function(){ setTimeout(function(){
demo1.opened(); demo1.opened();
}, 1000); }, 1000);
} }
document.getElementById('demo1-close').onclick = function(){ document.getElementById('demo1-close').onclick = function(){
//先点一下关闭, 然后把下拉框点开, 3S后会自动关闭 //先点一下关闭, 然后把下拉框点开, 3S后会自动关闭
setTimeout(function(){ setTimeout(function(){
demo1.closed(); demo1.closed();
}, 3000); }, 3000);
} }
</script> </script>
``` ```
@ -45,18 +45,18 @@ document.getElementById('demo1-close').onclick = function(){
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
], ],
show(){ show(){
alert('打开了') alert('打开了')
}, },
hide(){ hide(){
alert('关闭了') alert('关闭了')
} }
}) })
</script> </script>
``` ```

View File

@ -9,12 +9,12 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -29,23 +29,23 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
model: { model: {
label: { label: {
type: 'block', type: 'block',
block: { block: {
//最大显示数量, 0:不限制 //最大显示数量, 0:不限制
showCount: 0, showCount: 0,
//是否显示删除图标 //是否显示删除图标
showIcon: false, showIcon: false,
} }
} }
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -60,23 +60,23 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
model: { model: {
label: { label: {
type: 'block', type: 'block',
block: { block: {
//最大显示数量, 0:不限制 //最大显示数量, 0:不限制
showCount: 1, showCount: 1,
//是否显示删除图标 //是否显示删除图标
showIcon: true, showIcon: true,
} }
} }
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -91,26 +91,26 @@ var demo3 = xmSelect.render({
<script> <script>
var demo4 = xmSelect.render({ var demo4 = xmSelect.render({
el: '#demo4', el: '#demo4',
model: { model: {
label: { label: {
type: 'text', type: 'text',
//使用字符串拼接的方式 //使用字符串拼接的方式
text: { text: {
//左边拼接的字符 //左边拼接的字符
left: '【', left: '【',
//右边拼接的字符 //右边拼接的字符
right: '】', right: '】',
//中间的分隔符 //中间的分隔符
separator: '', separator: '',
}, },
} }
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
], ],
}) })
</script> </script>
``` ```
@ -125,22 +125,22 @@ var demo4 = xmSelect.render({
<script> <script>
var demo5 = xmSelect.render({ var demo5 = xmSelect.render({
el: '#demo5', el: '#demo5',
model: { model: {
label: { label: {
type: 'xxxx', //自定义与下面的对应 type: 'xxxx', //自定义与下面的对应
xxxx: { xxxx: {
template(data, sels){ template(data, sels){
return "已选中 " + sels.length + " 项, 共 " + data.length + " 项" return "已选中 " + sels.length + " 项, 共 " + data.length + " 项"
} }
}, },
} }
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
], ],
}) })
</script> </script>
``` ```
@ -155,23 +155,23 @@ var demo5 = xmSelect.render({
<script> <script>
var demo6 = xmSelect.render({ var demo6 = xmSelect.render({
el: '#demo6', el: '#demo6',
model: { model: {
label: { label: {
type: 'xxxx', //自定义与下面的对应 type: 'xxxx', //自定义与下面的对应
xxxx: { xxxx: {
template(data, sels){ template(data, sels){
//也可以是html //也可以是html
return `<div style="color: red;">${sels.length} / ${data.length}</div>` return `<div style="color: red;">${sels.length} / ${data.length}</div>`
} }
}, },
} }
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
], ],
}) })
</script> </script>
``` ```

View File

@ -9,12 +9,12 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [ data: [
{name: '张三', value: 'zhangsan', selected: true}, {name: '张三', value: 'zhangsan', selected: true},
{name: '李四', value: 'lisi', selected: true}, {name: '李四', value: 'lisi', selected: true},
{name: '王五', value: 'wangwu'}, {name: '王五', value: 'wangwu'},
] ]
}) })
</script> </script>
``` ```
@ -29,15 +29,15 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
template({ item, sels, name, value }){ template({ item, sels, name, value }){
return name + '<span style="position: absolute; right: 10px; color: #8799a3">'+value+'</span>' return name + '<span style="position: absolute; right: 10px; color: #8799a3">'+value+'</span>'
}, },
data: [ data: [
{name: '张三', value: 'zhangsan', selected: true}, {name: '张三', value: 'zhangsan', selected: true},
{name: '李四', value: 'lisi', selected: true}, {name: '李四', value: 'lisi', selected: true},
{name: '王五', value: 'wangwu'}, {name: '王五', value: 'wangwu'},
] ]
}) })
</script> </script>
``` ```

View File

@ -15,23 +15,23 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
on({ arr, change, isAdd }){ on({ arr, change, isAdd }){
alert(`已有: ${arr.length} 变化: ${change.length}, 状态: ${isAdd}`) alert(`已有: ${arr.length} 变化: ${change.length}, 状态: ${isAdd}`)
}, },
data: [ data: [
{name: '张三', value: 'zhangsan', selected: true}, {name: '张三', value: 'zhangsan', selected: true},
{name: '李四', value: 'lisi', selected: true}, {name: '李四', value: 'lisi', selected: true},
{name: '王五', value: 'wangwu'}, {name: '王五', value: 'wangwu'},
] ]
}) })
document.getElementById('setValue1').onclick = function(){ document.getElementById('setValue1').onclick = function(){
demo1.setValue(['zhangsan'], null, true); demo1.setValue(['zhangsan'], null, true);
} }
document.getElementById('setValue2').onclick = function(){ document.getElementById('setValue2').onclick = function(){
demo1.setValue(['zhangsan']); demo1.setValue(['zhangsan']);
} }
</script> </script>
``` ```
@ -48,28 +48,33 @@ document.getElementById('setValue2').onclick = function(){
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
toolbar: { toolbar: {
show: true show: true
}, },
on({ arr, change, isAdd }){ on: function(data){
//arr: 当前多选已选中的数据 //arr: 当前多选已选中的数据
//change, 此次选择变化的数据,数组 var arr = data.arr;
//isAdd, 此次操作是新增还是删除 //change, 此次选择变化的数据,数组
console.log(arr); var change = data.change;
if(isAdd){ //isAdd, 此次操作是新增还是删除
var item = change[0]; var isAdd = data.isAdd;
var index = arr.findIndex(i => i.mutex == item.mutex && i.value != item.value);
if(index != -1){ console.log(arr);
arr.splice(index, 1);
} if(isAdd){
} var item = change[0];
}, var index = arr.findIndex(i => i.mutex == item.mutex && i.value != item.value);
data: [ if(index != -1){
{name: '北京', value: 1, mutex: 1, selected: true}, arr.splice(index, 1);
{name: '上海', value: 2, mutex: 1}, }
{name: '广州', value: 3}, }
] },
data: [
{name: '北京', value: 1, mutex: 1, selected: true},
{name: '上海', value: 2, mutex: 1},
{name: '广州', value: 3},
]
}) })
</script> </script>
``` ```

View File

@ -14,40 +14,40 @@
<script> <script>
function run(count, paging){ function run(count, paging){
//生成数据 //生成数据
var data = []; var data = [];
for(var i = 0; i < count; i++){ for(var i = 0; i < count; i++){
data.push({ data.push({
name: '测试数据' + i, name: '测试数据' + i,
value: i, value: i,
}) })
} }
//记录开始渲染时间 //记录开始渲染时间
var startTime = Date.now(); var startTime = Date.now();
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
paging, paging,
data data
}) })
//记录结束时间 //记录结束时间
var endTime = Date.now(); var endTime = Date.now();
document.getElementById('demo1-result').innerText = `渲染耗时: ${endTime - startTime} ms` document.getElementById('demo1-result').innerText = `渲染耗时: ${endTime - startTime} ms`
} }
document.getElementById('demo1-test1').onclick = function(){ document.getElementById('demo1-test1').onclick = function(){
run(1000, false) run(1000, false)
}; };
document.getElementById('demo1-test2').onclick = function(){ document.getElementById('demo1-test2').onclick = function(){
run(10000, false) run(10000, false)
}; };
document.getElementById('demo1-test3').onclick = function(){ document.getElementById('demo1-test3').onclick = function(){
run(10000, true) run(10000, true)
}; };
run(1000, false); run(1000, false);

View File

@ -9,13 +9,13 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
max: 2, max: 2,
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -30,16 +30,16 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
max: 2, max: 2,
maxMethod(seles, item){ maxMethod(seles, item){
alert(`${item.name}不能选了, 已经超了`) alert(`${item.name}不能选了, 已经超了`)
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```
@ -54,16 +54,16 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
max: 2, max: 2,
theme: { theme: {
maxColor: 'orange', maxColor: 'orange',
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```

View File

@ -9,26 +9,26 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
toolbar: { toolbar: {
show: true, show: true,
}, },
filterable: true, filterable: true,
paging: true, paging: true,
pageSize: 3, pageSize: 3,
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
{name: '赵六', value: 4}, {name: '赵六', value: 4},
{name: '苹果', value: 5}, {name: '苹果', value: 5},
{name: '香蕉', value: 6}, {name: '香蕉', value: 6},
{name: '凤梨', value: 7}, {name: '凤梨', value: 7},
{name: '葡萄', value: 8}, {name: '葡萄', value: 8},
{name: '樱桃', value: 9}, {name: '樱桃', value: 9},
{name: '车厘子', value: 10}, {name: '车厘子', value: 10},
{name: '火龙果', value: 11}, {name: '火龙果', value: 11},
] ]
}) })
</script> </script>
``` ```
@ -43,27 +43,27 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
toolbar: { toolbar: {
show: true, show: true,
showIcon: false, showIcon: false,
}, },
filterable: true, filterable: true,
paging: true, paging: true,
pageSize: 3, pageSize: 3,
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
{name: '赵六', value: 4}, {name: '赵六', value: 4},
{name: '苹果', value: 5}, {name: '苹果', value: 5},
{name: '香蕉', value: 6}, {name: '香蕉', value: 6},
{name: '凤梨', value: 7}, {name: '凤梨', value: 7},
{name: '葡萄', value: 8}, {name: '葡萄', value: 8},
{name: '樱桃', value: 9}, {name: '樱桃', value: 9},
{name: '车厘子', value: 10}, {name: '车厘子', value: 10},
{name: '火龙果', value: 11}, {name: '火龙果', value: 11},
] ]
}) })
</script> </script>
``` ```
@ -78,33 +78,33 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
toolbar: { toolbar: {
show: true, show: true,
list: ['ALL', { list: ['ALL', {
name: '自定义', name: '自定义',
icon: 'el-icon-star-off', icon: 'el-icon-star-off',
method(data){ method(data){
alert('我是自定义的'); alert('我是自定义的');
} }
}] }]
}, },
filterable: true, filterable: true,
paging: true, paging: true,
pageSize: 3, pageSize: 3,
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
{name: '赵六', value: 4}, {name: '赵六', value: 4},
{name: '苹果', value: 5}, {name: '苹果', value: 5},
{name: '香蕉', value: 6}, {name: '香蕉', value: 6},
{name: '凤梨', value: 7}, {name: '凤梨', value: 7},
{name: '葡萄', value: 8}, {name: '葡萄', value: 8},
{name: '樱桃', value: 9}, {name: '樱桃', value: 9},
{name: '车厘子', value: 10}, {name: '车厘子', value: 10},
{name: '火龙果', value: 11}, {name: '火龙果', value: 11},
] ]
}) })
</script> </script>
``` ```
@ -116,10 +116,10 @@ var demo3 = xmSelect.render({
``` ```
//全选, 清空, 反选 //全选, 清空, 反选
xmSelect.render({ xmSelect.render({
toolbar: { toolbar: {
show: true, show: true,
list: [ 'ALL', 'CLEAR', 'REVERSE' ] list: [ 'ALL', 'CLEAR', 'REVERSE' ]
}, },
}) })
``` ```
@ -129,27 +129,27 @@ xmSelect.render({
<script> <script>
var demo4 = xmSelect.render({ var demo4 = xmSelect.render({
el: '#demo4', el: '#demo4',
toolbar: { toolbar: {
show: true, show: true,
list: [ 'ALL', 'CLEAR', 'REVERSE' ] list: [ 'ALL', 'CLEAR', 'REVERSE' ]
}, },
filterable: true, filterable: true,
paging: true, paging: true,
pageSize: 3, pageSize: 3,
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
{name: '赵六', value: 4}, {name: '赵六', value: 4},
{name: '苹果', value: 5}, {name: '苹果', value: 5},
{name: '香蕉', value: 6}, {name: '香蕉', value: 6},
{name: '凤梨', value: 7}, {name: '凤梨', value: 7},
{name: '葡萄', value: 8}, {name: '葡萄', value: 8},
{name: '樱桃', value: 9}, {name: '樱桃', value: 9},
{name: '车厘子', value: 10}, {name: '车厘子', value: 10},
{name: '火龙果', value: 11}, {name: '火龙果', value: 11},
] ]
}) })
</script> </script>
``` ```

View File

@ -17,22 +17,22 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
filterable: true, filterable: true,
showCount: 5, showCount: 5,
data: [ data: [
{name: '张三1', value: 1, selected: true}, {name: '张三1', value: 1, selected: true},
{name: '李四1', value: 2, selected: true}, {name: '李四1', value: 2, selected: true},
{name: '王五1', value: 3}, {name: '王五1', value: 3},
{name: '赵六1', value: 4}, {name: '赵六1', value: 4},
{name: '苹果2', value: 5}, {name: '苹果2', value: 5},
{name: '香蕉2', value: 6}, {name: '香蕉2', value: 6},
{name: '凤梨2', value: 7}, {name: '凤梨2', value: 7},
{name: '葡萄2', value: 8}, {name: '葡萄2', value: 8},
{name: '樱桃3', value: 9}, {name: '樱桃3', value: 9},
{name: '车厘子3', value: 10}, {name: '车厘子3', value: 10},
{name: '火龙果3', value: 11}, {name: '火龙果3', value: 11},
] ]
}) })
</script> </script>
``` ```

View File

@ -1,35 +1,6 @@
## 分组 ## 分组
### optgroup模式
:::demo 指定选项中的`optgroup`为`true`
```html
<div id="demo1" class="xm-select-demo"></div>
<script>
var demo1 = xmSelect.render({
el: '#demo1',
toolbar:{
show: true,
},
height: '500px',
data: [
{name: '销售员', optgroup: true},
{name: '张三1', value: 1, selected: true},
{name: '李四1', value: 2, selected: true},
{name: '王五1', value: 3, disabled: true},
{name: '奖品', optgroup: true},
{name: '苹果2', value: 4, selected: true, disabled: true},
{name: '香蕉2', value: 5},
{name: '葡萄2', value: 6},
]
})
</script>
```
:::
### children模式 ### children模式
:::demo 选项中的`children`为数组 :::demo 选项中的`children`为数组
@ -38,57 +9,24 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
toolbar:{ toolbar:{
show: true, show: true,
}, },
filterable: true, filterable: true,
height: '500px', height: '500px',
data: [ data: [
{name: '销售员', children: [ {name: '销售员', children: [
{name: '张三1', value: 1, selected: true}, {name: '张三1', value: 1, selected: true},
{name: '李四1', value: 2, selected: true}, {name: '李四1', value: 2, selected: true},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
]}, ]},
{name: '奖品', children: [ {name: '奖品', children: [
{name: '苹果2', value: 4, selected: true, disabled: true}, {name: '苹果2', value: 4, selected: true, disabled: true},
{name: '香蕉2', value: 5}, {name: '香蕉2', value: 5},
{name: '葡萄2', value: 6}, {name: '葡萄2', value: 6},
]}, ]},
] ]
})
</script>
```
:::
### 混合模式
如果自己感觉舒服的话, 也可以这么用...
:::demo
```html
<div id="demo3" class="xm-select-demo"></div>
<script>
var demo3 = xmSelect.render({
el: '#demo3',
filterable: true,
toolbar: {
show: true
},
height: '500px',
data: [
{name: '城市', optgroup: true},
{name: '北京13', value: 1},
{name: '天津1', value: 2, selected: true, disabled: true},
{name: '上海1', value: 3},
{name: '销售员', children: [
{name: '李四23', value: 4, selected: true},
{name: '王五2', value: 5},
]},
],
}) })
</script> </script>
``` ```
@ -103,27 +41,29 @@ var demo3 = xmSelect.render({
<script> <script>
var demo4 = xmSelect.render({ var demo4 = xmSelect.render({
el: '#demo4', el: '#demo4',
toolbar:{ toolbar:{
show: true, show: true,
}, },
height: '500px', height: '500px',
data: [ data: [
{name: '选中', optgroup: true, click: 'SELECT'}, {name: '选中', optgroup: true, click: 'SELECT', children: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2, disabled: true}, {name: '李四', value: 2, disabled: true},
{name: '清空', optgroup: true, click: 'CLEAR'}, ]},
{name: '王五', value: 3, disabled: true}, {name: '清空', optgroup: true, click: 'CLEAR', children: [
{name: '苹果', value: 4, selected: true}, {name: '王五', value: 3, disabled: true},
{name: '自动', optgroup: true, click: 'AUTO'}, {name: '苹果', value: 4, selected: true},
{name: '香蕉', value: 5}, ]},
{name: '葡萄', value: 6}, {name: '自动', optgroup: true, click: 'AUTO', children: [
{name: '自定义', optgroup: true, click: function(item){ {name: '香蕉', value: 5},
alert('自定义的, 想干嘛干嘛'); {name: '葡萄', value: 6},
}}, ]},
{name: '小米', value: 7}, {name: '自定义', optgroup: true, click: function(item){ alert('自定义的, 想干嘛干嘛') }, children: [
{name: '华为', value: 8}, {name: '小米', value: 7},
] {name: '华为', value: 8},
]},
]
}) })
</script> </script>
``` ```
@ -138,26 +78,26 @@ var demo4 = xmSelect.render({
<script> <script>
var demo5 = xmSelect.render({ var demo5 = xmSelect.render({
el: '#demo5', el: '#demo5',
toolbar:{ toolbar:{
show: true, show: true,
}, },
filterable: true, filterable: true,
height: '500px', height: '500px',
paging: true, paging: true,
pageSize: 2, pageSize: 2,
data: [ data: [
{name: '销售员', children: [ {name: '销售员', children: [
{name: '张三1', value: 1}, {name: '张三1', value: 1},
{name: '李四1', value: 2}, {name: '李四1', value: 2},
{name: '王五13', value: 3}, {name: '王五13', value: 3},
]}, ]},
{name: '奖品', children: [ {name: '奖品', children: [
{name: '苹果23', value: 4}, {name: '苹果23', value: 4},
{name: '香蕉2', value: 5}, {name: '香蕉2', value: 5},
{name: '葡萄2', value: 6}, {name: '葡萄2', value: 6},
]}, ]},
] ]
}) })
</script> </script>
``` ```

View File

@ -15,20 +15,20 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
toolbar:{ toolbar:{
show: true, show: true,
}, },
autoRow: true, autoRow: true,
height: '500px', height: '500px',
data: [ data: [
{name: '张三1', value: 1, selected: true}, {name: '张三1', value: 1, selected: true},
{name: '李四1', value: 2, selected: true}, {name: '李四1', value: 2, selected: true},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
{name: '苹果2', value: 4, selected: true, disabled: true}, {name: '苹果2', value: 4, selected: true, disabled: true},
{name: '香蕉2', value: 5, selected: true}, {name: '香蕉2', value: 5, selected: true},
{name: '葡萄2', value: 6}, {name: '葡萄2', value: 6},
] ]
}) })
</script> </script>
``` ```
@ -40,67 +40,67 @@ var demo1 = xmSelect.render({
前面的label居中 需要 **自行** 加一段css, 这里就没有内置到插件中了, 避免样式污染, 当前或许你有更好的css解决方案 ^_^ 前面的label居中 需要 **自行** 加一段css, 这里就没有内置到插件中了, 避免样式污染, 当前或许你有更好的css解决方案 ^_^
```css ```css
.layui-form-pane .layui-form-label{ .layui-form-pane .layui-form-label{
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
``` ```
:::demo :::demo
```html ```html
<form class="layui-form layui-form-pane xm-select-demo ly-label-center" action=""> <form class="layui-form layui-form-pane xm-select-demo ly-label-center" action="">
<div class="layui-form-item" pane> <div class="layui-form-item" pane>
<label class="layui-form-label">居中风格</label> <label class="layui-form-label">居中风格</label>
<div class="layui-input-block"> <div class="layui-input-block">
<div id="demo2"></div> <div id="demo2"></div>
</div> </div>
</div> </div>
</form> </form>
<form class="layui-form layui-form-pane xm-select-demo" action=""> <form class="layui-form layui-form-pane xm-select-demo" action="">
<div class="layui-form-item" pane> <div class="layui-form-item" pane>
<label class="layui-form-label">默认风格</label> <label class="layui-form-label">默认风格</label>
<div class="layui-input-block"> <div class="layui-input-block">
<div id="demo3"></div> <div id="demo3"></div>
</div> </div>
</div> </div>
</form> </form>
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
toolbar:{ toolbar:{
show: true, show: true,
}, },
filterable: true, filterable: true,
height: '500px', height: '500px',
autoRow: true, autoRow: true,
data: [ data: [
{name: '张三1', value: 1, selected: true}, {name: '张三1', value: 1, selected: true},
{name: '李四1', value: 2, selected: true}, {name: '李四1', value: 2, selected: true},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
{name: '苹果2', value: 4, selected: true, disabled: true}, {name: '苹果2', value: 4, selected: true, disabled: true},
{name: '香蕉2', value: 5, selected: true}, {name: '香蕉2', value: 5, selected: true},
{name: '葡萄2', value: 6}, {name: '葡萄2', value: 6},
] ]
}) })
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
toolbar:{ toolbar:{
show: true, show: true,
}, },
filterable: true, filterable: true,
height: '500px', height: '500px',
autoRow: true, autoRow: true,
data: [ data: [
{name: '张三1', value: 1, selected: true}, {name: '张三1', value: 1, selected: true},
{name: '李四1', value: 2, selected: true}, {name: '李四1', value: 2, selected: true},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
{name: '苹果2', value: 4, selected: true, disabled: true}, {name: '苹果2', value: 4, selected: true, disabled: true},
{name: '香蕉2', value: 5, selected: true}, {name: '香蕉2', value: 5, selected: true},
{name: '葡萄2', value: 6}, {name: '葡萄2', value: 6},
] ]
}) })
</script> </script>
``` ```

View File

@ -10,42 +10,42 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
radio: true, radio: true,
clickClose: true, clickClose: true,
model: { model: {
icon: 'hidden', icon: 'hidden',
label: { label: {
type: 'text' type: 'text'
} }
}, },
data: [ data: [
{name: '张三1', value: 1, selected: true}, {name: '张三1', value: 1, selected: true},
{name: '李四1', value: 2}, {name: '李四1', value: 2},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
{name: '苹果2', value: 4}, {name: '苹果2', value: 4},
] ]
}) })
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
radio: true, radio: true,
clickClose: true, clickClose: true,
theme: { theme: {
color: '#5FB878', color: '#5FB878',
}, },
model: { model: {
icon: 'hidden', icon: 'hidden',
label: { label: {
type: 'text' type: 'text'
} }
}, },
data: [ data: [
{name: '张三1', value: 1, selected: true}, {name: '张三1', value: 1, selected: true},
{name: '李四1', value: 2}, {name: '李四1', value: 2},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
{name: '苹果2', value: 4}, {name: '苹果2', value: 4},
] ]
}) })
</script> </script>
``` ```
@ -60,16 +60,16 @@ var demo2 = xmSelect.render({
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
model: { model: {
icon: 'hidden', icon: 'hidden',
}, },
data: [ data: [
{name: '张三1', value: 1, selected: true, disabled: true}, {name: '张三1', value: 1, selected: true, disabled: true},
{name: '李四1', value: 2, selected: true}, {name: '李四1', value: 2, selected: true},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
{name: '苹果2', value: 4}, {name: '苹果2', value: 4},
] ]
}) })
</script> </script>
``` ```

View File

@ -14,47 +14,47 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
size: 'large', size: 'large',
data: [ data: [
{name: 'large', value: 1, selected: true}, {name: 'large', value: 1, selected: true},
{name: '李四1', value: 2}, {name: '李四1', value: 2},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
{name: '苹果2', value: 4}, {name: '苹果2', value: 4},
] ]
}) })
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
size: 'medium', size: 'medium',
data: [ data: [
{name: 'medium', value: 1, selected: true}, {name: 'medium', value: 1, selected: true},
{name: '李四1', value: 2}, {name: '李四1', value: 2},
{name: '默认尺寸', value: 3, selected: true, disabled: true}, {name: '默认尺寸', value: 3, selected: true, disabled: true},
{name: '苹果2', value: 4}, {name: '苹果2', value: 4},
] ]
}) })
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
size: 'small', size: 'small',
data: [ data: [
{name: 'small', value: 1, selected: true}, {name: 'small', value: 1, selected: true},
{name: '李四1', value: 2}, {name: '李四1', value: 2},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
{name: '苹果2', value: 4}, {name: '苹果2', value: 4},
] ]
}) })
var demo4 = xmSelect.render({ var demo4 = xmSelect.render({
el: '#demo4', el: '#demo4',
size: 'mini', size: 'mini',
data: [ data: [
{name: 'mini', value: 1, selected: true}, {name: 'mini', value: 1, selected: true},
{name: '李四1', value: 2}, {name: '李四1', value: 2},
{name: '王五1', value: 3, disabled: true}, {name: '王五1', value: 3, disabled: true},
{name: '苹果2', value: 4}, {name: '苹果2', value: 4},
] ]
}) })
</script> </script>
``` ```

View File

@ -21,16 +21,16 @@ xmSelectObj.warning(COLOR, SUSTAIN);
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3, disabled: true}, {name: '王五', value: 3, disabled: true},
] ]
}) })
document.getElementById('demo1-warning').onclick = function(){ document.getElementById('demo1-warning').onclick = function(){
demo1.warning(); demo1.warning();
} }
</script> </script>
``` ```
@ -46,16 +46,16 @@ document.getElementById('demo1-warning').onclick = function(){
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3, disabled: true}, {name: '王五', value: 3, disabled: true},
] ]
}) })
document.getElementById('demo2-warning').onclick = function(){ document.getElementById('demo2-warning').onclick = function(){
demo2.warning('#6739b6'); demo2.warning('#6739b6');
} }
</script> </script>
``` ```
@ -71,16 +71,16 @@ document.getElementById('demo2-warning').onclick = function(){
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3, disabled: true}, {name: '王五', value: 3, disabled: true},
] ]
}) })
document.getElementById('demo3-warning').onclick = function(){ document.getElementById('demo3-warning').onclick = function(){
demo3.warning('#6739b6', true); demo3.warning('#6739b6', true);
} }
</script> </script>
``` ```

View File

@ -5,8 +5,8 @@
``` ```
xmSelect.render({ xmSelect.render({
//... //...
disabled: true disabled: true
}) })
``` ```
@ -16,13 +16,13 @@ xmSelect.render({
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
disabled: true, disabled: true,
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3, disabled: true}, {name: '王五', value: 3, disabled: true},
] ]
}) })
</script> </script>
``` ```
@ -39,19 +39,19 @@ var demo1 = xmSelect.render({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3, disabled: true}, {name: '王五', value: 3, disabled: true},
] ]
}) })
document.getElementById('demo21').onclick = function(){ document.getElementById('demo21').onclick = function(){
demo2.update({ disabled: true }); demo2.update({ disabled: true });
} }
document.getElementById('demo22').onclick = function(){ document.getElementById('demo22').onclick = function(){
demo2.update({ disabled: false }); demo2.update({ disabled: false });
} }
</script> </script>
``` ```
@ -67,23 +67,23 @@ document.getElementById('demo22').onclick = function(){
<script> <script>
var demo3 = xmSelect.render({ var demo3 = xmSelect.render({
el: '#demo3', el: '#demo3',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
], ],
on({ arr, change, isAdd }){ on({ arr, change, isAdd }){
var hasZS = change.find(item => item.name === '张三'); var hasZS = change.find(item => item.name === '张三');
if(isAdd && hasZS){ if(isAdd && hasZS){
demo3.update({ disabled: true }); demo3.update({ disabled: true });
} }
} }
}) })
//没有做不到, 只有想不到, 把多选玩出花来吧 //没有做不到, 只有想不到, 把多选玩出花来吧
document.getElementById('demo3-disabled').onclick = function(){ document.getElementById('demo3-disabled').onclick = function(){
demo3.update({ disabled: false }); demo3.update({ disabled: false });
} }
</script> </script>
``` ```

View File

@ -6,15 +6,15 @@
``` ```
//想创建就必须要开启本地搜索 //想创建就必须要开启本地搜索
xmSelect.render({ xmSelect.render({
//... //...
filterable: true, filterable: true,
create: function(val){ create: function(val){
//返回一个创建成功的对象, val是搜索的数据 //返回一个创建成功的对象, val是搜索的数据
return { return {
name: '创建-' + val, name: '创建-' + val,
value: val value: val
} }
} }
}) })
``` ```
@ -24,19 +24,19 @@ xmSelect.render({
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
filterable: true, filterable: true,
create: function(val){ create: function(val){
return { return {
name: '创建-' + val, name: '创建-' + val,
value: val value: val
} }
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3, disabled: true}, {name: '王五', value: 3, disabled: true},
] ]
}) })
</script> </script>
``` ```
@ -51,27 +51,27 @@ var demo1 = xmSelect.render({
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo2', el: '#demo2',
radio: true, radio: true,
clickClose: true, clickClose: true,
filterable: true, filterable: true,
create: function(val){ create: function(val){
return { return {
name: '创建-' + val, name: '创建-' + val,
value: val value: val
} }
}, },
model: { model: {
icon: 'hidden', icon: 'hidden',
label: { label: {
type: 'text', type: 'text',
} }
}, },
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
``` ```

View File

@ -19,34 +19,34 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
document.getElementById('demo1-test1').onclick = function(){ document.getElementById('demo1-test1').onclick = function(){
demo1.setValue([ demo1.setValue([
{name: '张三', value: 1}, {name: '张三', value: 1},
]) ])
}; };
document.getElementById('demo1-test2').onclick = function(){ document.getElementById('demo1-test2').onclick = function(){
demo1.setValue([ 1 ]) demo1.setValue([ 1 ])
}; };
document.getElementById('demo1-test3').onclick = function(){ document.getElementById('demo1-test3').onclick = function(){
demo1.append([ 2 ]); demo1.append([ 2 ]);
}; };
document.getElementById('demo1-test4').onclick = function(){ document.getElementById('demo1-test4').onclick = function(){
demo1.delete([ 2 ]) demo1.delete([ 2 ])
}; };
document.getElementById('demo1-test5').onclick = function(){ document.getElementById('demo1-test5').onclick = function(){
demo1.setValue([ ]) demo1.setValue([ ])
}; };
</script> </script>
@ -74,27 +74,27 @@ document.getElementById('demo1-test5').onclick = function(){
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
document.getElementById('demo2-getValue').onclick = function(){ document.getElementById('demo2-getValue').onclick = function(){
//获取当前多选选中的值 //获取当前多选选中的值
var selectArr = demo2.getValue(); var selectArr = demo2.getValue();
document.getElementById('demo2-value').innerHTML = `\ndemo2.getValue()\n\n` + JSON.stringify(selectArr, null, 2); document.getElementById('demo2-value').innerHTML = `\ndemo2.getValue()\n\n` + JSON.stringify(selectArr, null, 2);
} }
var types = ['name', 'nameStr', 'value', 'valueStr']; var types = ['name', 'nameStr', 'value', 'valueStr'];
types.forEach(function(type){ types.forEach(function(type){
document.getElementById(type).onclick = function(){ document.getElementById(type).onclick = function(){
//获取当前多选选中的值 //获取当前多选选中的值
var selectArr = demo2.getValue(type); var selectArr = demo2.getValue(type);
document.getElementById('demo2-value').innerHTML = `\ndemo2.getValue('${type}')\n\n` + JSON.stringify(selectArr, null, 2); document.getElementById('demo2-value').innerHTML = `\ndemo2.getValue('${type}')\n\n` + JSON.stringify(selectArr, null, 2);
} }
}); });

View File

@ -6,18 +6,18 @@
:::demo :::demo
```html ```html
<form> <form>
<div id="demo1" class="xm-select-demo"></div> <div id="demo1" class="xm-select-demo"></div>
<button class="btn" type="submit">提交</button> <button class="btn" type="submit">提交</button>
</form> </form>
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>
@ -30,19 +30,19 @@ var demo1 = xmSelect.render({
:::demo :::demo
```html ```html
<form> <form>
<div id="demo2" class="xm-select-demo"></div> <div id="demo2" class="xm-select-demo"></div>
<button class="btn" type="submit">提交</button> <button class="btn" type="submit">提交</button>
</form> </form>
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
name: 'lalalalalala', name: 'lalalalalala',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
</script> </script>

View File

@ -10,63 +10,63 @@
<script> <script>
layui.use('table', function() { layui.use('table', function() {
var table = layui.table; var table = layui.table;
//第一个实例 //第一个实例
table.render({ table.render({
elem: '#demo', elem: '#demo',
page: true, //开启分页 page: true, //开启分页
height: 500, height: 500,
cols: [ cols: [
[ //表头 [ //表头
{ field: 'id', title: 'ID', width: 80, sort: true }, { field: 'id', title: 'ID', width: 80, sort: true },
{ field: 'username', title: '用户名', width: 80 }, { field: 'username', title: '用户名', width: 80 },
{ field: 'sex', title: '性别', width: 80, sort: true }, { field: 'sex', title: '性别', width: 80, sort: true },
{ field: 'city', title: '城市', width: 80 }, { field: 'city', title: '城市', width: 80 },
{ field: 'sign', title: '爱好', width: 200, templet: function(d){ { field: 'sign', title: '爱好', width: 200, templet: function(d){
return '<div id="XM-' + d.id + '" ></div>' return '<div id="XM-' + d.id + '" ></div>'
} }, } },
{ field: 'experience', title: '积分', width: 80, sort: true }, { field: 'experience', title: '积分', width: 80, sort: true },
{ field: 'score', title: '评分', width: 80, sort: true }, { field: 'score', title: '评分', width: 80, sort: true },
{ field: 'classify', title: '职业', width: 80 }, { field: 'classify', title: '职业', width: 80 },
{ field: 'wealth', title: '财富', width: 135, sort: true } { field: 'wealth', title: '财富', width: 135, sort: true }
] ]
], ],
data: [ data: [
{"id":10000,"username":"user-0","sex":"女","city":"城市-0","sign":"签名-0","experience":255,"logins":24,"wealth":82830700,"classify":"作家","score":57}, {"id":10000,"username":"user-0","sex":"女","city":"城市-0","sign":"签名-0","experience":255,"logins":24,"wealth":82830700,"classify":"作家","score":57},
{"id":10001,"username":"user-1","sex":"男","city":"城市-1","sign":"签名-1","experience":884,"logins":58,"wealth":64928690,"classify":"词人","score":27}, {"id":10001,"username":"user-1","sex":"男","city":"城市-1","sign":"签名-1","experience":884,"logins":58,"wealth":64928690,"classify":"词人","score":27},
{"id":10002,"username":"user-2","sex":"女","city":"城市-2","sign":"签名-2","experience":650,"logins":77,"wealth":6298078,"classify":"酱油","score":31}, {"id":10002,"username":"user-2","sex":"女","city":"城市-2","sign":"签名-2","experience":650,"logins":77,"wealth":6298078,"classify":"酱油","score":31},
{"id":10003,"username":"user-3","sex":"女","city":"城市-3","sign":"签名-3","experience":362,"logins":157,"wealth":37117017,"classify":"诗人","score":68}, {"id":10003,"username":"user-3","sex":"女","city":"城市-3","sign":"签名-3","experience":362,"logins":157,"wealth":37117017,"classify":"诗人","score":68},
{"id":10004,"username":"user-4","sex":"男","city":"城市-4","sign":"签名-4","experience":807,"logins":51,"wealth":76263262,"classify":"作家","score":6}, {"id":10004,"username":"user-4","sex":"男","city":"城市-4","sign":"签名-4","experience":807,"logins":51,"wealth":76263262,"classify":"作家","score":6},
{"id":10005,"username":"user-5","sex":"女","city":"城市-5","sign":"签名-5","experience":173,"logins":68,"wealth":60344147,"classify":"作家","score":87}, {"id":10005,"username":"user-5","sex":"女","city":"城市-5","sign":"签名-5","experience":173,"logins":68,"wealth":60344147,"classify":"作家","score":87},
{"id":10006,"username":"user-6","sex":"女","city":"城市-6","sign":"签名-6","experience":982,"logins":37,"wealth":57768166,"classify":"作家","score":34}, {"id":10006,"username":"user-6","sex":"女","city":"城市-6","sign":"签名-6","experience":982,"logins":37,"wealth":57768166,"classify":"作家","score":34},
{"id":10007,"username":"user-7","sex":"男","city":"城市-7","sign":"签名-7","experience":727,"logins":150,"wealth":82030578,"classify":"作家","score":28}, {"id":10007,"username":"user-7","sex":"男","city":"城市-7","sign":"签名-7","experience":727,"logins":150,"wealth":82030578,"classify":"作家","score":28},
{"id":10008,"username":"user-8","sex":"男","city":"城市-8","sign":"签名-8","experience":951,"logins":133,"wealth":16503371,"classify":"词人","score":14}, {"id":10008,"username":"user-8","sex":"男","city":"城市-8","sign":"签名-8","experience":951,"logins":133,"wealth":16503371,"classify":"词人","score":14},
{"id":10009,"username":"user-9","sex":"女","city":"城市-9","sign":"签名-9","experience":484,"logins":25,"wealth":86801934,"classify":"词人","score":75} {"id":10009,"username":"user-9","sex":"女","city":"城市-9","sign":"签名-9","experience":484,"logins":25,"wealth":86801934,"classify":"词人","score":75}
], ],
done: function(res){ done: function(res){
//修改一些css样式, 这里虽然能够使用, 但是还是不太友好, 努力中... //修改一些css样式, 这里虽然能够使用, 但是还是不太友好, 努力中...
var cells = document.querySelectorAll('div[lay-id="demo"] .layui-table-cell'); var cells = document.querySelectorAll('div[lay-id="demo"] .layui-table-cell');
for(var i = 0 ; i < cells.length ; i++ ){ for(var i = 0 ; i < cells.length ; i++ ){
cells[i].style.overflow = 'unset'; cells[i].style.overflow = 'unset';
cells[i].style.height = 'auto'; cells[i].style.height = 'auto';
} }
//渲染多选 //渲染多选
res.data.forEach(item => { res.data.forEach(item => {
var xm = xmSelect.render({ var xm = xmSelect.render({
el: '#XM-' + item.id, el: '#XM-' + item.id,
autoRow: true, autoRow: true,
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
item.__xm = xm; item.__xm = xm;
}) })
} }
}); });
}); });

View File

@ -5,32 +5,32 @@
<div id="demo1"></div> <div id="demo1"></div>
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
autoRow: true, autoRow: true,
toolbar: { show: true }, toolbar: { show: true },
filterable: true, filterable: true,
remoteSearch: true, remoteSearch: true,
remoteMethod: function(val, cb, show){ remoteMethod: function(val, cb, show){
//这里如果val为空, 则不触发搜索 //这里如果val为空, 则不触发搜索
if(!val){ if(!val){
return cb([]); return cb([]);
} }
//这里引入了一个第三方插件axios, 相当于$.ajax //这里引入了一个第三方插件axios, 相当于$.ajax
axios({ axios({
method: 'get', method: 'get',
url: 'https://www.fastmock.site/mock/98228b1f16b7e5112d6c0c87921eabc1/xmSelect/search', url: 'https://www.fastmock.site/mock/98228b1f16b7e5112d6c0c87921eabc1/xmSelect/search',
params: { params: {
keyword: val, keyword: val,
} }
}).then(response => { }).then(response => {
var res = response.data; var res = response.data;
cb(res.data) cb(res.data)
}).catch(err => { }).catch(err => {
cb([]); cb([]);
}); });
}, },
}) })
</script> </script>
``` ```
::: :::

View File

@ -9,16 +9,16 @@
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [] data: []
}) })
demo1.update({ demo1.update({
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, selected: true}, {name: '李四', value: 2, selected: true},
{name: '王五', value: 3, disabled: true}, {name: '王五', value: 3, disabled: true},
] ]
}) })
</script> </script>
@ -34,21 +34,21 @@ demo1.update({
<script> <script>
var demo2 = xmSelect.render({ var demo2 = xmSelect.render({
el: '#demo2', el: '#demo2',
toolbar: {show: true}, toolbar: {show: true},
data: [] data: []
}) })
axios({ axios({
method: 'get', method: 'get',
url: 'https://www.fastmock.site/mock/98228b1f16b7e5112d6c0c87921eabc1/xmSelect/search', url: 'https://www.fastmock.site/mock/98228b1f16b7e5112d6c0c87921eabc1/xmSelect/search',
}).then(response => { }).then(response => {
var res = response.data; var res = response.data;
demo2.update({ demo2.update({
data: res.data, data: res.data,
autoRow: true, autoRow: true,
}) })
}); });
</script> </script>

View File

@ -9,24 +9,24 @@
<script> <script>
document.getElementById('demo1-btn').onclick = function(){ document.getElementById('demo1-btn').onclick = function(){
layer.open({ layer.open({
type: 1, type: 1,
title: '多选', title: '多选',
content: '<div id="demo1" class="xm-select-demo-alert"></div>', content: '<div id="demo1" class="xm-select-demo-alert"></div>',
success: function(layero, index){ success: function(layero, index){
//这里因为内容过少, 会被遮挡, 所以简单修改了下样式 //这里因为内容过少, 会被遮挡, 所以简单修改了下样式
document.getElementById('layui-layer' + index).getElementsByClassName('layui-layer-content')[0].style.overflow = 'unset'; document.getElementById('layui-layer' + index).getElementsByClassName('layui-layer-content')[0].style.overflow = 'unset';
//渲染多选 //渲染多选
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2, disabled: true}, {name: '李四', value: 2, disabled: true},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
} }
}); });
} }
</script> </script>
``` ```

View File

@ -17,7 +17,7 @@ xmSelect.get('#demo2');
xmSelect.get(/demo.*/); xmSelect.get(/demo.*/);
//过滤方法 //过滤方法
xmSelect.get((el) => { xmSelect.get((el) => {
return el == '#demo1' || el == '#xm3' return el == '#demo1' || el == '#xm3'
}); });
//获取单实例 //获取单实例
xmSelect.get('#demo2', true); xmSelect.get('#demo2', true);
@ -39,12 +39,12 @@ xmSelect.get('#demo2', true);
['#demo1', '#demo2', '#xm3'].forEach((el, index) => { ['#demo1', '#demo2', '#xm3'].forEach((el, index) => {
xmSelect.render({ xmSelect.render({
el, el,
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3, disabled: true}, {name: '王五', value: 3, disabled: true},
] ]
}); });
}); });

View File

@ -27,24 +27,24 @@ xmSelect.batch(filter, method, ...args);
['#demo1', '#demo2', '#xm3'].forEach((el, index) => { ['#demo1', '#demo2', '#xm3'].forEach((el, index) => {
xmSelect.render({ xmSelect.render({
el, el,
data: [ data: [
{name: '张三', value: 1, selected: true}, {name: '张三', value: 1, selected: true},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3, disabled: true}, {name: '王五', value: 3, disabled: true},
] ]
}); });
}); });
document.getElementById('btn1').onclick = function(){ document.getElementById('btn1').onclick = function(){
xmSelect.batch('', 'update', { xmSelect.batch('', 'update', {
disabled: true disabled: true
}); });
} }
document.getElementById('btn2').onclick = function(){ document.getElementById('btn2').onclick = function(){
xmSelect.batch('', 'update', { xmSelect.batch('', 'update', {
disabled: false disabled: false
}); });
} }
@ -53,8 +53,8 @@ document.getElementById('btn3').onclick = function(){
} }
document.getElementById('btn4').onclick = function(){ document.getElementById('btn4').onclick = function(){
var selectArr = xmSelect.batch(null, 'getValue', 'name'); var selectArr = xmSelect.batch(null, 'getValue', 'name');
document.getElementById('demo-value').innerHTML = JSON.stringify(selectArr, null, 2); document.getElementById('demo-value').innerHTML = JSON.stringify(selectArr, null, 2);
} }
</script> </script>
``` ```

View File

@ -14,37 +14,59 @@
<script> <script>
//先渲染多选 //先渲染多选
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
content: ` prop: {
<table class="layui-table"> name: 'username',
<colgroup> value: 'username',
<col width="150"> },
<col width="200"> content: `
<col> <table class="layui-table" lay-filter="demo">
</colgroup> <thead>
<thead> <tr>
<tr> <th lay-data="{field:'username', width:80}">昵称</th>
<th>昵称</th> <th lay-data="{field:'experience', width:50, sort:true}">积分</th>
<th>加入时间</th> <th lay-data="{field:'sign', width: 200}">签名</th>
<th>签名</th> </tr>
</tr> </thead>
</thead> <tbody>
<tbody> <tr>
<tr> <td>贤心1</td>
<td>贤心</td> <td>66</td>
<td>2016-11-29</td> <td>人生就像是一场修行a</td>
<td>人生就像是一场修行</td> </tr>
</tr> <tr>
<tr> <td>贤心2</td>
<td>许闲心</td> <td>88</td>
<td>2016-11-28</td> <td>人生就像是一场修行b</td>
<td>于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…</td> </tr>
</tr> <tr>
</tbody> <td>贤心3</td>
</table> <td>33</td>
`, <td>人生就像是一场修行c</td>
</tr>
</tbody>
</table>
`,
height: 'auto',
}) })
layui.table.init('demo', {
done: function(res){
demo1.update({ data: res.data })
}
}).on('row(demo)', function(obj){
var values = demo1.getValue();
var item = obj.data;
var has = values.find(function(i){
return i.username === item.username
})
if(has){
demo1.delete([ item ]);
}else{
demo1.append([ item ]);
}
})

View File

@ -1,8 +1,23 @@
## 下拉树 ## 下拉树
### eleTree ### tree
结合 `layui` 插件中心的 `eleTree`, <a href='https://fly.layui.com/extend/eleTree/' target='_blank'>传送门</a> 默认配置
```
tree: {
//是否显示树状结构
show: false,
//是否展示三角图标
showFolderIcon: true,
//是否显示虚线
showLine: false,
//间距
indent: 20,
//默认展开节点的数组
expandedKeys: [],
},
```
:::demo :::demo
@ -10,60 +25,81 @@
<div id="demo1" class="xm-select-demo"></div> <div id="demo1" class="xm-select-demo"></div>
<br/>
<div class="layui-form">
<input type="checkbox" name="showFolderIcon" lay-filter="showFolderIcon" lay-skin="primary" title="是否展示三角图标" checked>
<input type="checkbox" name="showLine" lay-filter="showLine" lay-skin="primary" title="是否显示虚线" checked>
</div>
<div style="margin-top: 20px">间距</div>
<div id="slideTest1"></div>
<script> <script>
//先渲染多选 layui.form.render();
layui.form.on('checkbox(showFolderIcon)', function(data){
demo1.update({
tree: {
showFolderIcon: data.elem.checked
}
})
});
layui.form.on('checkbox(showLine)', function(data){
demo1.update({
tree: {
showLine: data.elem.checked
}
})
});
layui.slider.render({
elem: '#slideTest1',
min: 10,
max: 100,
showstep: true,
input: true,
tips: true,
value: 20,
change: function(value){
demo1.update({
tree: {
indent: value
}
})
}
});
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
theme: { autoRow: true,
color: '#5FB878', tree: {
}, show: true,
content: '<div id="ele1" lay-filter="ele1"></div>', showFolderIcon: true,
showLine: true,
indent: 20,
expandedKeys: [ -3 ],
},
height: 'auto',
data(){
return [
{name: '销售员', value: -1, disabled: true, children: [
{name: '张三1', value: 1, selected: true},
{name: '李四1', value: 2, selected: true},
{name: '王五1', value: 3, disabled: true},
]},
{name: '奖品', value: -2, children: [
{name: '奖品3', value: -3, children: [
{name: '苹果3', value: 14, selected: true},
{name: '香蕉3', value: 15},
{name: '葡萄3', value: 16},
]},
{name: '苹果2', value: 4, selected: true, disabled: true},
{name: '香蕉2', value: 5},
{name: '葡萄2', value: 6},
]},
]
}
}) })
//渲染自定义内容
var ele = layui.eleTree.render({
elem: '#ele1',
data: [
{ id: 1, label: "安徽省", children: [
{ id: 2, label: "马鞍山市", disabled: true, children: [
{ id: 3, label: "和县" },
{ id: 4, label: "花山区" }
]}
]},
{ id: 5, label: "河南省", children: [
{ id: 6, label: "郑州市" },
{ id: 7, label: "开封市" },
{ id: 8, label: "焦作市" },
{ id: 9, label: "洛阳市" },
]}
],
showCheckbox: true,
defaultExpandAll: true,
});
//监听下拉多选的选择
demo1.update({
on({ arr, change, isAdd }){
if(isAdd === false){//监听取消
ele.setChecked(arr.map(item => item.id), true);
}
},
});
//监听树的选择
layui.eleTree.on("nodeChecked(ele1)", function(d) {
var arr = ele.getChecked(true, false)
demo1.update({
prop: {
name: 'label',
value: 'id',
},
data: arr,
}).setValue(arr)
})
</script> </script>
``` ```
::: :::

View File

@ -1,8 +1,14 @@
## 下拉 ## 下拉日期多选
### layuiTree ### laydate
结合 `layui``tree`, <a href='https://www.layui.com/doc/modules/tree.html' target='_blank'>传送门</a> ```
//css调整部分
xm-select .scroll-body{
text-align: center;
}
```
:::demo :::demo
```html ```html
@ -10,55 +16,69 @@
<div id="demo1" class="xm-select-demo"></div> <div id="demo1" class="xm-select-demo"></div>
<script> <script>
var data = [
{ id: 1, title: "安徽省", children: [
{ id: 2, title: "马鞍山市", disabled: true, children: [
{ id: 3, title: "和县" },
{ id: 4, title: "花山区" }
]}
]},
{ id: 5, title: "河南省", children: [
{ id: 6, title: "郑州市" },
{ id: 7, title: "开封市" },
{ id: 8, title: "焦作市" },
{ id: 9, title: "洛阳市" },
]}
]
//先渲染多选
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
theme: { content: '<div id="laydate" />',
color: '#5FB878', height: 'auto',
}, autoRow: true,
content: '<div id="layuiTree"></div>', on: function(data){
data: data, if(!data.isAdd){
prop: { dateSelect(demo1.getValue('value'));
name: 'title', }
value: 'id', }
}
}) })
//渲染自定义内容 layui.laydate.render({
var ele = layui.tree.render({ elem: '#laydate',
id: 'demoId', position: 'static',
elem: '#layuiTree', showBottom: false,
data: data, format: 'yyyy-M-dd',
showCheckbox: true, change: function(){
oncheck: function(obj){ dateSelect(demo1.getValue('value'));
var checkData = layui.tree.getChecked('demoId'); },
} done: function(value){
}); console.log(value)
var values = demo1.getValue('value');
var index = values.findIndex(function(val){
return val === value
});
//监听下拉多选的选择 if(index != -1){
demo1.update({ values.splice(index, 1);
on({ arr, change, isAdd }){ }else{
if(isAdd === false){//监听取消 values.push(value);
ele.setChecked(arr.map(item => item.id), true); }
}
}, dateSelect(values);
});
demo1.update({
data: values.map(function(val){
return {
name: val,
value: val,
selected: true,
}
})
})
},
ready: removeAll,
})
function removeAll(){
document.querySelectorAll('#laydate td[lay-ymd].layui-this').forEach(function(dom){
dom.classList.remove('layui-this');
});
}
function dateSelect(values){
removeAll();
values.forEach(function(val){
var dom = document.querySelector('#laydate td[lay-ymd="'+val.replace(/-0([1-9])/g, '-$1')+'"]');
dom && dom.classList.add('layui-this');
});
}
//这里仅仅提供一个演示, 更多的想法由你自己来创造
</script> </script>
``` ```

View File

@ -9,36 +9,36 @@
<script> <script>
//先渲染多选 //先渲染多选
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
autoRow: true, autoRow: true,
filterable: true, tree: {
toolbar: {show: true}, show: true,
paging: true, expandedKeys: [-3],
create: (val, data) => { },
console.log(val, data) height: 'auto',
return { on({ arr, change, isAdd }){
name: val, console.log(arr, change, isAdd)
value: val, },
} data(){
}, return [
data(){ {name: '销售员', value: -1, disabled: true, children: [
return [ {name: '张三1', value: 1, selected: true},
{name: '销售员', children: [ {name: '李四1', value: 2, selected: true},
{name: '张三1', value: 1, selected: true}, {name: '王五1', value: 3, disabled: true},
{name: '李四1', value: 2, selected: true}, ]},
{name: '王五1', value: 3, disabled: true}, {name: '奖品', value: -2, children: [
]}, {name: '奖品3', value: -3, children: [
{name: '奖品', children: [ {name: '苹果3', value: 14, selected: true, disabled: true},
{name: '苹果2', value: 4, selected: true, disabled: true}, {name: '香蕉3', value: 15},
{name: '香蕉2', value: 5}, {name: '葡萄3', value: 16},
{name: '葡萄2', value: 6}, ]},
]}, {name: '苹果2', value: 4, selected: true, disabled: true},
] {name: '香蕉2', value: 5},
} {name: '葡萄2', value: 6},
]},
]
}
}) })
</script> </script>
``` ```
::: :::

View File

@ -21,8 +21,8 @@
//lES6 新增了let命令用来声明变量。它的用法类似于var但是所声明的变量只在let命令所在的代码块内有效。 //lES6 新增了let命令用来声明变量。它的用法类似于var但是所声明的变量只在let命令所在的代码块内有效。
{ {
let a = 10; let a = 10;
var b = 1; var b = 1;
} }
a // ReferenceError: a is not defined. a // ReferenceError: a is not defined.
@ -66,10 +66,10 @@ let name = "Bob", time = "today";
var name = 'zs'; var name = 'zs';
var obj = { var obj = {
name: name, name: name,
run: function(){ run: function(){
console.log('haha'); console.log('haha');
} }
} }
@ -77,10 +77,10 @@ var obj = {
let name = 'zs'; let name = 'zs';
let obj = { let obj = {
name, name,
run(){ run(){
console.log('haha'); console.log('haha');
} }
} }
``` ```
@ -90,12 +90,12 @@ let obj = {
``` ```
//常规写法 //常规写法
setTimeout(function(){ setTimeout(function(){
//... //...
}, 1000); }, 1000);
//简写 //简写
setTimeout(() => { setTimeout(() => {
//... //...
}, 1000); }, 1000);
``` ```
@ -105,9 +105,9 @@ setTimeout(() => {
``` ```
//假如现在有一个对象 //假如现在有一个对象
let obj = { let obj = {
name: 'zs', name: 'zs',
age: 18, age: 18,
address: 'beijing', address: 'beijing',
} }
//正常获取name //正常获取name
@ -127,19 +127,19 @@ obj.status = '1';
//对象属性合并 //对象属性合并
var newObj = { var newObj = {
...obj, ...obj,
status: '1' status: '1'
} }
//方法传参 //方法传参
function calc(data){ function calc(data){
var a = data.a; var a = data.a;
var b = data.b; var b = data.b;
return a + b; return a + b;
} }
//解构传参 //解构传参
function calc({ a, b }){ function calc({ a, b }){
return a + b; return a + b;
} }
``` ```

View File

@ -16,9 +16,9 @@
> 作者: maplemei, 热爱前端的Java程序猿, 如果喜欢作者的插件, 可以请作者吃雪糕 ^_^ > 作者: maplemei, 热爱前端的Java程序猿, 如果喜欢作者的插件, 可以请作者吃雪糕 ^_^
<p> <p>
<a href="javascript:;"> <a href="javascript:;">
<img src="../assets/wx.jpg" alt="打赏" width="300"> <img src="../assets/wx.jpg" alt="打赏" width="300">
</a> </a>
</p> </p>
@ -52,19 +52,19 @@ $ npm install && npm run dev
<script> <script>
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
language: 'zn', language: 'zn',
data: [ data: [
{name: '张三', value: 1}, {name: '张三', value: 1},
{name: '李四', value: 2}, {name: '李四', value: 2},
{name: '王五', value: 3}, {name: '王五', value: 3},
] ]
}) })
document.getElementById('demo1-getValue').onclick = function(){ document.getElementById('demo1-getValue').onclick = function(){
//获取当前多选选中的值 //获取当前多选选中的值
var selectArr = demo1.getValue(); var selectArr = demo1.getValue();
document.getElementById('demo1-value').innerHTML = JSON.stringify(selectArr, null, 2); document.getElementById('demo1-value').innerHTML = JSON.stringify(selectArr, null, 2);
} }
</script> </script>

View File

@ -3,82 +3,78 @@
### 配置项 ### 配置项
| 参数 | 说明 | 类型 | 可选值 | 默认值 | | 参数 | 说明 | 类型 | 可选值 | 默认值 |
| ----------------- | ------------------------------ | --------------- | ------ | ------ | | ----------------- | ------------------------------ | --------------- | ------ | ------ |
| el | 渲染对象, css选择器 | string | - | - | | el | 渲染对象, css选择器 | string | - | - |
| language | 语言选择 | string | zn / en | zn | | language | 语言选择 | string | zn / en | zn |
| data | 显示的数据 | array | - | [ ] | | data | 显示的数据 | array | - | [ ] |
| content | 自定义下拉框html | string | - | - | | content | 自定义下拉框html | string | - | - |
| initValue | 初始化选中的数据, 需要在data中存在 | array | - | null | | initValue | 初始化选中的数据, 需要在data中存在 | array | - | null |
| tips | 默认提示, 类似于placeholder | string | - | 请选择 | | tips | 默认提示, 类似于placeholder | string | - | 请选择 |
| empty | 空数据提示 | string | - | 暂无数据 | | empty | 空数据提示 | string | - | 暂无数据 |
| filterable | 是否开启搜索 | boolean | true / false | false | | filterable | 是否开启搜索 | boolean | true / false | false |
| searchTips | 搜索提示 | string | - | 请选择 | | searchTips | 搜索提示 | string | - | 请选择 |
| delay | 搜索延迟 ms | int | - | 500 | | delay | 搜索延迟 ms | int | - | 500 |
| filterMethod | 搜索回调函数 | function(val, item, index, prop) val: 当前搜索值, item: 每个option选项, index: 位置数据中的下标, prop: 定义key | - | - | | filterMethod | 搜索回调函数 | function(val, item, index, prop) val: 当前搜索值, item: 每个option选项, index: 位置数据中的下标, prop: 定义key | - | - |
| filterDone | 搜索完成函数 | function(val, list) val: 当前搜索值, list: 过滤后的数据 | - | - | | filterDone | 搜索完成函数 | function(val, list) val: 当前搜索值, list: 过滤后的数据 | - | - |
| remoteSearch | 是否开启自定义搜索 (远程搜索)| boolean | true / false | false | | remoteSearch | 是否开启自定义搜索 (远程搜索)| boolean | true / false | false |
| remoteMethod | 自定义搜索回调函数 | function(val, cb, show) val: 当前搜索值, cb: 回调函数, 需要回调一个数组, 结构同data, show: 下拉框显示状态 | - | - | | remoteMethod | 自定义搜索回调函数 | function(val, cb, show) val: 当前搜索值, cb: 回调函数, 需要回调一个数组, 结构同data, show: 下拉框显示状态 | - | - |
| direction | 下拉方向| string | auto / up / down | auto | | direction | 下拉方向| string | auto / up / down | auto |
| style | 自定义样式| object | - | { } | | style | 自定义样式| object | - | { } |
| height | 默认最大高度| string | - | 200px | | height | 默认最大高度| string | - | 200px |
| paging | 是否开启自定义分页 | boolean | true / false | false | | paging | 是否开启自定义分页 | boolean | true / false | false |
| pageSize | 分页条数 | int | - | 10 | | pageSize | 分页条数 | int | - | 10 |
| pageEmptyShow | 分页无数据是否显示 | boolean | true / false | true | | pageEmptyShow | 分页无数据是否显示 | boolean | true / false | true |
| radio | 是否开启单选模式 | boolean | true / false | false | | radio | 是否开启单选模式 | boolean | true / false | false |
| repeat | 是否开启重复性模式 | boolean | true / false | false | | repeat | 是否开启重复性模式 | boolean | true / false | false |
| clickClose | 是否点击选项后自动关闭下拉框 | boolean | true / false | false | | clickClose | 是否点击选项后自动关闭下拉框 | boolean | true / false | false |
| prop | 自定义属性名称, 具体看下表 | object | - | | | prop | 自定义属性名称, 具体看下表 | object | - | |
| theme | 主题配置, 具体看下表 | object | - | | | theme | 主题配置, 具体看下表 | object | - | |
| model | 模型, 多选的展示方式, 具体见下表 | object | - | | | model | 模型, 多选的展示方式, 具体见下表 | object | - | |
| show | 展开下拉的回调 | function | - | - | | show | 展开下拉的回调 | function | - | - |
| hide | 隐藏下拉的回调 | function | - | - | | hide | 隐藏下拉的回调 | function | - | - |
| template | 自定义渲染选项 | function({ item, sels, name, value }) | - | - | | template | 自定义渲染选项 | function({ item, sels, name, value }) | - | - |
| on | 监听选中变化 | function({ arr, change, isAdd }) | - | - | | on | 监听选中变化 | function({ arr, change, isAdd }) | - | - |
| max | 设置多选选中上限 | int | - | 0 | | max | 设置多选选中上限 | int | - | 0 |
| maxMethod | 达到选中上限的回到 | function(sels, item), sels: 已选中数据, item: 当前选中的值 | - | - | | maxMethod | 达到选中上限的回到 | function(sels, item), sels: 已选中数据, item: 当前选中的值 | - | - |
| name | 表单提交时的name | string | - | select | | name | 表单提交时的name | string | - | select |
| toolbar | 工具条, 具体看下表 | object | - | - | | toolbar | 工具条, 具体看下表 | object | - | - |
| showCount | 展示在下拉框中的最多选项数量 | int | - | 0 | | showCount | 展示在下拉框中的最多选项数量 | int | - | 0 |
| autoRow | 是否开启自动换行(选项过多时) | boolean | true / false | false | | autoRow | 是否开启自动换行(选项过多时) | boolean | true / false | false |
| size | 尺寸 | string | large / medium / small / mini | medium | | size | 尺寸 | string | large / medium / small / mini | medium |
| disabled | 是否禁用多选 | boolean | true / false | false | | disabled | 是否禁用多选 | boolean | true / false | false |
| create | 创建条目 | function(val, data), val: 搜索的数据, data: 当前下拉数据 | - | null | | create | 创建条目 | function(val, data), val: 搜索的数据, data: 当前下拉数据 | - | null |
| tree | 树形结构, 具体看下表 | object | - | - |
### prop ### prop
| 参数 | 说明 | 类型 | 可选值 | 默认值 | | 参数 | 说明 | 类型 | 可选值 | 默认值 |
| ----------------- | ------------------------------ | --------------- | ------ | ------ | | ----------------- | ------------------------------ | --------------- | ------ | ------ |
| name | 显示名称 | string | - | name | | name | 显示名称 | string | - | name |
| value | 选中值, 当前多选唯一 | string | - | value | | value | 选中值, 当前多选唯一 | string | - | value |
| selected | 是否选中 | string | - | selected | | selected | 是否选中 | string | - | selected |
| disabled | 是否禁用 | string | - | disabled | | disabled | 是否禁用 | string | - | disabled |
| children | 分组children | string | - | children | | children | 分组children | string | - | children |
| optgroup | 分组optgroup | string | - | optgroup | | optgroup | 分组optgroup | string | - | optgroup |
### 分组说明 ### 分组说明
如果children属性为数组, 或者optgroup=true的时候开启分组模式 如果children属性为数组的时候开启分组模式
``` ```
//平级结构下面的数据为一组
{name: '城市', optgroup: true},
//children下的数组为一组
{name: '销售员', children: [ {name: '销售员', children: [
{name: '李四', value: 4, selected: true}, {name: '李四', value: 4, selected: true},
{name: '王五', value: 5}, {name: '王五', value: 5},
]}, ]},
//可在分组上定义click属性, 来定义点击事件 //可在分组上定义click属性, 来定义点击事件
//这里以optgroup模式为例, children模式同理 {name: '选中', children: [...], click: 'SELECT'},
{name: '选中', optgroup: true, click: 'SELECT'}, {name: '清空', children: [...], click: 'CLEAR'},
{name: '清空', optgroup: true, click: 'CLEAR'}, {name: '自动', children: [...], click: 'AUTO'},
{name: '自动', optgroup: true, click: 'AUTO'}, {name: '自定义', children: [...], click: function(item){
{name: '自定义', optgroup: true, click: function(item){ alert('自定义的, 想干嘛干嘛');
alert('自定义的, 想干嘛干嘛');
}}, }},
@ -88,10 +84,10 @@
### theme ### theme
| 参数 | 说明 | 类型 | 可选值 | 默认值 | | 参数 | 说明 | 类型 | 可选值 | 默认值 |
| ------------ | --------- | --------------- | ------ | ------ | | ------------ | --------- | --------------- | ------ | ------ |
| color | 主题颜色 | string | - | #009688 | | color | 主题颜色 | string | - | #009688 |
| maxColor | 选中上限闪烁边框颜色 | string | - | #e54d42 | | maxColor | 选中上限闪烁边框颜色 | string | - | #e54d42 |
### model ### model
@ -100,91 +96,101 @@
``` ```
model: { model: {
//是否展示复选框或者单选框图标 show, hidden:变换背景色 //是否展示复选框或者单选框图标 show, hidden:变换背景色
icon: 'show', icon: 'show',
label: { label: {
//使用方式 //使用方式
type: 'block', type: 'block',
//使用字符串拼接的方式 //使用字符串拼接的方式
text: { text: {
//左边拼接的字符 //左边拼接的字符
left: '', left: '',
//右边拼接的字符 //右边拼接的字符
right: '', right: '',
//中间的分隔符 //中间的分隔符
separator: ', ', separator: ', ',
}, },
//使用方块显示 //使用方块显示
block: { block: {
//最大显示数量, 0:不限制 //最大显示数量, 0:不限制
showCount: 0, showCount: 0,
//是否显示删除图标 //是否显示删除图标
showIcon: true, showIcon: true,
}, },
//自定义文字 //自定义文字
count: { count: {
//函数处理 //函数处理
template(data, sels){ template(data, sels){
//data: 所有的数据 //data: 所有的数据
//sels: 选中的数据 //sels: 选中的数据
return `已选中 ${sels.length} 项, 共 ${data.length} 项` return `已选中 ${sels.length} 项, 共 ${data.length} 项`
} }
}, },
}, },
}, },
``` ```
### toolbar ### toolbar
| 参数 | 说明 | 类型 | 可选值 | 默认值 | | 参数 | 说明 | 类型 | 可选值 | 默认值 |
| ------------ | --------- | --------------- | ------ | ------ | | ------------ | --------- | --------------- | ------ | ------ |
| show | 是否展示工具条 | boolean | true / false | false | | show | 是否展示工具条 | boolean | true / false | false |
| showIcon | 是否显示工具图标 | boolean | true / false | true | | showIcon | 是否显示工具图标 | boolean | true / false | true |
| list | 工具条数组 (默认有 全选/清空, 可以自定义), 还有 REVERSE:反选 | array | - | [ "ALL", "CLEAR" ] | | list | 工具条数组 (默认有 全选/清空, 可以自定义), 还有 REVERSE:反选 | array | - | [ "ALL", "CLEAR" ] |
> 自定义方式 > 自定义方式
``` ```
list: [ "ALL", "CLEAR", list: [ "ALL", "CLEAR",
{ {
//显示图标, 可以是layui内置的图标, 也可以是自己引入的图标 //显示图标, 可以是layui内置的图标, 也可以是自己引入的图标
//传入的icon会转化为 <i class="layui-icon layui-icon-face-smile"></i> //传入的icon会转化为 <i class="layui-icon layui-icon-face-smile"></i>
icon: 'layui-icon layui-icon-face-smile', icon: 'layui-icon layui-icon-face-smile',
//显示名称 //显示名称
name: 'xxx', name: 'xxx',
//点击时触发的回调 //点击时触发的回调
method: function(data){ method: function(data){
//data 当前页面的数据 //data 当前页面的数据
} }
} }
] ]
``` ```
### tree
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
| ------------ | --------- | --------------- | ------ | ------ |
| show | 是否展示为树状结构 | boolean | true / false | false |
| showFolderIcon | 是否显示节点前的三角图标 | boolean | true / false | true |
| showLine | 是否显示虚线 | boolean | true / false | true |
| indent | 间距 | int | - | 20 |
| expandedKeys | 默认展开的节点数组 | array | - | [ ] |
### 全局方法 ### 全局方法
| 事件名 | 说明 | 参数 | 返回值 | | 事件名 | 说明 | 参数 | 返回值 |
| ------ | ------------------ | -------- | -------- | | ------ | ------------------ | -------- | -------- |
| render | 渲染多选 | (options: 配置项) | 实例对象 | | render | 渲染多选 | (options: 配置项) | 实例对象 |
| get | 获取页面中已经渲染的多选 | (filter: 过滤`el`, single: 是否返回单实例) | 符合条件的实例数组 | | get | 获取页面中已经渲染的多选 | (filter: 过滤`el`, single: 是否返回单实例) | 符合条件的实例数组 |
| batch | 批量操作已渲染的多选 | (filter: 过滤`el`, method: 方法, ...方法参数) | 符合条件的实例数组 | | batch | 批量操作已渲染的多选 | (filter: 过滤`el`, method: 方法, ...方法参数) | 符合条件的实例数组 |
``` ```
//render 使用方式 //render 使用方式
xmSelect.render(OPTIONS); xmSelect.render(OPTIONS);
//get 使用方式 //get 使用方式
xmSelect.get('#demo1'); //指定某一个获取 xmSelect.get('#demo1'); //指定某一个获取
xmSelect.get(/.*demo1.*/); //正则获取 xmSelect.get(/.*demo1.*/); //正则获取
//自定义方法获取 //自定义方法获取
xmSelect.get(function(el){ xmSelect.get(function(el){
return el == '#demo1' || el == '#demo2'; return el == '#demo1' || el == '#demo2';
}); });
//单实例 //单实例
xmSelect.get('#demo2', true); xmSelect.get('#demo2', true);
@ -192,7 +198,7 @@ xmSelect.get('#demo2', true);
//batch 使用方式 //batch 使用方式
//批量执行禁用 //批量执行禁用
xmSelect.batch(/.*demo/, 'update', { xmSelect.batch(/.*demo/, 'update', {
disabled: true, disabled: true,
}); });
//批量执行warning //批量执行warning
xmSelect.batch(/.*demo/, 'warning', '#F00', true); xmSelect.batch(/.*demo/, 'warning', '#F00', true);
@ -205,7 +211,7 @@ xmSelect.batch(/.*demo/, 'warning', '#F00', true);
xmSelect.render()后会返回一个xmSelect对象, 可以进行方法调用 xmSelect.render()后会返回一个xmSelect对象, 可以进行方法调用
::: :::
| 事件名 | 说明 | 参数 | | 事件名 | 说明 | 参数 |
| ------ | ------------------ | -------- | | ------ | ------------------ | -------- |
| getValue | 获取当前选中的数据 | (type: 类型), 可选值: name, nameStr, value, valueStr | | getValue | 获取当前选中的数据 | (type: 类型), 可选值: name, nameStr, value, valueStr |
| setValue | 动态设置数据 | (array: 选中的数据, show: 是否展开下拉,不传默认当前显示状态,取值: true/false, listenOn: 是否触发on的监听, 默认false) | | setValue | 动态设置数据 | (array: 选中的数据, show: 是否展开下拉,不传默认当前显示状态,取值: true/false, listenOn: 是否触发on的监听, 默认false) |

View File

@ -37,8 +37,8 @@
``` ```
var demo1 = xmSelect.render({ var demo1 = xmSelect.render({
el: '#demo1', el: '#demo1',
data: [] data: []
}) })
//....N多操作以后 //....N多操作以后
@ -53,7 +53,7 @@ arr = JSON.parse(arr);
arr = eval('(' + arr + ')'); arr = eval('(' + arr + ')');
demo1.update({ demo1.update({
data: arr, data: arr,
}) })

View File

@ -97,8 +97,8 @@ export default [{
component: Component, component: Component,
children: [ children: [
{ path: '/example-plugin/ZP01', name: '下拉自定义', component: importMd('/ZP01') }, { path: '/example-plugin/ZP01', name: '下拉自定义', component: importMd('/ZP01') },
{ path: '/example-plugin/ZP02', name: '下拉树 EleTree', component: importMd('/ZP02') }, { path: '/example-plugin/ZP02', name: '下拉树 Tree', component: importMd('/ZP02') },
// { path: '/example-plugin/ZP03', name: '下拉树 LayuiTree', component: importMd('/ZP03') }, { path: '/example-plugin/ZP03', name: '下拉日期多选', component: importMd('/ZP03') },
] ]
}, { }, {
path: '/question', path: '/question',
@ -112,6 +112,7 @@ export default [{
path: '/test', path: '/test',
name: '测试', name: '测试',
hidden: true, hidden: true,
// hidden: false,
component: importMd('/ZTEST'), component: importMd('/ZTEST'),
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "xm-select", "name": "xm-select",
"version": "1.0.13", "version": "1.1.0",
"description": "始于Layui的select多选解决方案", "description": "始于Layui的select多选解决方案",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@ -27,6 +27,7 @@
"markdown-it-anchor": "^5.2.4", "markdown-it-anchor": "^5.2.4",
"markdown-it-chain": "^1.3.0", "markdown-it-chain": "^1.3.0",
"markdown-it-container": "^2.0.0", "markdown-it-container": "^2.0.0",
"preact": "^10.0.5",
"style-loader": "^0.23.1", "style-loader": "^0.23.1",
"transliteration": "^2.1.7", "transliteration": "^2.1.7",
"url-loader": "^2.1.0", "url-loader": "^2.1.0",

166
src/common/util.js Normal file
View File

@ -0,0 +1,166 @@
/**
* 选中dom元素
*/
export function selector(el) {
return document.querySelector(el);
}
/**
* 警告提示
*/
export function warn() {
let arr = [];
for (var i = 0; i < arguments.length; i++) {
arr.push(`${i + 1}. ${arguments[i]}`);
}
console.warn(arr.join('\n'));
}
/**
* 安全拷贝数据
*/
export function safety(data) {
return JSON.parse(JSON.stringify(data));
}
/**
* 检测对象是否为数组
*/
export function isArray(obj) {
return Object.prototype.toString.call(obj) == "[object Array]";
}
/**
* 检测对象是否为函数
*/
export function isFunction(obj) {
return Object.prototype.toString.call(obj) == "[object Function]";
}
/**
* 转化为数字
*/
export function toNum(obj) {
obj -= 0;
isNaN(obj) && (obj = 0);
return obj;
}
/**
* 简单的深度合并
*/
export function deepMerge(obj1, obj2) {
let key;
for (key in obj2) {
// 如果target(也就是obj1[key])存在且是对象的话再去调用deepMerge否则就是obj1[key]里面没这个对象需要与obj2[key]合并
// 如果obj2[key]没有值或者值不是对象此时直接替换obj1[key]
obj1[key] =
obj1[key] &&
obj1[key].toString() === "[object Object]" &&
(obj2[key] && obj2[key].toString() === "[object Object]") ?
deepMerge(obj1[key], obj2[key]) :
(obj1[key] = obj2[key]);
}
return obj1;
}
/**
* 数组合并
*/
export function mergeArr(arr1, arr2, prop) {
let value = prop.value;
let result = [...arr2];
for (let i = 0; i < arr1.length; i++) {
let item = arr1[i];
if (!arr2.find(a => a[value] == item[value])) {
result.push(item);
}
}
return result;
}
export function watch(data) {
return new Promise((resolve, reject) => {
for (let key in data) {
let value = data[key];
Object.defineProperty(data, key, {
configurable: false, // 该状态下的属性描述符不能被修改和删除
enumerable: false, // 该状态下的属性描述符中的属性不可被枚举
get() {
return value;
},
set(newVal) {
if (newVal !== value) {
resolve(key, newVal, value);
value = newVal;
}
}
});
}
});
}
export function checkUserAgent() {
const ua = navigator.userAgent;
if (ua.indexOf('Mac OS') != -1) {
return 'mac';
}
return 'win';
}
export function IEVersion() {
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
if (isIE) {
var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
reIE.test(userAgent);
var fIEVersion = parseFloat(RegExp["$1"]);
if (fIEVersion == 7) {
return 7;
} else if (fIEVersion == 8) {
return 8;
} else if (fIEVersion == 9) {
return 9;
} else if (fIEVersion == 10) {
return 10;
} else {
return 6; //IE版本<=7
}
} else if (isEdge) {
return 'edge'; //edge
} else if (isIE11) {
return 11; //IE11
} else {
return -1; //不是ie浏览器
}
}
export function exchangeOptionsData(arr, { prop }){
let { disabled, children, optgroup, value } = prop;
let newArr = [], group;
for(let i = 0; i < arr.length; i++){
let item = arr[i];
newArr.push(item);
if(item[optgroup]){
group = item;
item[children] = [];
continue;
}
let child = item[children];
if(isArray(child)){
group = null;
item[optgroup] = true;
child.forEach(c => newArr.push(c));
continue;
}
if(group){
group[children].push(item);
}
}
return newArr;
}

View File

@ -1,172 +0,0 @@
/**
* 选中dom元素
*/
export function selector(el) {
return document.querySelector(el);
}
/**
* 警告提示
*/
export function warn() {
let arr = [];
for (var i = 0; i < arguments.length; i++) {
arr.push(`${i + 1}. ${arguments[i]}`);
}
console.warn(arr.join('\n'));
}
/**
* 全局监听点击事件
*/
export function listenerClose(data, handler) {
window.addEventListener('click', (e) => handler(e));
}
/**
* 安全拷贝数据
*/
export function safety(data) {
return JSON.parse(JSON.stringify(data));
}
/**
* 检测对象是否为数组
*/
export function isArray(obj) {
return Object.prototype.toString.call(obj) == "[object Array]";
}
/**
* 检测对象是否为函数
*/
export function isFunction(obj) {
return Object.prototype.toString.call(obj) == "[object Function]";
}
/**
* 转化为数字
*/
export function toNum(obj) {
obj -= 0;
isNaN(obj) && (obj = 0);
return obj;
}
/**
* 简单的深度合并
*/
export function deepMerge(obj1, obj2) {
let key;
for (key in obj2) {
// 如果target(也就是obj1[key])存在且是对象的话再去调用deepMerge否则就是obj1[key]里面没这个对象需要与obj2[key]合并
// 如果obj2[key]没有值或者值不是对象此时直接替换obj1[key]
obj1[key] =
obj1[key] &&
obj1[key].toString() === "[object Object]" &&
(obj2[key] && obj2[key].toString() === "[object Object]") ?
deepMerge(obj1[key], obj2[key]) :
(obj1[key] = obj2[key]);
}
return obj1;
}
/**
* 数组合并
*/
export function mergeArr(arr1, arr2, prop) {
let value = prop.value;
let result = [...arr2];
for (let i = 0; i < arr1.length; i++) {
let item = arr1[i];
if (!arr2.find(a => a[value] == item[value])) {
result.push(item);
}
}
return result;
}
export function watch(data) {
return new Promise((resolve, reject) => {
for (let key in data) {
let value = data[key];
Object.defineProperty(data, key, {
configurable: false, // 该状态下的属性描述符不能被修改和删除
enumerable: false, // 该状态下的属性描述符中的属性不可被枚举
get() {
return value;
},
set(newVal) {
if (newVal !== value) {
resolve(key, newVal, value);
value = newVal;
}
}
});
}
});
}
export function checkUserAgent() {
const ua = navigator.userAgent;
if (ua.indexOf('Mac OS') != -1) {
return 'mac';
}
return 'win';
}
export function IEVersion() {
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
if (isIE) {
var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
reIE.test(userAgent);
var fIEVersion = parseFloat(RegExp["$1"]);
if (fIEVersion == 7) {
return 7;
} else if (fIEVersion == 8) {
return 8;
} else if (fIEVersion == 9) {
return 9;
} else if (fIEVersion == 10) {
return 10;
} else {
return 6; //IE版本<=7
}
} else if (isEdge) {
return 'edge'; //edge
} else if (isIE11) {
return 11; //IE11
} else {
return -1; //不是ie浏览器
}
}
export function exchangeOptionsData(arr, { prop }){
let { disabled, children, optgroup, value } = prop;
let newArr = [], group;
for(let i = 0; i < arr.length; i++){
let item = arr[i];
newArr.push(item);
if(item[optgroup]){
group = item;
item[children] = [];
continue;
}
let child = item[children];
if(isArray(child)){
group = null;
item[optgroup] = true;
child.forEach(c => newArr.push(c));
continue;
}
if(group){
group[children].push(item);
}
}
return newArr;
}

View File

@ -1,11 +0,0 @@
export default {
tips: 'please selected',
empty: 'no data',
searchTips: 'please search',
toolbar: {
ALL: 'select all',
CLEAR: 'clear',
REVERSE: 'invert select',
SEARCH: 'search',
}
}

View File

@ -1,11 +0,0 @@
export default {
tips: '请选择',
empty: '暂无数据',
searchTips: '请选择',
toolbar: {
ALL: '全选',
CLEAR: '清空',
REVERSE: '反选',
SEARCH: '搜索',
}
}

View File

@ -1,179 +0,0 @@
import { h, Component, render } from '@/components/preact'
import Framework from '@/components/element/framework'
import { selector, warn, listenerClose, isArray, deepMerge, exchangeOptionsData } from '@/components/common/util'
import defaultOptions from '@/components/config/options'
/**
* 保留初始化的数据
*/
const initData = {};
const data = {};
const onClose = (el) => Object.keys(data).filter(a => a != el).forEach(el => data[el].closed());
listenerClose(data, onClose);
/**
* 子组件集合
*/
const childs = {};
/**
* 对外提供的处理方法
*/
class xmOptions {
constructor(options) {
//保留初始化时的数据
initData[options.el] = options;
//定义默认值
this.options = defaultOptions(options.language);
//开始渲染数据
this.update(options);
}
/**
* 更新数据 + 重新渲染
*/
update(options = {}){
//记录最新的配置项
this.options = deepMerge(this.options, options);
//如果dom不存在, 则不进行渲染事项
let dom = selector(this.options.el);
if(!dom){
warn(`没有找到渲染对象: ${options.el}, 请检查`)
return ;
}
//判断data的数据类型
let optionsData = this.options.data || [];
if(typeof(optionsData) === 'function'){
optionsData = optionsData();
this.options.data = optionsData;
}
if(!isArray(optionsData)){
warn(`data数据必须为数组类型, 不能是${ typeof(data) }类型`)
return ;
}
//调整数据结构
this.options.data = exchangeOptionsData(optionsData, this.options);
const onRef = (ref) => childs[this.options.el] = ref;
render(<Framework { ...this.options } onClose={ onClose } onRef={ onRef } />, dom);
//记录数据
data[this.options.el] = this;
//返回多选对象
return this;
}
/**
* 重置多选, 回到初始化的状态
*/
reset(){
let initVal = this.options;
//设置options的默认数据
this.options = defaultOptions(initVal.language);
//更新渲染
this.update({ ...initData[initVal.el]});
//子组件初始化
childs[this.options.el].reset(this.options, true);
return this;
}
/**
* 主动打开多选
*/
opened(){
let ref = childs[this.options.el];
!ref.state.show && ref.onClick();
return this;
}
/**
* 主动关闭多选
*/
closed(){
let ref = childs[this.options.el];
ref.state.show && ref.onClick();
return this;
}
/**
* 获取多选选中的数据
*/
getValue(type){
let arr = deepMerge([], childs[this.options.el].state.sels);
if(type === 'name'){
return arr.map(item => item[this.options.prop.name]);
}else
if(type === 'nameStr'){
return arr.map(item => item[this.options.prop.name]).join(',');
}else
if(type === 'value'){
return arr.map(item => item[this.options.prop.value]);
}else
if(type === 'valueStr'){
return arr.map(item => item[this.options.prop.value]).join(',');
}
return arr;
}
/**
* 设置多选数据
*/
setValue(sels, show, listenOn = false){
if(!isArray(sels)){
warn('请传入数组结构...')
return ;
}
childs[this.options.el].value(sels, show, listenOn);
return this;
}
/**
* 追加赋值
*/
append(sels){
if(!isArray(sels)){
warn('请传入数组结构...')
return ;
}
childs[this.options.el].append(sels);
return this;
}
/**
* 删除赋值
*/
delete(sels){
if(!isArray(sels)){
warn('请传入数组结构...')
return ;
}
childs[this.options.el].del(sels);
return this;
}
/**
* 闪烁警告边框
*/
warning(color, sustain = false){
let showColor = color || this.options.theme.maxColor;
sustain === true ? (
childs[this.options.el].base.style.borderColor = showColor
) : (
childs[this.options.el].updateBorderColor(showColor)
)
return this;
}
}
export default xmOptions;

View File

@ -1,283 +0,0 @@
import { h, Component, render } from '@/components/preact'
import { checkUserAgent, isFunction, toNum, mergeArr } from '@/components/common/util'
//渲染类
import Tips from './tips';
import Label from './label';
import General from './model/general';
import Custom from './model/custom';
/**
* 框架渲染类, 渲染基础的外边框 + 属性变化监听
*/
class Framework extends Component{
constructor(options){
super(options);
//初始化多选数据
this.reset(this.props);
//回传子组件
this.props.onRef(this);
this.bodyView = null;
}
reset(props, refresh = false){
//用于多选上限的边框颜色变化
this.updateBorderColor('');
let old = this.state.data;
this.resetDate(props.data);
(JSON.stringify(props.data) !== JSON.stringify(old) || refresh) && this.value(props.initValue ? props.initValue : this.findValue(this.state.data), !!this.state.show);
}
findValue(data){
const { selected } = this.props.prop;
return data.filter(item => item[selected] === true);
}
resetSelectValue(sels = [], change = [], isAdd, listenOn = true){
let on = this.props.on;
if(isFunction(on) && this.prepare && listenOn){
on({ arr: sels, change, isAdd });
}
this.setState({ sels });
}
resetDate(data = []){
this.setState({ data });
}
value(sels, show, listenOn){
if(show !== false && show !== true){
show = this.state.show;
}
let changeData = this.exchangeValue(sels);
this.resetSelectValue(changeData, changeData, true, listenOn);
this.setState({ show })
}
exchangeValue(sels){
const { optgroup, value } = this.props.prop;
let data = this.state.data;
let list = data.filter(item => !item[optgroup]);
return sels.map(sel => typeof sel === 'object' ? sel[value] : sel).map(val => list.find(item => item[value] == val)).filter(a => a);
}
append(arr){
let changeData = this.exchangeValue(arr);
this.resetSelectValue(mergeArr(changeData, this.state.sels, this.props.prop), changeData, true);
}
del(arr){
let value = this.props.prop.value;
let sels = this.state.sels;
arr = this.exchangeValue(arr);
arr.forEach(v => {
let index = sels.findIndex(item => item[value] === v[value]);
if(index != -1){
sels.splice(index, 1);
}
});
this.resetSelectValue(sels, arr, false);
}
auto(arr){
let value = this.props.prop.value;
let sels = arr.filter(v => this.state.sels.findIndex(item => item[value] === v[value]) != -1);
sels.length == arr.length ? this.del(arr) : this.append(arr);
}
updateBorderColor(tmpColor){
this.setState({ tmpColor });
}
onReset(data, type){
//重置数据
if(type === 'data'){
let changeData = this.findValue(data);
this.resetSelectValue(mergeArr(changeData, this.state.sels, this.props.prop), changeData, true);
this.setState({ data });
}else
//重置选中数据
if(type === 'sels'){
this.resetSelectValue(data, data, true);
}else
//追加数据
if(type === 'append'){
this.append(data);
}else
//清理数据
if(type === 'delete'){
this.del(data);
}else
//自动判断模式
if(type === 'auto'){
this.auto(data);
}
}
onClick(e){
if(this.props.disabled){
this.state.show !== false && this.setState({ show: false });
return ;
}
let show = !this.state.show;
if(show){
if(this.props.show && this.props.show() == false){
return;
}
//事件互斥原则, 打开一个多选, 关闭其他所有多选
this.props.onClose(this.props.el);
}else{
if(this.props.hide && this.props.hide() == false){
return;
}
//如果产生滚动条, 关闭下拉后回到顶部
this.bodyView.scroll && this.bodyView.scroll(0, 0);
}
this.setState({ show });
//阻止其他绑定事件的冒泡
e && e.stopPropagation();
}
componentWillReceiveProps(props){
this.reset(props)
}
componentDidUpdate(){
let direction = this.props.direction;
let rect = this.base.getBoundingClientRect();
if(direction === 'auto'){
//用于控制js获取下拉框的高度
this.bodyView.style.display = 'block';
this.bodyView.style.visibility = 'hidden';
//获取下拉元素的高度
let bodyViewRect = this.bodyView.getBoundingClientRect();
let bodyViewHeight = bodyViewRect.height;
//还原控制效果
this.bodyView.style.display = '';
this.bodyView.style.visibility = '';
//确定下拉框是朝上还是朝下
let clientHeight = document.documentElement.clientHeight;
let diff = clientHeight - (rect.y || rect.top) - rect.height - 20;
direction = diff > bodyViewHeight || (rect.y || rect.top) < diff ? 'down' : 'up';
}
if(direction == 'down'){
this.bodyView.style.top = rect.height + 4 + 'px';
this.bodyView.style.bottom = 'auto';
}else{
this.bodyView.style.top = 'auto';
this.bodyView.style.bottom = rect.height + 4 + 'px';
}
}
componentDidMount(){
this.prepare = true;
}
render(config, { sels, show }) {
const { tips, theme, prop, style, radio, repeat, clickClose, on, max, maxMethod } = config;
const borderStyle = { borderColor: theme.color };
//最外层边框的属性
const xmSelectProps = {
style: {
...style,
...(show ? borderStyle : {})
},
onClick: this.onClick.bind(this),
ua: checkUserAgent(),
size: config.size,
}
if(this.state.tmpColor){
xmSelectProps.style.borderColor = this.state.tmpColor;
setTimeout(() => {
xmSelectProps.style.borderColor = '';
this.updateBorderColor('')
}, 300);
}
if(config.disabled){
show = false;
}
//右边下拉箭头的变化class
const iconClass = show ? 'xm-icon xm-icon-expand' : 'xm-icon';
//提示信息的属性
const tipsProps = {
tips,
//没有已选择数据, 则显示提示
show: !sels.length
}
//普通多选数据
const valueProp = prop.value;
//选项, 选中状态, 禁用状态, 是否强制删除:在label上点击删除
const ck = (item, selected, disabled, mandatoryDelete) => {
//如果是禁用状态, 不能进行操作
if(disabled) return;
//如果现在是选中状态
if(selected && (!repeat || mandatoryDelete)){
let index = sels.findIndex(sel => sel[valueProp] == item[valueProp])
if(index != -1){
sels.splice(index, 1);
this.resetSelectValue(sels, [item], !selected);
}
}else{
//查看是否设置了多选上限
let maxCount = toNum(max);
if(maxCount > 0 && sels.length >= maxCount){
this.updateBorderColor(theme.maxColor);
//查看是否需要回调
maxMethod && isFunction(maxMethod) && maxMethod(sels, item);
return ;
}
//如果是单选模式
if(radio){
this.resetSelectValue([item], [item], !selected);
}else{
this.resetSelectValue([...sels, item], [item], !selected);
}
}
//检查是否为选择即关闭状态, 强制删除情况下不做处理
clickClose && !mandatoryDelete && this.onClick();
};
const select = (
<input class="xm-select-default" name={ config.name } value={ sels.map(item => item[prop.value]).join(',') }></input>
)
const labelProps = { ...config, data: this.state.data, sels, ck, title: sels.map(sel => sel[prop.name]).join(',') }
const bodyProps = { ...config, data: this.state.data, sels, ck, show, onReset: this.onReset.bind(this) }
//控制下拉框的显示于隐藏
const bodyClass = ['xm-body', show ? '' : 'dis'].join(' ');
return (
<xm-select { ...xmSelectProps } >
{ select }
<i class={ iconClass } />
<Tips { ...tipsProps } />
<Label { ...labelProps } />
<div class={ bodyClass } ref={ ref => this.bodyView = ref}>
{ config.content ? (
<Custom content={ config.content } height={ config.height } />
) : (
<General { ...bodyProps } />
) }
</div>
{ config.disabled && <div class="xm-select-disabled"></div> }
</xm-select>
);
}
}
export default Framework;

View File

@ -1,32 +0,0 @@
import { h, Component, render } from '@/components/preact'
/**
* 默认提示
*/
class Custom extends Component{
constructor(options){
super(options);
}
blockClick(e){
e.stopPropagation();
}
shouldComponentUpdate(){
return !this.prepare;
}
render(config) {
this.prepare = true;
return (
<div onClick={ this.blockClick } class="xm-body-custom" >
<div class="scroll-body" style={ {maxHeight: config.height} }>
<div style="margin: 5px 0" dangerouslySetInnerHTML={{ __html: config.content }}></div>
</div>
</div>
)
}
}
export default Custom;

View File

@ -1,412 +0,0 @@
import { h, Component, render } from '@/components/preact'
import { isFunction, isArray, safety, deepMerge, mergeArr, IEVersion } from '@/components/common/util'
/**
* 普通的多选渲染
*/
class General extends Component{
constructor(options){
super(options);
this.setState({
filterValue: '',
remote: true,
loading: false,
pageIndex: 1,
pageSize: 10,
});
this.searchCid = 0;
this.inputOver = true;
this.__value = '';
this.dynamicInput = false;
}
optionClick(item, selected, disabled, e){
this.props.ck(item, selected, disabled);
//阻止父组件上的事件冒泡
this.blockClick(e);
}
groupClick(item, e){
const { click, children, disabled } = this.props.prop;
let m = item[click], arr = item[children].filter(opt => !opt[disabled]);
if(m === 'SELECT'){
this.props.onReset(arr, 'append');
}else if(m === 'CLEAR'){
this.props.onReset(arr, 'delete');
}else if(m === 'AUTO'){
this.props.onReset(arr, 'auto');
}else if(isFunction(m)){
m(item);
}
//阻止父组件上的事件冒泡
this.blockClick(e);
}
blockClick(e){
e.stopPropagation();
}
pagePrevClick(e){
let index = this.state.pageIndex;
if(index <= 1){
return ;
}
this.changePageIndex(index - 1);
}
pageNextClick(e, size){
let index = this.state.pageIndex;
if(index >= size){
return ;
}
this.changePageIndex(index + 1);
}
changePageIndex(index){
this.setState({
pageIndex: index
})
}
searchInput(e){
let v = e.target.value;
if(v === this.__value){
return ;
}
clearTimeout(this.searchCid);
if(this.inputOver){
//保证输入框内的值是实时的
this.__value = v;
//让搜索变成异步的
this.searchCid = setTimeout(() => {
this.callback = true;
this.setState({ filterValue: this.__value, remote: true })
}, this.props.delay);
}
}
focus(){
this.searchInputRef && this.searchInputRef.focus();
}
blur(){
this.searchInputRef && this.searchInputRef.blur();
}
handleComposition(e){
let type = e.type;
if(type === 'compositionstart'){
this.inputOver = false;
clearTimeout(this.searchCid);
}else if(type === 'compositionend'){
this.inputOver = true;
this.searchInput(e);
}
}
componentWillReceiveProps(props){
if(this.props.show != props.show){
if(!props.show){
//清空输入框的值
this.setState({ filterValue: '' });
this.__value = '';
this.searchInputRef && (this.searchInputRef.value = '');
}else{
//聚焦输入框
setTimeout(() => this.focus(), 0);
}
}
}
componentDidUpdate(){
if(this.callback){
this.callback = false;
let done = this.props.filterDone;
if(isFunction(done)){
done(this.state.filterValue, this.tempData || []);
}
}
}
render(config) {
let { data, prop, template, theme, radio, sels, empty, filterable, filterMethod, remoteSearch, remoteMethod, delay, searchTips, create } = config
const { name, value, disabled, children, optgroup } = prop;
let arr = deepMerge([], data), creator;
//是否开启了搜索
if(filterable){
if(remoteSearch){//是否进行远程搜索
if(this.state.remote){
this.callback = false;
this.setState({ loading: true, remote: false });
//让输入框失去焦点
this.blur();
remoteMethod(this.state.filterValue, result => {
//回调后可以重新聚焦
this.focus();
this.callback = true;
this.setState({ loading: false });
this.props.onReset(result, 'data');
}, this.props.show);
}
}else{
const filterData = (item, index) => {
const isGroup = item[optgroup];
if(isGroup){
delete item.__del;
return true;
}
return filterMethod(this.state.filterValue, item, index, prop);
}
arr = arr.filter(filterData);
for(let i = 0; i < arr.length - 1; i++){
let a = arr[i];
let b = arr[i + 1];
if(a[optgroup] && b[optgroup]){
arr[i].__del = true;
}
}
if(arr.length && arr[arr.length - 1][optgroup]){
arr[arr.length - 1].__del = true;
}
arr = arr.filter(item => !item.__del);
//创建条目
creator = this.state.filterValue && isFunction(create);
}
}
const search = (
<div class='xm-search'>
<i class="xm-iconfont xm-icon-sousuo"></i>
<input type="text" class="xm-input xm-search-input" placeholder={ searchTips }
ref={ input => this.searchInputRef = input }
onClick={ this.blockClick.bind(this) }
onInput={ this.searchInput.bind(this) }
onCompositionStart={ this.handleComposition.bind(this) }
onCompositionUpdate={ this.handleComposition.bind(this) }
onCompositionEnd={ this.handleComposition.bind(this) }
/>
</div>
);
//如果是分组模式, 要分页先去除分组, 然后在计算分页, 最后再加上分组
let groups = [], groupInfo = {};
groups = arr.filter(item => item[optgroup]).forEach(g => {
g[children].forEach(item => groupInfo[item[value]] = g);
});
arr = arr.filter(item => !item[optgroup]);
let paging = '';
if(config.paging){
//计算当前分页的总页码
let size = Math.floor((arr.length - 1) / config.pageSize) + 1;
size <= 0 && (size = 1);
let pageIndex = this.state.pageIndex;
//如果当前页码大于总页码, 重置一下
if(pageIndex > size){
pageIndex = size;
}
//如有总页码>1, 但是因为搜索造成的页码=0的情况
if(size > 0 && pageIndex <= 0){
pageIndex = 1;
}
//实现简单的物理分页
let start = (pageIndex - 1) * config.pageSize;
let end = start + config.pageSize;
arr = arr.slice(start, end);
const disabledStyle = {cursor: 'no-drop', color: '#d2d2d2'};
let prevStyle = {}, nextStyle = {};
pageIndex <= 1 && (prevStyle = disabledStyle);
pageIndex == size && (nextStyle = disabledStyle);
// const defaultCurrClass = {
// position: 'relative',
// borderRadius: '1px',
// }
// {
// ''.padEnd(size, ' ').split('').map((s, i) => (
// <span style={
// this.state.pageIndex == i + 1 ? {
// ...defaultCurrClass,
// backgroundColor: theme.color,
// borderColor: theme.color,
// color: '#FFF',
// } : defaultCurrClass
// }>{ i + 1 }</span>
// ))
// }
this.state.pageIndex !== pageIndex && this.changePageIndex(pageIndex);
paging = (
<div class='xm-paging'>
<span style={ prevStyle } onClick={ this.pagePrevClick.bind(this) }>上一页</span>
<span>{ this.state.pageIndex } / { size }</span>
<span style={ nextStyle } onClick={ e => this.pageNextClick.bind(this, e, size)() }>下一页</span>
</div>
)
}else{
//检查是否设置了显示数量上限
if(config.showCount > 0){
arr = arr.slice(0, config.showCount);
}
}
let newArr = [], group;
arr.forEach(item => {
let g = groupInfo[item[value]];
if(g != group){
group = g;
newArr.push(group);
}
newArr.push(item);
});
arr = newArr;
//查看是否创建了条目
if(creator){
creator = create(this.state.filterValue, deepMerge([], arr));
creator && arr.splice(0, 0, creator);
}
let safetyArr = deepMerge([], arr);
this.tempData = safetyArr;
//工具条操作
const toolbar = (
<div class='xm-toolbar'>
{ config.toolbar.list.map(tool => {
const toolClass = 'toolbar-tag';
const toolStyle = {};
let info, name = config.languageProp.toolbar[tool];
if(tool === 'ALL'){
info = { icon: 'xm-iconfont xm-icon-quanxuan', name, method: (pageData) => {
const { optgroup, disabled } = prop;
const list = pageData.filter(item => !item[optgroup]).filter(item => !item[disabled])
this.props.onReset(mergeArr(list, sels, prop), 'sels');
} };
}else if(tool === 'CLEAR'){
info = { icon: 'xm-iconfont xm-icon-qingkong', name, method: (pageData) => {
this.props.onReset(sels.filter(item => item[prop.disabled]), 'sels');
} };
}else if(tool === 'REVERSE'){
info = { icon: 'xm-iconfont xm-icon-fanxuan', name, method: (pageData) => {
const { optgroup, disabled } = prop;
const list = pageData.filter(item => !item[optgroup]).filter(item => !item[disabled])
let selectedList = [];
sels.forEach(item => {
let index = list.findIndex(pageItem => pageItem[value] === item[value]);
if(index == -1){
selectedList.push(item);
}else{
list.splice(index, 1);
}
})
this.props.onReset(mergeArr(list, selectedList, prop), 'sels');
} };
}else if(tool === 'SEARCH'){
toolStyle.color = theme.color;
info = { icon: 'xm-iconfont xm-icon-sousuo', name, method: (pageData) => {
} };
}else {
info = tool
}
const hoverChange = e => {
if(e.type === 'mouseenter') e.target.style.color = theme.color;
if(e.type === 'mouseleave') e.target.style.color = '';
}
return (<div class={ toolClass } style={ toolStyle } onClick={ () => {
isFunction(info.method) && info.method(safetyArr)
} } onMouseEnter={ hoverChange } onMouseLeave={ hoverChange }>
{ config.toolbar.showIcon && <i class={ info.icon }></i> }
<span>{ info.name }</span>
</div>)
}).filter(a => a) }
</div>
)
const showIcon = config.model.icon != 'hidden';
const renderItem = item => {
const selected = !!sels.find(sel => sel[value] == item[value])
const iconStyle = selected ? {
color: theme.color,
border: 'none'
} : {
borderColor: theme.color,
};
const itemStyle = {}
if(!showIcon && selected){
itemStyle.backgroundColor = theme.color;
item[disabled] && (itemStyle.backgroundColor = '#C2C2C2');
}
const className = ['xm-option', (item[disabled] ? ' disabled' : ''), (selected ? ' selected' : ''), (showIcon ? 'show-icon' : 'hide-icon') ].join(' ');
const iconClass = ['xm-option-icon xm-iconfont', radio ? 'xm-icon-danx' : 'xm-icon-duox'].join(' ');
return (
<div class={ className } style={ itemStyle } value={ item[value] } onClick={ this.optionClick.bind(this, item, selected, item[disabled]) }>
{ showIcon && <i class={ iconClass } style={ iconStyle }></i> }
<div class='xm-option-content' dangerouslySetInnerHTML={{ __html: template({ data, item, arr: sels, name: item[name], value: item[value] }) }}></div>
</div>
)
}
const renderGroup = item => {
const isGroup = item[optgroup];
if(isGroup){//分组模式
return (
<div class="xm-group">
<div class="xm-group-item" onClick={ this.groupClick.bind(this, item) }>{ item[name] }</div>
</div>
)
}
return renderItem(item);
}
arr = arr.map(renderGroup);
if(!arr.length){
//查看无数据情况下是否显示分页
!config.pageEmptyShow && (paging = '');
arr.push(<div class="xm-select-empty">{ empty }</div>)
}
return (
<div onClick={ this.blockClick }>
<div>
{ config.toolbar.show && toolbar }
{ filterable && search }
<div class="scroll-body" style={ {maxHeight: config.height} }>{ arr }</div>
{ config.paging && paging }
</div>
{ this.state.loading && <div class="loading" >
<span class="loader"></span>
</div> }
</div>
)
}
}
export default General;

View File

@ -1,20 +0,0 @@
import { h, Component, render } from '@/components/preact'
/**
* 默认提示
*/
class Tips extends Component{
constructor(options){
super(options);
}
render({ tips, show }) {
const tipsClass = show ? 'xm-tips' : 'xm-tips dis';
return (
<div class={ tipsClass }>{ tips }</div>
)
}
}
export default Tips;

View File

@ -0,0 +1,384 @@
import { h, Component, render } from 'preact'
import { datas, childData } from '@/index.js';
import { checkUserAgent, isFunction, isArray, toNum, mergeArr } from '@/common/util'
import Label from '../label';
import General from '../plugin/general';
import Custom from '../plugin/custom';
import Tree from '../plugin/tree';
/**
* 框架渲染类, 渲染基础的外边框 + 属性变化监听
*/
class Framework extends Component{
constructor(options){
super(options);
//保留对象引用
childData[options.el] = this;
//初始化state数据
this.state = this.initState();
this.bodyView = null;
}
initState(){
return {
data: [],
dataObj: {},
flatData: [],
sels: [],
show: false,
tmpColor: '',
}
}
init(props, refresh){
let { data } = props;
//如果新数据和旧数据不同 或者 强制刷新 才进行数据处理
if(refresh){
let dataObj = {};
let flatData = [];
this.load(data, dataObj, flatData);
let sels = props.initValue ? this.exchangeValue(props.initValue) : Object.values(dataObj).filter(item => item[props.prop.selected] === true).filter(item => item[this.props.prop.optgroup] !== true)
this.setState({ sels, dataObj, flatData });
}
this.setState({ data });
}
exchangeValue(arr){
return arr.map(sel => typeof sel === 'object' ? sel : this.state.dataObj[sel]).filter(a => a).filter(item => item[this.props.prop.optgroup] !== true)
}
value(sels, show, listenOn){
if(show !== false && show !== true){
show = this.state.show;
}
let changeData = this.exchangeValue(sels);
this.resetSelectValue(changeData, changeData, true, listenOn);
this.setState({ show })
}
load(data, dataObj, flatData, parent){
const { children, optgroup, value, selected, disabled } = this.props.prop;
data.forEach(item => {
//数据提取/处理
item.__node = { parent }
dataObj[item[value]] = item;
flatData.push(item);
//遍历子级数据
let child = item[children];
if(child && isArray(child)){
item[optgroup] = true;
this.load(child, dataObj, flatData, item);
if(item[selected] === true){
delete item[selected]
child.forEach(c => c[selected] = true)
}
if(item[disabled] === true){
delete item[disabled]
child.forEach(c => c[disabled] = true)
}
let len = child.length;
if(len > 0){
//检查子节点的数据是否都被选中
let slen = child.filter(i => i[selected] === true || i.__node.selected === true).length;
item.__node.selected = slen === len;
item.__node.half = slen > 0 && slen < len;
item.__node.disabled = child.filter(i => i[disabled] === true || i.__node.disabled === true).length === len;
}
}
});
}
//重置已选择数据
resetSelectValue(sels = [], change = [], isAdd, listenOn = true){
let on = this.props.on;
if(isFunction(on) && this.prepare && listenOn){
on({ arr: sels, change, isAdd });
}
this.setState({ sels });
}
updateBorderColor(tmpColor){
this.setState({ tmpColor });
}
treeHandler(sels, parent, change, type){
const { value, selected, disabled, children, optgroup } = this.props.prop;
let child = parent[children];
child.filter(item => !(item[disabled] || item.__node.disabled)).forEach(item => {
if(item[optgroup]){
this.treeHandler(sels, item, change, type);
}else{
let index = sels.findIndex(sel => sel[value] == item[value])
if(type === 'del'){
if(index != -1){
sels.splice(index, 1);
change.push(item);
}
}else if(type === 'half' || type === 'add'){
if(index == -1){
sels.push(item);
change.push(item);
}
}
}
})
let len = child.length;
let slen = child.filter(i => sels.findIndex(sel => sel[value] === i[value]) !== -1 || i.__node.selected === true).length;
parent.__node.selected = slen === len;
parent.__node.half = slen > 0 && slen < len;
}
//选项, 选中状态, 禁用状态, 是否强制删除:在label上点击删除
itemClick(item, itemSelected, itemDisabled, mandatoryDelete){
const { theme, prop, radio, repeat, clickClose, max, maxMethod } = this.props
let { sels } = this.state
const { value, selected, disabled, children, optgroup } = prop
//如果是禁用状态, 不能进行操作
if(itemDisabled) return;
if(item[optgroup]){
let child = item[children], change = [], isAdd = true;
if(item.__node.selected){
this.treeHandler(sels, item, change, 'del');
isAdd = false;
}else if(item.__node.half){
this.treeHandler(sels, item, change, 'half');
}else{
this.treeHandler(sels, item, change, 'add');
}
this.resetSelectValue(sels, change, isAdd);
this.setState({ data: this.state.data })
}else{
//如果现在是选中状态
if(itemSelected && (!repeat || mandatoryDelete)){
let index = sels.findIndex(sel => sel[value] == item[value])
if(index != -1){
sels.splice(index, 1);
this.resetSelectValue(sels, [item], !itemSelected);
}
}else{
//查看是否设置了多选上限
let maxCount = toNum(max);
if(maxCount > 0 && sels.length >= maxCount){
this.updateBorderColor(theme.maxColor);
//查看是否需要回调
maxMethod && isFunction(maxMethod) && maxMethod(sels, item);
return ;
}
//如果是单选模式
if(radio){
sels = [item];
}else{
sels = [...sels, item]
}
this.resetSelectValue(sels, [item], !itemSelected);
}
let parent = item.__node.parent;
if(parent){
while(parent){
let child = parent[children], len = child.length;
let slen = child.filter(i => sels.findIndex(sel => sel[value] === i[value]) !== -1 || i.__node.selected === true).length;
parent.__node.selected = slen === len;
parent.__node.half = slen > 0 && slen < len;
parent = parent.__node.parent;
}
this.setState({ data: this.state.data })
}
}
//检查是否为选择即关闭状态, 强制删除情况下不做处理
clickClose && !mandatoryDelete && this.onClick();
};
//select框被点击
onClick(e){
if(this.props.disabled){
this.state.show !== false && this.setState({ show: false });
return ;
}
let show = !this.state.show;
if(show){
if(this.props.show && this.props.show() == false){
return;
}
//事件互斥原则, 打开一个多选, 关闭其他所有多选
Object.keys(datas).filter(key => key != this.props.el).forEach(el => datas[el].closed())
}else{
if(this.props.hide && this.props.hide() == false){
return;
}
//如果产生滚动条, 关闭下拉后回到顶部
this.bodyView.scroll && this.bodyView.scroll(0, 0);
}
this.setState({ show });
//阻止其他绑定事件的冒泡
e && e.stopPropagation();
}
onReset(data, type){
//重置数据
if(type === 'data'){
let changeData = data.filter(item => item[this.props.prop.selected] === true);
this.resetSelectValue(mergeArr(changeData, this.state.sels, this.props.prop), changeData, true);
let dataObj = {};
let flatData = [];
this.load(data, dataObj, flatData);
this.setState({ data, flatData });
}else
//重置选中数据
if(type === 'sels'){
this.resetSelectValue(data, data, true);
}else
//追加数据
if(type === 'append'){
this.append(data);
}else
//清理数据
if(type === 'delete'){
this.del(data);
}else
//自动判断模式
if(type === 'auto'){
this.auto(data);
}
}
append(arr){
let changeData = this.exchangeValue(arr);
this.resetSelectValue(mergeArr(changeData, this.state.sels, this.props.prop), changeData, true);
}
del(arr){
let value = this.props.prop.value;
let sels = this.state.sels;
arr = this.exchangeValue(arr);
arr.forEach(v => {
let index = sels.findIndex(item => item[value] === v[value]);
if(index != -1){
sels.splice(index, 1);
}
});
this.resetSelectValue(sels, arr, false);
}
auto(arr){
let value = this.props.prop.value;
let sels = arr.filter(v => this.state.sels.findIndex(item => item[value] === v[value]) != -1);
sels.length == arr.length ? this.del(arr) : this.append(arr);
}
//组件将要接收新属性
componentWillReceiveProps(props){
this.init(props, props.updateData);
}
//组件将要被挂载
componentWillMount(){
this.init(this.props, true);
}
render(config, state) {
const { theme, prop, radio, repeat, clickClose, on, max, maxMethod, content, disabled, tree } = config;
const borderStyle = { borderColor: theme.color };
let { data, dataObj, flatData, sels, show, tmpColor } = state;
//组件为禁用状态
if(disabled){
show = false;
}
//最外层边框的属性
const xmSelectProps = {
style: { ...config.style, ...(show ? borderStyle : {}) },
onClick: this.onClick.bind(this),
ua: checkUserAgent(),
size: config.size,
}
if(tmpColor){
xmSelectProps.style.borderColor = tmpColor;
setTimeout(() => {
xmSelectProps.style.borderColor = '';
this.updateBorderColor('');
}, 300);
}
//普通多选数据
const valueProp = prop.value;
const labelProps = { ...config, data, sels, ck: this.itemClick.bind(this), title: sels.map(sel => sel[prop.name]).join(',') }
const bodyProps = { ...config, data, dataObj, flatData, sels, ck: this.itemClick.bind(this), show, onReset: this.onReset.bind(this) }
//渲染组件
let Body = content ? <Custom { ...bodyProps } /> : tree.show ? <Tree { ...bodyProps } /> : <General { ...bodyProps } />;
return (
<xm-select { ...xmSelectProps } >
<input class="xm-select-default" name={ config.name } value={ sels.map(item => item[prop.value]).join(',') }></input>
<i class={ show ? 'xm-icon xm-icon-expand' : 'xm-icon' } />
{ sels.length === 0 && <div class="xm-tips">{ config.tips }</div> }
<Label { ...labelProps } />
<div class={ show ? 'xm-body' : 'xm-body dis' } ref={ ref => this.bodyView = ref}>
{ Body }
</div>
{ disabled && <div class="xm-select-disabled"></div> }
</xm-select>
);
}
//组件完成挂载
componentDidMount(){
this.prepare = true;
}
//此时页面又被重新渲染了
componentDidUpdate(){
let { direction } = this.props;
let rect = this.base.getBoundingClientRect();
if(direction === 'auto'){
//用于控制js获取下拉框的高度
this.bodyView.style.display = 'block';
this.bodyView.style.visibility = 'hidden';
//获取下拉元素的高度
let bodyViewRect = this.bodyView.getBoundingClientRect();
let bodyViewHeight = bodyViewRect.height;
//还原控制效果
this.bodyView.style.display = '';
this.bodyView.style.visibility = '';
//确定下拉框是朝上还是朝下
let y = rect.y || rect.top || 0;
let clientHeight = document.documentElement.clientHeight;
let diff = clientHeight - y - rect.height - 20;
direction = diff > bodyViewHeight || y < diff ? 'down' : 'up';
}
if(direction == 'down'){
this.bodyView.style.top = rect.height + 4 + 'px';
this.bodyView.style.bottom = 'auto';
}else{
this.bodyView.style.top = 'auto';
this.bodyView.style.bottom = rect.height + 4 + 'px';
}
}
}
export default Framework;

View File

@ -1,4 +1,4 @@
import { h, Component, render } from '@/components/preact' import { h, Component, render } from 'preact'
/** /**
* 标签的渲染 * 标签的渲染
@ -15,31 +15,31 @@ class Label extends Component{
e.stopPropagation(); e.stopPropagation();
} }
scrollFunc(e){ scrollFunc(e){
if(e.wheelDeltaX == 0){ if(e.wheelDeltaX == 0){
let child = this.labelRef.getElementsByClassName('xm-label-block'); let child = this.labelRef.getElementsByClassName('xm-label-block');
let sum = 10; let sum = 10;
for(let i = 0; i < child.length; i++){ for(let i = 0; i < child.length; i++){
sum += child[i].getBoundingClientRect().width + 5; sum += child[i].getBoundingClientRect().width + 5;
} }
let width = this.labelRef.getBoundingClientRect().width; let width = this.labelRef.getBoundingClientRect().width;
let max = sum > width ? sum - width : width; let max = sum > width ? sum - width : width;
let left = this.labelRef.scrollLeft + e.deltaY; let left = this.labelRef.scrollLeft + e.deltaY;
left < 0 && (left = 0); left < 0 && (left = 0);
left > max && (left = max); left > max && (left = max);
this.labelRef.scrollLeft = left; this.labelRef.scrollLeft = left;
} }
} }
componentDidMount(){ componentDidMount(){
if (this.labelRef.addEventListener) { if (this.labelRef.addEventListener) {
this.labelRef.addEventListener('DOMMouseScroll', this.scrollFunc.bind(this), false); this.labelRef.addEventListener('DOMMouseScroll', this.scrollFunc.bind(this), false);
} }
if(this.labelRef.attachEvent){ if(this.labelRef.attachEvent){
this.labelRef.attachEvent('onmousewheel', this.scrollFunc.bind(this)); this.labelRef.attachEvent('onmousewheel', this.scrollFunc.bind(this));
} }
this.labelRef.onmousewheel = this.scrollFunc.bind(this); this.labelRef.onmousewheel = this.scrollFunc.bind(this);
} }
render(config) { render(config) {
const { data, prop, theme, model, sels, autoRow } = config; const { data, prop, theme, model, sels, autoRow } = config;
@ -52,12 +52,12 @@ class Label extends Component{
//渲染结果 //渲染结果
let html = ''; let html = '';
let innerHTML = true; let innerHTML = true;
if(type === 'text'){ if(type === 'text'){
html = sels.map(sel => `${conf.left}${sel[name]}${conf.right}`).join(conf.separator) html = sels.map(sel => `${conf.left}${sel[name]}${conf.right}`).join(conf.separator)
}else if(type === 'block'){ }else if(type === 'block'){
innerHTML = false; innerHTML = false;
//已选择的数据 //已选择的数据
let arr = [...sels]; let arr = [...sels];
@ -92,14 +92,14 @@ class Label extends Component{
} }
} }
const className = ['xm-label', autoRow ? 'auto-row' : 'single-row'].join(' '); const className = ['xm-label', autoRow ? 'auto-row' : 'single-row'].join(' ');
return ( return (
<div class={ className }> <div class={ className }>
<div class="scroll" ref={ ref => this.labelRef = ref }> <div class="scroll" ref={ ref => this.labelRef = ref }>
{ innerHTML ? { innerHTML ?
<div class="label-content" dangerouslySetInnerHTML={{__html: html}}></div> : <div class="label-content" dangerouslySetInnerHTML={{__html: html}}></div> :
<div class="label-content">{ html }</div> <div class="label-content">{ html }</div>
} }
</div> </div>
</div> </div>
) )

View File

@ -0,0 +1,32 @@
import { h, Component, render } from 'preact'
/**
* 默认提示
*/
class Custom extends Component{
constructor(options){
super(options);
}
blockClick(e){
e.stopPropagation();
}
shouldComponentUpdate(){
return !this.prepare;
}
render(config) {
this.prepare = true;
return (
<div onClick={ this.blockClick } class="xm-body-custom" >
<div class="scroll-body" style={ {maxHeight: config.height} }>
<div style="margin: 5px 0" dangerouslySetInnerHTML={{ __html: config.content }}></div>
</div>
</div>
)
}
}
export default Custom;

View File

@ -0,0 +1,412 @@
import { h, Component, render } from 'preact'
import { isFunction, isArray, safety, deepMerge, mergeArr, IEVersion } from '@/common/util'
/**
* 普通的多选渲染
*/
class General extends Component{
constructor(options){
super(options);
this.setState({
filterValue: '',
remote: true,
loading: false,
pageIndex: 1,
pageSize: 10,
});
this.searchCid = 0;
this.inputOver = true;
this.__value = '';
this.dynamicInput = false;
}
optionClick(item, selected, disabled, e){
this.props.ck(item, selected, disabled);
//阻止父组件上的事件冒泡
this.blockClick(e);
}
groupClick(item, e){
const { click, children, disabled } = this.props.prop;
let m = item[click], arr = item[children].filter(opt => !opt[disabled]);
if(m === 'SELECT'){
this.props.onReset(arr, 'append');
}else if(m === 'CLEAR'){
this.props.onReset(arr, 'delete');
}else if(m === 'AUTO'){
this.props.onReset(arr, 'auto');
}else if(isFunction(m)){
m(item);
}
//阻止父组件上的事件冒泡
this.blockClick(e);
}
blockClick(e){
e.stopPropagation();
}
pagePrevClick(e){
let index = this.state.pageIndex;
if(index <= 1){
return ;
}
this.changePageIndex(index - 1);
}
pageNextClick(e, size){
let index = this.state.pageIndex;
if(index >= size){
return ;
}
this.changePageIndex(index + 1);
}
changePageIndex(index){
this.setState({
pageIndex: index
})
}
searchInput(e){
let v = e.target.value;
if(v === this.__value){
return ;
}
clearTimeout(this.searchCid);
if(this.inputOver){
//保证输入框内的值是实时的
this.__value = v;
//让搜索变成异步的
this.searchCid = setTimeout(() => {
this.callback = true;
this.setState({ filterValue: this.__value, remote: true })
}, this.props.delay);
}
}
focus(){
this.searchInputRef && this.searchInputRef.focus();
}
blur(){
this.searchInputRef && this.searchInputRef.blur();
}
handleComposition(e){
let type = e.type;
if(type === 'compositionstart'){
this.inputOver = false;
clearTimeout(this.searchCid);
}else if(type === 'compositionend'){
this.inputOver = true;
this.searchInput(e);
}
}
componentWillReceiveProps(props){
if(this.props.show != props.show){
if(!props.show){
//清空输入框的值
this.setState({ filterValue: '' });
this.__value = '';
this.searchInputRef && (this.searchInputRef.value = '');
}else{
//聚焦输入框
setTimeout(() => this.focus(), 0);
}
}
}
componentDidUpdate(){
if(this.callback){
this.callback = false;
let done = this.props.filterDone;
if(isFunction(done)){
done(this.state.filterValue, this.tempData || []);
}
}
}
render(config) {
let { data, flatData, prop, template, theme, radio, sels, empty, filterable, filterMethod, remoteSearch, remoteMethod, delay, searchTips, create } = config
const { name, value, disabled, children, optgroup } = prop;
let arr = deepMerge([], flatData), creator;
//是否开启了搜索
if(filterable){
if(remoteSearch){//是否进行远程搜索
if(this.state.remote){
this.callback = false;
this.setState({ loading: true, remote: false });
//让输入框失去焦点
this.blur();
remoteMethod(this.state.filterValue, result => {
//回调后可以重新聚焦
this.focus();
this.callback = true;
this.setState({ loading: false });
this.props.onReset(result, 'data');
}, this.props.show);
}
}else{
const filterData = (item, index) => {
const isGroup = item[optgroup];
if(isGroup){
delete item.__del;
return true;
}
return filterMethod(this.state.filterValue, item, index, prop);
}
arr = arr.filter(filterData);
for(let i = 0; i < arr.length - 1; i++){
let a = arr[i];
let b = arr[i + 1];
if(a[optgroup] && b[optgroup]){
arr[i].__del = true;
}
}
if(arr.length && arr[arr.length - 1][optgroup]){
arr[arr.length - 1].__del = true;
}
arr = arr.filter(item => !item.__del);
//创建条目
creator = this.state.filterValue && isFunction(create);
}
}
const search = (
<div class='xm-search'>
<i class="xm-iconfont xm-icon-sousuo"></i>
<input type="text" class="xm-input xm-search-input" placeholder={ searchTips }
ref={ input => this.searchInputRef = input }
onClick={ this.blockClick.bind(this) }
onInput={ this.searchInput.bind(this) }
onCompositionStart={ this.handleComposition.bind(this) }
onCompositionUpdate={ this.handleComposition.bind(this) }
onCompositionEnd={ this.handleComposition.bind(this) }
/>
</div>
);
//如果是分组模式, 要分页先去除分组, 然后在计算分页, 最后再加上分组
let groups = [], groupInfo = {};
groups = arr.filter(item => item[optgroup]).forEach(g => {
g[children].forEach(item => groupInfo[item[value]] = g);
});
arr = arr.filter(item => !item[optgroup]);
let paging = '';
if(config.paging){
//计算当前分页的总页码
let size = Math.floor((arr.length - 1) / config.pageSize) + 1;
size <= 0 && (size = 1);
let pageIndex = this.state.pageIndex;
//如果当前页码大于总页码, 重置一下
if(pageIndex > size){
pageIndex = size;
}
//如有总页码>1, 但是因为搜索造成的页码=0的情况
if(size > 0 && pageIndex <= 0){
pageIndex = 1;
}
//实现简单的物理分页
let start = (pageIndex - 1) * config.pageSize;
let end = start + config.pageSize;
arr = arr.slice(start, end);
const disabledStyle = {cursor: 'no-drop', color: '#d2d2d2'};
let prevStyle = {}, nextStyle = {};
pageIndex <= 1 && (prevStyle = disabledStyle);
pageIndex == size && (nextStyle = disabledStyle);
// const defaultCurrClass = {
// position: 'relative',
// borderRadius: '1px',
// }
// {
// ''.padEnd(size, ' ').split('').map((s, i) => (
// <span style={
// this.state.pageIndex == i + 1 ? {
// ...defaultCurrClass,
// backgroundColor: theme.color,
// borderColor: theme.color,
// color: '#FFF',
// } : defaultCurrClass
// }>{ i + 1 }</span>
// ))
// }
this.state.pageIndex !== pageIndex && this.changePageIndex(pageIndex);
paging = (
<div class='xm-paging'>
<span style={ prevStyle } onClick={ this.pagePrevClick.bind(this) }>上一页</span>
<span>{ this.state.pageIndex } / { size }</span>
<span style={ nextStyle } onClick={ e => this.pageNextClick.bind(this, e, size)() }>下一页</span>
</div>
)
}else{
//检查是否设置了显示数量上限
if(config.showCount > 0){
arr = arr.slice(0, config.showCount);
}
}
let newArr = [], group;
arr.forEach(item => {
let g = groupInfo[item[value]];
if(g != group){
group = g;
newArr.push(group);
}
newArr.push(item);
});
arr = newArr;
//查看是否创建了条目
if(creator){
creator = create(this.state.filterValue, deepMerge([], arr));
creator && arr.splice(0, 0, creator);
}
let safetyArr = deepMerge([], arr);
this.tempData = safetyArr;
//工具条操作
const toolbar = (
<div class='xm-toolbar'>
{ config.toolbar.list.map(tool => {
const toolClass = 'toolbar-tag';
const toolStyle = {};
let info, name = config.languageProp.toolbar[tool];
if(tool === 'ALL'){
info = { icon: 'xm-iconfont xm-icon-quanxuan', name, method: (pageData) => {
const { optgroup, disabled } = prop;
const list = pageData.filter(item => !item[optgroup]).filter(item => !item[disabled])
this.props.onReset(mergeArr(list, sels, prop), 'sels');
} };
}else if(tool === 'CLEAR'){
info = { icon: 'xm-iconfont xm-icon-qingkong', name, method: (pageData) => {
this.props.onReset(sels.filter(item => item[prop.disabled]), 'sels');
} };
}else if(tool === 'REVERSE'){
info = { icon: 'xm-iconfont xm-icon-fanxuan', name, method: (pageData) => {
const { optgroup, disabled } = prop;
const list = pageData.filter(item => !item[optgroup]).filter(item => !item[disabled])
let selectedList = [];
sels.forEach(item => {
let index = list.findIndex(pageItem => pageItem[value] === item[value]);
if(index == -1){
selectedList.push(item);
}else{
list.splice(index, 1);
}
})
this.props.onReset(mergeArr(list, selectedList, prop), 'sels');
} };
}else if(tool === 'SEARCH'){
toolStyle.color = theme.color;
info = { icon: 'xm-iconfont xm-icon-sousuo', name, method: (pageData) => {
} };
}else {
info = tool
}
const hoverChange = e => {
if(e.type === 'mouseenter') e.target.style.color = theme.color;
if(e.type === 'mouseleave') e.target.style.color = '';
}
return (<div class={ toolClass } style={ toolStyle } onClick={ () => {
isFunction(info.method) && info.method(safetyArr)
} } onMouseEnter={ hoverChange } onMouseLeave={ hoverChange }>
{ config.toolbar.showIcon && <i class={ info.icon }></i> }
<span>{ info.name }</span>
</div>)
}).filter(a => a) }
</div>
)
const showIcon = config.model.icon != 'hidden';
const renderItem = item => {
const selected = !!sels.find(sel => sel[value] == item[value])
const iconStyle = selected ? {
color: theme.color,
border: 'none'
} : {
borderColor: theme.color,
};
const itemStyle = {}
if(!showIcon && selected){
itemStyle.backgroundColor = theme.color;
item[disabled] && (itemStyle.backgroundColor = '#C2C2C2');
}
const className = ['xm-option', (item[disabled] ? ' disabled' : ''), (selected ? ' selected' : ''), (showIcon ? 'show-icon' : 'hide-icon') ].join(' ');
const iconClass = ['xm-option-icon xm-iconfont', radio ? 'xm-icon-danx' : 'xm-icon-duox'].join(' ');
return (
<div class={ className } style={ itemStyle } value={ item[value] } onClick={ this.optionClick.bind(this, item, selected, item[disabled]) }>
{ showIcon && <i class={ iconClass } style={ iconStyle }></i> }
<div class='xm-option-content' dangerouslySetInnerHTML={{ __html: template({ data, item, arr: sels, name: item[name], value: item[value] }) }}></div>
</div>
)
}
const renderGroup = item => {
const isGroup = item[optgroup];
if(isGroup){//分组模式
return (
<div class="xm-group">
<div class="xm-group-item" onClick={ this.groupClick.bind(this, item) }>{ item[name] }</div>
</div>
)
}
return renderItem(item);
}
arr = arr.map(renderGroup);
if(!arr.length){
//查看无数据情况下是否显示分页
!config.pageEmptyShow && (paging = '');
arr.push(<div class="xm-select-empty">{ empty }</div>)
}
return (
<div onClick={ this.blockClick }>
<div>
{ config.toolbar.show && toolbar }
{ filterable && search }
<div class="scroll-body" style={ {maxHeight: config.height} }>{ arr }</div>
{ config.paging && paging }
</div>
{ this.state.loading && <div class="loading" >
<span class="loader"></span>
</div> }
</div>
)
}
}
export default General;

View File

@ -0,0 +1,124 @@
import { h, Component, render } from 'preact'
class Tree extends Component{
constructor(options){
super(options);
this.state = {
expandedKeys: [],
}
}
init(props){
const { tree, dataObj, prop } = props;
const { value } = prop
let keys = [];
tree.expandedKeys.forEach(key => {
keys.push(key);
let item = dataObj[key];
while(item){
let pkey = item[value];
keys.findIndex(k => k === pkey) === -1 && (keys.push(pkey))
item = item.__node.parent
}
});
this.setState({ expandedKeys: keys })
}
blockClick(e){
e.stopPropagation();
}
optionClick(item, selected, disabled, type, e){
if(type === 'line'){
let val = item[this.props.prop.value];
let expandedKeys = this.state.expandedKeys;
let index = expandedKeys.findIndex(v => v === val);
index === -1 ? expandedKeys.push(val) : expandedKeys.splice(index, 1);
this.setState({ expandedKeys });
}else if(type === 'checkbox'){
this.props.ck(item, selected, disabled);
}
//阻止父组件上的事件冒泡
this.blockClick(e);
}
//组件将要接收新属性
componentWillReceiveProps(props){
// this.init(props);
}
//组件将要被挂载
componentWillMount(){
this.init(this.props);
}
render(config, { expandedKeys }) {
let { prop, empty, sels, theme, radio, template, data, tree } = config;
let { name, value, disabled, children } = prop;
const showIcon = config.model.icon != 'hidden';
const renderItem = (item, indent, expand) => {
const half = item.__node.half === true;
const selected = !!sels.find(sel => sel[value] == item[value]) || half || item.__node.selected
const dis = item[disabled] || item.__node.disabled;
const iconStyle = selected || half ? {
color: theme.color,
border: 'none'
} : {
borderColor: theme.color,
};
const itemStyle = { paddingLeft: indent + 'px' }
if(!showIcon && selected){
itemStyle.backgroundColor = theme.color;
dis && (itemStyle.backgroundColor = '#C2C2C2');
}
const className = ['xm-option', (dis ? ' disabled' : ''), (selected ? ' selected' : ''), (showIcon ? 'show-icon' : 'hide-icon') ].join(' ');
const iconClass = ['xm-option-icon xm-iconfont', radio ? 'xm-icon-danx' : half ? 'xm-icon-banxuan' : 'xm-icon-duox'].join(' ');
const treeIconClass = ['xm-tree-icon', expand ? 'expand':'', item[children] && item[children].length > 0 ? 'visible':'hidden'].join(' ');
return (
<div class={ className } style={ itemStyle } value={ item[value] } onClick={ this.optionClick.bind(this, item, selected, item[disabled], 'line') }>
{ tree.showFolderIcon && <i class={ treeIconClass }></i> }
{ tree.showFolderIcon && tree.showLine && <i class={ expand ? 'top-line expand' : 'top-line' } style={ { left: indent - tree.indent + 3 + 'px', width: tree.indent + (expand === 0 ? 10 : -2) + 'px' } }></i> }
{ showIcon && <i class={ iconClass } style={ iconStyle } onClick={ this.optionClick.bind(this, item, selected, item[disabled], 'checkbox') }></i> }
<div class='xm-option-content' dangerouslySetInnerHTML={{ __html: template({ data, item, arr: sels, name: item[name], value: item[value] }) }}></div>
</div>
)
}
const renderGroup = (item, indent) => {
const child = item[children];
indent = indent + tree.indent
if(child && child.length > 0){//分组模式
let expand = this.state.expandedKeys.findIndex(k => item[value] === k) !== -1;
return (
<div class="xm-tree">
{ tree.showFolderIcon && tree.showLine && <i class={ expand ? 'left-line expand' : 'left-line' } style={ {left: indent + 3 + 'px'} }></i> }
{ renderItem(item, indent, expand) }
{ expand && <div class="xm-tree-box">{ child.map(c => renderGroup(c, indent)) }</div> }
</div>
)
}
return renderItem(item, indent, 0);
}
let arr = data.map(item => renderGroup(item, 10 - tree.indent));
if(!arr.length){
//查看无数据情况下是否显示分页
arr.push(<div class="xm-select-empty">{ empty }</div>)
}
return (
<div onClick={ this.blockClick } class="xm-body-tree" >
<div class="scroll-body" style={ {maxHeight: config.height} }>{ arr }</div>
</div>
)
}
}
export default Tree;

View File

@ -1,311 +0,0 @@
var e = function() {},
t = {},
n = [],
o = [];
function r(t, r) {
var i, l, a, s, p = arguments,
u = o;
for (s = arguments.length; s-- > 2;) n.push(p[s]);
for (r && null != r.children && (n.length || n.push(r.children), delete r.children); n.length;)
if ((l = n.pop()) && void 0 !== l.pop)
for (s = l.length; s--;) n.push(l[s]);
else "boolean" == typeof l && (l = null), (a = "function" != typeof t) && (null == l ? l = "" : "number" == typeof l ?
l = String(l) : "string" != typeof l && (a = !1)), a && i ? u[u.length - 1] += l : u === o ? u = [l] : u.push(l), i =
a;
var c = new e;
return c.nodeName = t, c.children = u, c.attributes = null == r ? void 0 : r, c.key = null == r ? void 0 : r.key, c
}
function i(e, t) {
for (var n in t) e[n] = t[n];
return e
}
function l(e, t) {
null != e && ("function" == typeof e ? e(t) : e.current = t)
}
var a = "function" == typeof Promise ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout,
s = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,
p = [];
function u(e) {
!e._dirty && (e._dirty = !0) && 1 == p.push(e) && a(c)
}
function c() {
for (var e; e = p.pop();) e._dirty && U(e)
}
function f(e, t) {
return e.normalizedNodeName === t || e.nodeName.toLowerCase() === t.toLowerCase()
}
function d(e) {
var t = i({}, e.attributes);
t.children = e.children;
var n = e.nodeName.defaultProps;
if (void 0 !== n)
for (var o in n) void 0 === t[o] && (t[o] = n[o]);
return t
}
function v(e) {
var t = e.parentNode;
t && t.removeChild(e)
}
function h(e, t, n, o, r) {
if ("className" === t && (t = "class"), "key" === t);
else if ("ref" === t) l(n, null), l(o, e);
else if ("class" !== t || r)
if ("style" === t) {
if (o && "string" != typeof o && "string" != typeof n || (e.style.cssText = o || ""), o && "object" == typeof o) {
if ("string" != typeof n)
for (var i in n) i in o || (e.style[i] = "");
for (var i in o) e.style[i] = "number" == typeof o[i] && !1 === s.test(i) ? o[i] + "px" : o[i]
}
} else if ("dangerouslySetInnerHTML" === t) o && (e.innerHTML = o.__html || "");
else if ("o" == t[0] && "n" == t[1]) {
var a = t !== (t = t.replace(/Capture$/, ""));
t = t.toLowerCase().substring(2), o ? n || e.addEventListener(t, m, a) : e.removeEventListener(t, m, a), (e._listeners ||
(e._listeners = {}))[t] = o
} else if ("list" !== t && "type" !== t && !r && t in e) {
try {
e[t] = null == o ? "" : o
} catch (e) {}
null != o && !1 !== o || "spellcheck" == t || e.removeAttribute(t)
} else {
var p = r && t !== (t = t.replace(/^xlink:?/, ""));
null == o || !1 === o ? p ? e.removeAttributeNS("http://www.w3.org/1999/xlink", t.toLowerCase()) : e.removeAttribute(
t) : "function" != typeof o && (p ? e.setAttributeNS("http://www.w3.org/1999/xlink", t.toLowerCase(), o) : e.setAttribute(
t, o))
} else e.className = o || ""
}
function m(e) {
return this._listeners[e.type](e)
}
var _ = [],
y = 0,
g = !1,
b = !1;
function C() {
for (var e; e = _.shift();) e.componentDidMount && e.componentDidMount()
}
function x(e, t, n, o, r, i) {
y++ || (g = null != r && void 0 !== r.ownerSVGElement, b = null != e && !("__preactattr_" in e));
var l = function e(t, n, o, r, i) {
var l = t,
a = g;
if (null != n && "boolean" != typeof n || (n = ""), "string" == typeof n || "number" == typeof n) return t && void 0 !==
t.splitText && t.parentNode && (!t._component || i) ? t.nodeValue != n && (t.nodeValue = n) : (l = document.createTextNode(
n), t && (t.parentNode && t.parentNode.replaceChild(l, t), N(t, !0))), l.__preactattr_ = !0, l;
var s, p, u = n.nodeName;
if ("function" == typeof u) return function(e, t, n, o) {
for (var r = e && e._component, i = r, l = e, a = r && e._componentConstructor === t.nodeName, s = a, p = d(t); r &&
!s && (r = r._parentComponent);) s = r.constructor === t.nodeName;
return r && s && (!o || r._component) ? (B(r, p, 3, n, o), e = r.base) : (i && !a && (L(i), e = l = null), r = S(
t.nodeName, p, n), e && !r.nextBase && (r.nextBase = e, l = null), B(r, p, 1, n, o), e = r.base, l && e !== l &&
(l._component = null, N(l, !1))), e
}(t, n, o, r);
if (g = "svg" === u || "foreignObject" !== u && g, u = String(u), (!t || !f(t, u)) && (s = u, (p = g ? document.createElementNS(
"http://www.w3.org/2000/svg", s) : document.createElement(s)).normalizedNodeName = s, l = p, t)) {
for (; t.firstChild;) l.appendChild(t.firstChild);
t.parentNode && t.parentNode.replaceChild(l, t), N(t, !0)
}
var c = l.firstChild,
m = l.__preactattr_,
_ = n.children;
if (null == m) {
m = l.__preactattr_ = {};
for (var y = l.attributes, C = y.length; C--;) m[y[C].name] = y[C].value
}
return !b && _ && 1 === _.length && "string" == typeof _[0] && null != c && void 0 !== c.splitText && null == c.nextSibling ?
c.nodeValue != _[0] && (c.nodeValue = _[0]) : (_ && _.length || null != c) && function(t, n, o, r, i) {
var l, a, s, p, u, c, d, h, m = t.childNodes,
_ = [],
y = {},
g = 0,
b = 0,
C = m.length,
x = 0,
w = n ? n.length : 0;
if (0 !== C)
for (var k = 0; k < C; k++) {
var S = m[k],
P = S.__preactattr_;
null != (B = w && P ? S._component ? S._component.__key : P.key : null) ? (g++, y[B] = S) : (P || (void 0 !== S.splitText ?
!i || S.nodeValue.trim() : i)) && (_[x++] = S)
}
if (0 !== w)
for (k = 0; k < w; k++) {
var B;
if (u = null, null != (B = (p = n[k]).key)) g && void 0 !== y[B] && (u = y[B], y[B] = void 0, g--);
else if (b < x)
for (l = b; l < x; l++)
if (void 0 !== _[l] && (c = a = _[l], h = i, "string" == typeof(d = p) || "number" == typeof d ? void 0 !== c.splitText :
"string" == typeof d.nodeName ? !c._componentConstructor && f(c, d.nodeName) : h || c._componentConstructor ===
d.nodeName)) {
u = a, _[l] = void 0, l === x - 1 && x--, l === b && b++;
break
} u = e(u, p, o, r), s = m[k], u && u !== t && u !== s && (null == s ? t.appendChild(u) : u === s.nextSibling ?
v(s) : t.insertBefore(u, s))
}
if (g)
for (var k in y) void 0 !== y[k] && N(y[k], !1);
for (; b <= x;) void 0 !== (u = _[x--]) && N(u, !1)
}(l, _, o, r, b || null != m.dangerouslySetInnerHTML),
function(e, t, n) {
var o;
for (o in n) t && null != t[o] || null == n[o] || h(e, o, n[o], n[o] = void 0, g);
for (o in t) "children" === o || "innerHTML" === o || o in n && t[o] === ("value" === o || "checked" === o ? e[o] :
n[o]) || h(e, o, n[o], n[o] = t[o], g)
}(l, n.attributes, m), g = a, l
}(e, t, n, o, i);
return r && l.parentNode !== r && r.appendChild(l), --y || (b = !1, i || C()), l
}
function N(e, t) {
var n = e._component;
n ? L(n) : (null != e.__preactattr_ && l(e.__preactattr_.ref, null), !1 !== t && null != e.__preactattr_ || v(e), w(e))
}
function w(e) {
for (e = e.lastChild; e;) {
var t = e.previousSibling;
N(e, !0), e = t
}
}
var k = [];
function S(e, t, n) {
var o, r = k.length;
for (e.prototype && e.prototype.render ? (o = new e(t, n), T.call(o, t, n)) : ((o = new T(t, n)).constructor = e, o.render =
P); r--;)
if (k[r].constructor === e) return o.nextBase = k[r].nextBase, k.splice(r, 1), o;
return o
}
function P(e, t, n) {
return this.constructor(e, n)
}
function B(e, n, o, r, i) {
e._disable || (e._disable = !0, e.__ref = n.ref, e.__key = n.key, delete n.ref, delete n.key, void 0 === e.constructor
.getDerivedStateFromProps && (!e.base || i ? e.componentWillMount && e.componentWillMount() : e.componentWillReceiveProps &&
e.componentWillReceiveProps(n, r)), r && r !== e.context && (e.prevContext || (e.prevContext = e.context), e.context =
r), e.prevProps || (e.prevProps = e.props), e.props = n, e._disable = !1, 0 !== o && (1 !== o && !1 === t.syncComponentUpdates &&
e.base ? u(e) : U(e, 1, i)), l(e.__ref, e))
}
function U(e, t, n, o) {
if (!e._disable) {
var r, l, a, s = e.props,
p = e.state,
u = e.context,
c = e.prevProps || s,
f = e.prevState || p,
v = e.prevContext || u,
h = e.base,
m = e.nextBase,
g = h || m,
b = e._component,
w = !1,
k = v;
if (e.constructor.getDerivedStateFromProps && (p = i(i({}, p), e.constructor.getDerivedStateFromProps(s, p)), e.state =
p), h && (e.props = c, e.state = f, e.context = v, 2 !== t && e.shouldComponentUpdate && !1 === e.shouldComponentUpdate(
s, p, u) ? w = !0 : e.componentWillUpdate && e.componentWillUpdate(s, p, u), e.props = s, e.state = p, e.context =
u), e.prevProps = e.prevState = e.prevContext = e.nextBase = null, e._dirty = !1, !w) {
r = e.render(s, p, u), e.getChildContext && (u = i(i({}, u), e.getChildContext())), h && e.getSnapshotBeforeUpdate &&
(k = e.getSnapshotBeforeUpdate(c, f));
var P, T, M = r && r.nodeName;
if ("function" == typeof M) {
var W = d(r);
(l = b) && l.constructor === M && W.key == l.__key ? B(l, W, 1, u, !1) : (P = l, e._component = l = S(M, W, u), l.nextBase =
l.nextBase || m, l._parentComponent = e, B(l, W, 0, u, !1), U(l, 1, n, !0)), T = l.base
} else a = g, (P = b) && (a = e._component = null), (g || 1 === t) && (a && (a._component = null), T = x(a, r, u, n ||
!h, g && g.parentNode, !0));
if (g && T !== g && l !== b) {
var D = g.parentNode;
D && T !== D && (D.replaceChild(T, g), P || (g._component = null, N(g, !1)))
}
if (P && L(P), e.base = T, T && !o) {
for (var E = e, V = e; V = V._parentComponent;)(E = V).base = T;
T._component = E, T._componentConstructor = E.constructor
}
}
for (!h || n ? _.push(e) : w || e.componentDidUpdate && e.componentDidUpdate(c, f, k); e._renderCallbacks.length;) e._renderCallbacks
.pop().call(e);
y || o || C()
}
}
function L(e) {
var t = e.base;
e._disable = !0, e.componentWillUnmount && e.componentWillUnmount(), e.base = null;
var n = e._component;
n ? L(n) : t && (null != t.__preactattr_ && l(t.__preactattr_.ref, null), e.nextBase = t, v(t), k.push(e), w(t)), l(e.__ref,
null)
}
function T(e, t) {
this._dirty = !0, this.context = t, this.props = e, this.state = this.state || {}, this._renderCallbacks = []
}
i(T.prototype, {
setState: function(e, t) {
this.prevState || (this.prevState = this.state), this.state = i(i({}, this.state), "function" == typeof e ? e(this
.state, this.props) : e), t && this._renderCallbacks.push(t), u(this)
},
forceUpdate: function(e) {
e && this._renderCallbacks.push(e), U(this, 2)
},
render: function() {}
});
var M = function(e, t, n, o) {
for (var r = 1; r < t.length; r++) {
var i = t[r++],
l = "number" == typeof i ? n[i] : i;
1 === t[r] ? o[0] = l : 2 === t[r] ? (o[1] = o[1] || {})[t[++r]] = l : 3 === t[r] ? o[1] = Object.assign(o[1] || {},
l) : o.push(t[r] ? e.apply(null, M(e, l, n, ["", null])) : l)
}
return o
},
W = function(e) {
for (var t, n, o = 1, r = "", i = "", l = [0], a = function(e) {
1 === o && (e || (r = r.replace(/^\s*\n\s*|\s*\n\s*$/g, ""))) ? l.push(e || r, 0) : 3 === o && (e || r) ? (l.push(
e || r, 1), o = 2) : 2 === o && "..." === r && e ? l.push(e, 3) : 2 === o && r && !e ? l.push(!0, 2, r) : 4 ===
o && n && (l.push(e || r, 2, n), n = ""), r = ""
}, s = 0; s < e.length; s++) {
s && (1 === o && a(), a(s));
for (var p = 0; p < e[s].length; p++) t = e[s][p], 1 === o ? "<" === t ? (a(), l = [l], o = 3) : r += t : i ? t ===
i ? i = "" : r += t : '"' === t || "'" === t ? i = t : ">" === t ? (a(), o = 1) : o && ("=" === t ? (o = 4, n = r,
r = "") : "/" === t ? (a(), 3 === o && (l = l[0]), o = l, (l = l[0]).push(o, 4), o = 0) : " " === t || "\t" ===
t || "\n" === t || "\r" === t ? (a(), o = 2) : r += t)
}
return a(), l
},
D = "function" == typeof Map,
E = D ? new Map : {},
V = D ? function(e) {
var t = E.get(e);
return t || E.set(e, t = W(e)), t
} : function(e) {
for (var t = "", n = 0; n < e.length; n++) t += e[n].length + "-" + e[n];
return E[t] || (E[t] = W(e))
};
function A(e, t) {
! function(t, n, o) {
x(o, e, {}, !1, n, !1)
}(0, t, t.firstElementChild)
}
var H = function(e) {
var t = M(this, V(e), arguments, []);
return t.length > 1 ? t : t[0]
}.bind(r);
export {
r as h, H as html, A as render, T as Component
};

View File

@ -0,0 +1,158 @@
import { h, Component, render } from 'preact'
import { datas, optionData, childData } from '@/index.js';
import { selector, warn, listenerClose, isArray, deepMerge, exchangeOptionsData } from '@/common/util'
import Framework from '@/components/framework'
import defaultOptions from '@/config/options'
class xmOptions {
constructor(options) {
this.init(options);
}
init(options){
//定义默认值
this.options = defaultOptions(options.language);
//开始渲染数据
this.update(options);
}
/**
* 更新数据 + 重新渲染
*/
update(options = {}){
let updateData = !!options.data;
//记录最新的配置项
this.options = deepMerge(this.options, options);
//如果dom不存在, 则不进行渲染事项
let dom = selector(this.options.el);
if(!dom){
warn(`没有找到渲染对象: ${options.el}, 请检查`)
return ;
}
//判断data的数据类型
let optionsData = this.options.data || [];
if(typeof(optionsData) === 'function'){
optionsData = optionsData();
this.options.data = optionsData;
}
if(!isArray(optionsData)){
warn(`data数据必须为数组类型, 不能是${ typeof(data) }类型`)
return ;
}
render(<Framework { ...this.options } updateData={ updateData } />, dom);
//返回多选对象
return this;
}
/**
* 重置多选, 回到初始化的状态
*/
reset(){
const { el } = this.options
//重新渲染
this.init(optionData[el]);
//子组件初始化
childData[el].init(this.options, true);
return this;
}
/**
* 主动打开多选
*/
opened(){
let ref = childData[this.options.el];
!ref.state.show && ref.onClick();
return this;
}
/**
* 主动关闭多选
*/
closed(){
let ref = childData[this.options.el];
ref.state.show && ref.onClick();
return this;
}
/**
* 获取多选选中的数据
*/
getValue(type){
let arr = deepMerge([], childData[this.options.el].state.sels);
if(type === 'name'){
return arr.map(item => item[this.options.prop.name]);
}else
if(type === 'nameStr'){
return arr.map(item => item[this.options.prop.name]).join(',');
}else
if(type === 'value'){
return arr.map(item => item[this.options.prop.value]);
}else
if(type === 'valueStr'){
return arr.map(item => item[this.options.prop.value]).join(',');
}
return arr;
}
/**
* 设置多选数据
*/
setValue(sels, show, listenOn = false){
if(!isArray(sels)){
warn('请传入数组结构...')
return ;
}
childData[this.options.el].value(sels, show, listenOn);
return this;
}
/**
* 追加赋值
*/
append(sels){
if(!isArray(sels)){
warn('请传入数组结构...')
return ;
}
childData[this.options.el].append(sels);
return this;
}
/**
* 删除赋值
*/
delete(sels){
if(!isArray(sels)){
warn('请传入数组结构...')
return ;
}
childData[this.options.el].del(sels);
return this;
}
/**
* 闪烁警告边框
*/
warning(color, sustain = false){
let showColor = color || this.options.theme.maxColor;
sustain === true ? (
childData[this.options.el].base.style.borderColor = showColor
) : (
childData[this.options.el].updateBorderColor(showColor)
)
return this;
}
}
export default xmOptions;

11
src/config/language/en.js Normal file
View File

@ -0,0 +1,11 @@
export default {
tips: 'please selected',
empty: 'no data',
searchTips: 'please search',
toolbar: {
ALL: 'select all',
CLEAR: 'clear',
REVERSE: 'invert select',
SEARCH: 'search',
}
}

11
src/config/language/zn.js Normal file
View File

@ -0,0 +1,11 @@
export default {
tips: '请选择',
empty: '暂无数据',
searchTips: '请选择',
toolbar: {
ALL: '全选',
CLEAR: '清空',
REVERSE: '反选',
SEARCH: '搜索',
}
}

View File

@ -7,24 +7,24 @@ export default function (lan = 'zn') {
let setting = lanSetting[lan] || zn; let setting = lanSetting[lan] || zn;
return { return {
//配置语言 //配置语言
language: lan, language: lan,
//所有的语言配置 //所有的语言配置
languageProp: setting, languageProp: setting,
//多选数据 //多选数据
data: [], data: [],
//自定义数据 //自定义数据
content: '', content: '',
//表单提交的name //表单提交的name
name: 'select', name: 'select',
//尺寸 //尺寸
size: 'medium', size: 'medium',
//是否禁用多选 //是否禁用多选
disabled: false, disabled: false,
//默认选中数据, 优先级大于selected //默认选中数据, 优先级大于selected
initValue: null, initValue: null,
//创建条目 //创建条目
create: null, create: null,
//默认提示 //默认提示
tips: setting.tips, tips: setting.tips,
//空数据提示 //空数据提示
@ -52,45 +52,52 @@ export default function (lan = 'zn') {
style: {}, style: {},
//默认多选的高度 //默认多选的高度
height: '200px', height: '200px',
//已选中数据是否自动换行显示 //已选中数据是否自动换行显示
autoRow: false, autoRow: false,
//是否开启分页 //是否开启分页
paging: false, paging: false,
//分页每页的条数 //分页每页的条数
pageSize: 10, pageSize: 10,
//分页无数据是否展示分页 //分页无数据是否展示分页
pageEmptyShow: true, pageEmptyShow: true,
//是否开启单选模式 //是否开启单选模式
radio: false, radio: false,
//是否开启重复选模式 //是否开启重复选模式
repeat: false, repeat: false,
//是否点击选项后自动关闭下拉框 //是否点击选项后自动关闭下拉框
clickClose: false, clickClose: false,
//多选上限 //多选上限
max: 0, max: 0,
maxMethod: function(sels, item){}, maxMethod: function(sels, item){},
//选项显示数量 //选项显示数量
showCount: 0, showCount: 0,
//工具条 //工具条
toolbar: { toolbar: {
show: false, show: false,
showIcon: true, showIcon: true,
list: [ 'ALL', 'CLEAR' ], list: [ 'ALL', 'CLEAR' ],
}, },
tree: {
show: false,
showFolderIcon: true,
showLine: true,
indent: 20,
expandedKeys: [],
},
//自定义属性名称 //自定义属性名称
prop: { prop: {
name: 'name', name: 'name',
value: 'value', value: 'value',
selected: 'selected', selected: 'selected',
disabled: 'disabled', disabled: 'disabled',
children: 'children', children: 'children',
optgroup: 'optgroup', optgroup: 'optgroup',
click: 'click', click: 'click',
}, },
//主题配置 //主题配置
theme: { theme: {
color: '#009688', //默认主题颜色 color: '#009688', //默认主题颜色
maxColor: '#e54d42', //多选上限边框闪烁颜色 maxColor: '#e54d42', //多选上限边框闪烁颜色
}, },
//模型 //模型
model: { model: {
@ -111,7 +118,7 @@ export default function (lan = 'zn') {
} }
}, },
}, },
icon: 'show', icon: 'show',
}, },
// 展开下拉框 // 展开下拉框

View File

@ -1,59 +1,48 @@
import { name, version } from '../package.json' import { name, version } from '../package.json'
import '@/components/common/expand' import { selector, warn } from '@/common/util'
import Core from '@/components/core' import Select from '@/components/xm-select'
import '@/style/index.less'
import '@/style/iconfont.less'
import { selector, warn } from '@/components/common/util'
const object = {} export const datas = {};
const xmSelect = { export const optionData = {};
export const childData = {};
export default {
name, name,
version, version,
render(options) { render(options) {
let instance = new Core(options); let { el } = options;
if(instance){ optionData[el] = options;
let { el } = options;
let select = object[el]; let instance = new Select(options);
select !== undefined && (delete object[el]); //已经渲染
object[el] = instance; if (instance) {
} datas[el] = instance;
return instance; }
return instance;
}, },
get(filter, single){ get(filter, single) {
let type = Object.prototype.toString.call(filter); let type = Object.prototype.toString.call(filter);
let method; let method;
switch (type){ switch (type) {
case '[object String]': case '[object String]':
filter && (method = item => item === filter); filter && (method = item => item === filter);
break; break;
case '[object RegExp]': case '[object RegExp]':
method = item => filter.test(item); method = item => filter.test(item);
break; break;
case '[object Function]': case '[object Function]':
method = filter; method = filter;
break; break;
default: default:
break; break;
} }
let keys = Object.keys(object) let keys = Object.keys(datas)
let list = (method ? keys.filter(method) : keys).map(key => object[key]).filter(instance => selector(instance.options.el)); let list = (method ? keys.filter(method) : keys).map(key => datas[key]).filter(instance => selector(instance.options.el));
return single ? list[0] : list; return single ? list[0] : list;
}, },
batch(filter, method){ batch(filter, method) {
let args = [ ...arguments ]; let args = [...arguments];
args.splice(0, 2); args.splice(0, 2);
return this.get(filter).map(instance => instance[method](...args)); return this.get(filter).map(instance => instance[method](...args));
} }
} }
if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
module.exports = xmSelect;
} else if (typeof define === 'function' && define.amd) {
define(xmSelect);
} else if (window.layui && layui.define) {
layui.define(function(exports) {
exports('xmSelect', xmSelect);
});
}
window.xmSelect = xmSelect;

24
src/main.js Normal file
View File

@ -0,0 +1,24 @@
import '@/common/expand'
import '@/style/index.less'
import '@/style/iconfont.less'
import { default as xmSelect, datas } from './index.js';
const moduleName = 'xmSelect';
/**
* 监听全页面点击关闭事件
*/
window.addEventListener('click', () => Object.values(datas).forEach(item => item && item.closed && item.closed()))
if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
module.exports = xmSelect;
} else if (typeof define === 'function' && define.amd) {
define(xmSelect);
} else if (window.layui && layui.define) {
layui.define(function(exports) {
exports(moduleName, xmSelect);
});
}
window[moduleName] = xmSelect;

View File

@ -5,7 +5,7 @@
/* IE9*/ /* IE9*/
src: url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.eot?t=1534240067831#iefix') format('embedded-opentype'), src: url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.eot?t=1534240067831#iefix') format('embedded-opentype'),
/* IE6-IE8 */ /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAsYAAsAAAAAEQwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFY8ukovY21hcAAAAYAAAACrAAACPBtV6wxnbHlmAAACLAAABnEAAAmMovtEvWhlYWQAAAigAAAAMQAAADYSctBCaGhlYQAACNQAAAAgAAAAJAgBA69obXR4AAAI9AAAABsAAAAwMCX//WxvY2EAAAkQAAAAGgAAABoN8gwubWF4cAAACSwAAAAeAAAAIAEiAM9uYW1lAAAJTAAAAUUAAAJtPlT+fXBvc3QAAAqUAAAAhAAAALJ1LunfeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkYWacwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGByeMbwwZ27438AQw9zMcAQozAiSAwDk4AxmeJzlks0JwzAMhZ8bN/1xD4GU0h2Se26BbJMJOkkn6KmTPbJF8mT5UGg3qMRn0EPIRs8A9gAq0YsIhDcCLF5SQ9YrnLMe8VB9RSMlMjCxYcueIyfOy7CuAFHU7lP9iqApt5L3ksBJbzlgZ9PVkXDUvbWa6x8T/i0u+XyWKtmmHW0NDI55yeRok2DjaKdg65jX7Bzzm71jXnN08vzJkQvg7Ng/WAYH9Qb3wzM/AHicjVVvbFzFEd/Zfbv7/vn9uXf33vl8Pt/dO99BHOzEZ9/DKTImRS0KjUoLDUFCjtpCMGkT1D9qldQmhkiUSv2G1BBB1VYqilGREOIDViWEGzttqkpI/cAXqyL5gFRALVIF+VCJe9fZd+fEpR/o6d3s7G9mZ2dmZ3aJIKR3h0ZYmVgkIjGZJV8mDxECtenOTDOu1UU+hJoD+TCqzcNMk2V8O5OCbDVRPgZhEt4JCNTZ/4HA3+DfuWIxl8pcFFErG3K7oD7fvev8UaMUmEu259lrRjBsfs6cLhYbRfzSbSjGRVAkfQYihUXsyPkHTVyyZDNmXzSHg3Tl+aPKxpJFqbWGdtLl8w8iYDxuDTQIx7yc1YCdIx7Jk3HSwbwQwGBcyMKZVtG0ZCuJxjFJBb+foMSfhJaPOSr4FYgwSwqIx2MHJALtAdBi/7xcSMJL+fxmmBS2guD61tZm96X02mgcj0J1NAaIR9UMmhXIV24FuLUC71+r1AEmK1AYrQHUK/Tly/m8MrOZz2+FSf7jzc3NK9XR9F2lVq+gmRp0r+HK9B+VJmR263Rgd7ALwR/FOFfx/FeJS0YxQh9drakgMJhaBVizkwgqWxLD6eQ0Qo8f7p44fJziSH9x+PjLZUO+/jZ9+K35X37ljn/Rv+yW4Ziuf2nl4PfS5/LrP47OHTsFJULYjf369UZAEBmSqEOSJmG4Me6LeznA0BFkcDoJlGynVzmH2vY21DhPr25v9DjvbfTp2TXG1s5mlK0q4S7lT++6obbRox/s6CHF2LMEsHvoFfSFQIKnKQMZJVFCD6WH0p0PVvvcRx8uph8eUks0jOFNtskOkpDsJ18k9+NqVRg3qqMCSSerjyRuYUi1/vFH7YIqikGVcD+ehFl/pqPSPKZ6DG6mHisljFhBFvU/PoRkSNd/JHO6Ja5JOXcfwIGJbm/igBq/hn8Kfb57YbYUxyX4cwkLKH1u4gD9GVSL6USxCjjCO2p8VdcvH9XRYIQWqUblu3pR/v2BvXMAc3tTmJiDAQ895B9NL0C9BFdKqqRKczDX/Whg7O1irVbcqZ8/sbfYBOZwihC+6wSDzszUf+dF7rRO1O+fKaDO+nXOr6+vf8L5J44Qe4UvnlyRntwrxMoKzpFdeRJBNb9dGyiur1+nE59R+uwi9M1G395jb9KP0bcK2YM9nJB5cojcS75OFskxclzdc+pW699z8iYbtf14BGKf77ruZNyXKC0e50OEBI+V/Aug5Dex/9WjJfipuqnS00gfybjXbNe1f762tXmRPp3Bdl/l6g5JXyqXR0bK8J3PR+jvwYs8/GBnTM+kr8FX4ZknwC16XtG9iH9QfNn1vDHPe2GAj3ieV3XdF2+IPdeteh62Ra+HfQrsKWKSBtlHSOBgM7KkKQBLWnZoq1mVwotCLRGhOtSkMzMuqq2ml3SqUehdnZtynbtPLB88/Dy9dDrYVzoy/MTT6Svnlpd/AHueon5wpnGsEae/PZm+d3Jp6SSUTy7R3xw4f9/B5RN3O+5t3VNncjm6Cnt+uLx8DpedGj4yvD84HceNxTcG6ku4VPmZ9n6nNdj95BHyB3IJKxBPsKm6rpn4QopmqzlFm1MwqdxO5rPGnIc7aSfCGg1Vqyo6nUlQhnh7WiFhXzgGhVC4qjPRki9xdGCc4zXeSWb9BG1ktlqz2Q5Y7S2sIJfivkpVKCCDpyCWdbQzECj76qMVqvyJ/LxyI2rTv1bTC25lSM9xAUJ4Lc+U0wXTsKXDmaA8tHX+hvDt4Wa9IHLcMUBz9VwpL4xi2aGasAPPKNUbbmD/2jAtk0uXY4eJx8zRgj9iAnVNt5X+BL5vlHTOaiOmG7g6+7ZBNUOaefNXuJF3u25RjVvBLeW8E4wV7ZJBpbAXXGnqrwgupWVTAKqZjq5HbW44fMguNJhgwmw8oOk8GCqE8F3GhLB0uS/UDVt4lgjtqGxK/rpwuaDAqKHZNuWmJjVKuWUxbpg2B9DtoRdN3TKF9B0hw4p41C5i3CI9w4civP3aQLlmLMK3wpJpaI7BvmlhPtH3nPWCKQAdE2hK9zyuUeAm921qCA2kvqY8N1yDMq4beJlG+4XQqHDCQnqPlJIyyN579S4tIGcRv/82BbFfK9SgnVHkZzMeaSQjqR5/fP5XF2Chh+sW0g0gn27snqXv3/bsszsfJbCAIiTdjRTVCBL6jV0K5D8H/8xVAAAAeJxjYGRgYADi16c/vIvnt/nKwM3CAALXZxxzhtH///23YVFhbgZyORiYQKIAm34OJQAAAHicY2BkYGBu+N/AEMOi/P/f//8sKgxAERTAAwCmuAa3eJxjYWBgYAFhRiiNFf//z6L8/x+IDQAkCQRQAAAAAAAAjAEAATgBfgGaAiACbgMMA2AEhATGAAB4nGNgZGBg4GE4DMQgwATEXEDIwPAfzGcAAB2tAfIAAHicZY9NTsMwEIVf+gekEqqoYIfkBWIBKP0Rq25YVGr3XXTfpk6bKokjx63UA3AejsAJOALcgDvwSCebNpbH37x5Y08A3OAHHo7fLfeRPVwyO3INF7gXrlN/EG6QX4SbaONVuEX9TdjHM6bCbXRheYPXuGL2hHdhDx18CNdwjU/hOvUv4Qb5W7iJO/wKt9Dx6sI+5l5XuI1HL/bHVi+cXqnlQcWhySKTOb+CmV7vkoWt0uqca1vEJlODoF9JU51pW91T7NdD5yIVWZOqCas6SYzKrdnq0AUb5/JRrxeJHoQm5Vhj/rbGAo5xBYUlDowxQhhkiMro6DtVZvSvsUPCXntWPc3ndFsU1P9zhQEC9M9cU7qy0nk6T4E9XxtSdXQrbsuelDSRXs1JErJCXta2VELqATZlV44RelzRiT8oZ0j/AAlabsgAAAB4nG2L3QqCQBCFZ9RWU7sOfAeh8IFi3N10EHYUG1p8+gSjqz44F+cPEjgo4T81Jphihic0mGOBZyyxwhovUCxKIe4ylthRuDqV+I22UcLQ6+QH4ubWdZZkU3m4o/0tUqtSvT33TPLits12fzc+zhRcvoquo0o281OLhcMw7Q+AD8sULE0=') format('woff'), url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAksAAsAAAAAEYAAAAjdAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCEUgqTXI8lATYCJAM0CxwABCAFhG0HgTwbZQ4jEbaCkVIj+4sD3pR1GFAIp4fcnExVznDkY6poTaP8+woHw+EnHMKNfx8836/9zn2yu1/EgGTS1ROhmYfkmVCZjoeiFUKEJB4yw9Op/w7VIXHBVNhnuwzCYWJuctqf/TUplM2JBwVtNxeeFQx2AiDNB/4P17SEuttU1NxT62pHHh0FLvkr5IKlv59TW4obkWUQatb9n+IL9BoYMarW7aYmNPmkDAMFbkZvwqsJoWdiWzFhTVpHrPQCa/bkkkMAP2WakcHXARTwMAhKsGENuYnAqwmYSLbgmZ1AUINAq/HDU6XqEcCx/335AZ3iARRWA5HS7ELPKaD3HXzK2/3fHaMPOHq+bmAhBxpoBsyCvQ5aTkHLLlfj346yC0gTpY847xAcSUAsQydd36d9yv8doE36aWJRSJOVRP6fPPBhcQmi0BiEAB5+HBAHgA6mV05q4jvQHL4dA4HDgsHB4YIhoeUyAnAoMGJwaDDp4DBgMkBxLqYTKMB0BYcHZhrq4IdPOcPXUYe254F20C7YVxCTvQ7224IspxVBtMQtU1AoRFlCNJYt4AWdhkSIBEQDkSCCUIBajocT8z+QgxgIAbq6bO3aSk0FRpQ51eXzie22O5F0tOgRJY1Hhv+jGMNySErrQ+SzskZNRdmIlkXF6NhTKKc6lS7XprOVmjSKYek5RFkdgNXNF5A/EIFYWpJQYnsTgM0NtTYLm4wpQwk8miQV6nJRPI+H8fN6Wb7bPcLjYnVdDWWoU27ae0Pleki5H9HeJ6zncfYf8GyZ2027XOMGgPuwxct6PAtZhpJFIymaHVEZyiS32SOR6JY9thDj3HcwizEbL7fmVV2MhDdcysKBmebXXolBOt43C8bsLRCiOZBM2prDYomqi4tNzgTCXhGOWHff4e2dYbOvCeNPZO50flUHoEy1jnptCEtD574hRkkaHRje9z2dWk8VclIcxkaOxpDZhG6Nz4qDaRRGMhxMwNQ2h8a+fSIWs8W17VM43eMvup6dXH6ZazFT0ZDgvc54llOuPNp9jzXtTaWbtZ0PaCa5ljOefNa7gnbnzb4H7/ZgQ0WwJQLRSXQ1wYbgQWkaOYRZgyXEWvmepBwhyfLaRL1NqpcqRMttiYnaEIejG0lTMk0n4lqp7Z1qIyYzeQFmk4TSORO224Nhia6c0VVNmqhlboeQ9ql6vcMYcjo+GLpAV0Uw4/B7gB6fBctt26sStgcn2ZNCENw3jEnKdGchu5EiT0yiK3WoXuATzaS3hdX66wH+6r6XBEQOjhCAzMZgEiJUOExA5IyOFN2BoTqxTGdaVe2O8l/vyhTUeKIDNnnlIwEfujH2m0iZoBRZKS6BwxK/Cbh4TpBMKeOVwpz5iCKBE8WiXZL+gTEYWKY0PC7MzHGN7983OuylYZW1QXkGI8uWdK1oePeuweEAH5TPJGnSxE1rwBtBp8vlR492lw8/dDRTnnX48HB59yNHEuXxH98fOXzksPA66oQs6s+ouOjYg7KDsaSMsCaZiiUlWkLSFyXReYSM0EQ/ge5eFOXTl6OlUbD3IroIeuEzBmjA1KkDIAMhZwMNqH2Ks3dEz8Cl/l33zTs3Szy6tmWJZ31e/3HtZ78NAzJEfQ2VydBrEllsjOUWctuBA+jv3yhMB1KMI+mSp8tghwOGaVmKYUx3g765v3717fvrF00Lfz3rOxYIsn3B30N3c6HKY0dHsPM3nlWGKBcvVggXbmHu3OJCFW0eDwHDcdNmaLMJ983m1kOpiqRiCpe1Ojb8ZHjs6lN4a1Dg7M2mEmGAz7nn+QLOB7wNdYe+DQCkvBb5+BGtldzHD6YH/fChlP7wkUxjBEwjLaT/XyqGpwqmNh5hKcgAJpShEO7R7eRAWH3xHl+IjygmrDAZlIkNJt6EvNmzvMh5ZNDhQY4izZziPb9D+2fufuP2O47fc6fpaFREJP/A7pjdB2ZYVjQR/olR4ZGCA7tlu1pmWHlFgpZdss8EtzeX/mHgDSa7dldNn67q3pUcwDNmHFqTnRP7bg2dG5o6Z6FGReWpVHmUim7B7NRQNR0K4nKy/xn/T/y40TWzuMgki5sVacj/HuDicBnHv3JikWgA5Tdr2LBPU78bFTE9jSWNU+/0S6Qjeo2uX9KjZh/NqyocKug2NLT7DS2U+Wxh8Lq//TWLGq6LMkfUp39Ur45LeJLetMlaaqww91TcHegXIL1FK6ZYT/SAbfoiNPKx8fnUgn/mg6A1i7qnjJvkV25+Gv8qO27ShLJg/9YlCvPflo0WcyG0VzBvnk2U2cfxZ27Vv5dkD3OqVmuF0+j9Xe4GGJSVDrqHQuFsCYVgidx0U6lUyHoWXul6rLlnZl1AEhM7bHUCyPV1EWMgEwLeFu5SHw6hzhbTcSMB2jxQv+3ShR/JTzrfRuYxzD++oM0CwL0FAPg6oACJ9LHlohCSDwAASB/4JMDXjBxBuiXFJzqApC95WDP8wZeCmtNc4/t9JZqADJ9XowDpMsV0Bq40ht8ez+/wKRD/Jzpx7WvWAI/5yg7k+eegHgp2uukjZ+ojio17gxBDZtuPEX+6xuPwaENde4b+EA/TGqUCv7SCKeNgnJfrsCm2bnLMpspyhUsJdMhwX2CIaC63BOgGh4iecj9NjIQOkGAHjZggAI0coVyIclGuCHMDGsQTGBDP5ZY0fyYH6aLL/cxJIsoARzwKzp4C8ASKiStDSVarjjTLNr6DyQceyDBz9w0hIlnWlPVx4Q0shHP4iCezTkkzHejIXhMvcDgQc4F2IFPZYt5tq0qvfJaSjp0ZTwF4stUVQ1xboySr706z1s+/g8kHHiIn7lp/Q4j4cEZDSc1QvtGWdeK9bI8nsyZRt2Z6f6Aj45W64SBnieHCjnYgU0k7YtptqegmzaXL67PH35zu/Hynii9YihItRqw44oonPvFLQIISkjCT7cztRbscSY6K25XKdGkmfWvJGpH3YDg+1JuN5HTL9Kcixqjvvsw0PwMK5JSwKAZ1L80ILo5bNY6UY5vIDRzqPPFozZ4tjsVQvtMBAAA=') format('woff2'),
url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.ttf?t=1534240067831') format('truetype'), url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.ttf?t=1534240067831') format('truetype'),
/* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.svg?t=1534240067831#iconfont') format('svg'); url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.svg?t=1534240067831#iconfont') format('svg');
@ -59,3 +59,7 @@
.xm-icon-expand:before { .xm-icon-expand:before {
content: "\e641"; content: "\e641";
} }
.xm-icon-banxuan:before {
content: "\e60d";
}

View File

@ -13,31 +13,31 @@
} }
@-webkit-keyframes loader { @-webkit-keyframes loader {
0% { 0% {
-webkit-transform: rotate(0deg); -webkit-transform: rotate(0deg);
transform: rotate(0deg); transform: rotate(0deg);
} }
100% { 100% {
-webkit-transform: rotate(360deg); -webkit-transform: rotate(360deg);
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
@keyframes loader { @keyframes loader {
0% { 0% {
-webkit-transform: rotate(0deg); -webkit-transform: rotate(0deg);
transform: rotate(0deg); transform: rotate(0deg);
} }
100% { 100% {
-webkit-transform: rotate(360deg); -webkit-transform: rotate(360deg);
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
.userselect(@v){ .userselect(@v){
user-select: @v; user-select: @v;
-ms-user-select: @v; -ms-user-select: @v;
-moz-user-select: @v; -moz-user-select: @v;
-webkit-user-select: @v; -webkit-user-select: @v;
} }
xm-select{ xm-select{
@ -67,10 +67,10 @@ xm-select{
& > .xm-tips{ & > .xm-tips{
color: #999999; color: #999999;
padding: 0 10px; padding: 0 10px;
position: absolute; position: absolute;
display: flex; display: flex;
height: 100%; height: 100%;
align-items: center; align-items: center;
} }
& > .xm-icon{ & > .xm-icon{
@ -96,30 +96,30 @@ xm-select{
} }
& > .xm-label{ & > .xm-label{
&.single-row{ &.single-row{
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0px; bottom: 0px;
left: 0px; left: 0px;
right: 30px; right: 30px;
overflow: auto hidden; overflow: auto hidden;
.scroll{ .scroll{
overflow-y: hidden; overflow-y: hidden;
} }
.label-content{ .label-content{
flex-wrap: nowrap; flex-wrap: nowrap;
} }
} }
&.auto-row{ &.auto-row{
.label-content{ .label-content{
flex-wrap: wrap; flex-wrap: wrap;
} }
} }
.scroll{ .scroll{
.label-content{ .label-content{
display: flex; display: flex;
padding: 3px 30px 3px 10px; padding: 3px 30px 3px 10px;
} }
} }
@ -135,7 +135,7 @@ xm-select{
& > span{ & > span{
display: flex; display: flex;
color: #FFF; color: #FFF;
white-space: nowrap; white-space: nowrap;
} }
& > i{ & > i{
@ -163,48 +163,47 @@ xm-select{
padding: 5px 0; padding: 5px 0;
z-index: 999; z-index: 999;
width: 100%; width: 100%;
min-width: fit-content; min-width: fit-content;
border: @border; border: @border;
// max-height: 300px; // max-height: 300px;
// overflow-y: auto; // overflow-y: auto;
background-color: #fff; background-color: #fff;
border-radius: 2px; border-radius: 2px;
box-shadow: 0 2px 4px rgba(0, 0, 0, .12); box-shadow: 0 2px 4px rgba(0, 0, 0, .12);
animation-fill-mode: both;
animation-name: xm-upbit; animation-name: xm-upbit;
animation-duration: .3s; animation-duration: .3s;
animation-fill-mode: both; animation-fill-mode: both;
.scroll-body{ .scroll-body{
overflow: auto; overflow: auto;
.scrollBorder() { .scrollBorder() {
-webkit-border-radius: 2em; -webkit-border-radius: 2em;
-moz-border-radius: 2em; -moz-border-radius: 2em;
-ms-border-radius: 2em; -ms-border-radius: 2em;
border-radius:2em; border-radius:2em;
} }
&::-webkit-scrollbar{ width: 8px; } &::-webkit-scrollbar{ width: 8px; }
&::-webkit-scrollbar-track{ .scrollBorder(); background-color: #FFF; } &::-webkit-scrollbar-track{ .scrollBorder(); background-color: #FFF; }
&::-webkit-scrollbar-thumb{ .scrollBorder(); background-color: #C2C2C2; } &::-webkit-scrollbar-thumb{ .scrollBorder(); background-color: #C2C2C2; }
} }
&.up{ &.up{
top: auto; top: auto;
bottom: 42px; bottom: 42px;
} }
.xm-group{ .xm-group{
cursor: default; cursor: default;
&-item{ &-item{
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
padding: 0 10px; padding: 0 10px;
color: #999; color: #999;
font-size: 12px; font-size: 12px;
} }
} }
.xm-option{ .xm-option{
display: flex; display: flex;
@ -238,12 +237,12 @@ xm-select{
width: calc(100% - 20px); width: calc(100% - 20px);
} }
&.hide-icon .xm-option-content{ &.hide-icon .xm-option-content{
padding-left: 0; padding-left: 0;
} }
&.selected.hide-icon .xm-option-content{ &.selected.hide-icon .xm-option-content{
color: #FFF !important; color: #FFF !important;
} }
} }
.xm-select-empty{ .xm-select-empty{
@ -277,7 +276,7 @@ xm-select{
&>i{ &>i{
position: absolute; position: absolute;
color: @fontColor; color: @fontColor;
} }
&-input{ &-input{
@ -314,45 +313,95 @@ xm-select{
} }
} }
.xm-toolbar{ .xm-toolbar{
padding: 0 10px; padding: 0 10px;
display: flex; display: flex;
margin: -3px 0; margin: -3px 0;
cursor: default; cursor: default;
.toolbar-tag{ .toolbar-tag{
cursor: pointer; cursor: pointer;
display: flex; display: flex;
margin-right: 20px; margin-right: 20px;
color: @fontColor; color: @fontColor;
align-items: baseline; align-items: baseline;
&:hover{ &:hover{
opacity: .8; opacity: .8;
} }
&:active{ &:active{
opacity: 1; opacity: 1;
} }
&>i{ &>i{
margin-right: 2px; margin-right: 2px;
font-size: 14px; font-size: 14px;
} }
&:last-child{ &:last-child{
margin-right: 0; margin-right: 0;
} }
} }
} }
.xm-body-custom{ .xm-body-custom{
line-height: initial; line-height: initial;
cursor: default; cursor: default;
*{
box-sizing: initial;
}
}
.xm-tree{
position: relative;
&-icon{
display: inline-block;
margin-right: 3px;
cursor: pointer;
border: 6px dashed transparent;
border-left-color: #C2C2C2;
border-left-style: solid;
transition: all .3s;
-webkit-transition: all .3s;
z-index: 2;
visibility: hidden;
&.expand{
margin-top: 3px;
margin-right: 5px;
margin-left: -2px;
transform: rotate(90deg);
}
&.visible{
visibility: visible;
}
}
.left-line{
position: absolute;
left: 13px;
width: 0;
z-index: 1;
border-left: 1px dotted #c0c4cc !important;
}
.top-line{
position: absolute;
left: 13px;
height: 0;
z-index: 1;
border-top: 1px dotted #c0c4cc !important;
}
&-box{
&.dis{
}
}
}
.scroll-body>.xm-tree>.xm-option>.top-line{
width: 0 !important;
}
*{
box-sizing: initial;
}
}
} }
.xm-input{ .xm-input{
@ -368,7 +417,7 @@ xm-select{
line-height: 1.3; line-height: 1.3;
padding-left: 10px; padding-left: 10px;
outline: 0; outline: 0;
.userselect(text); .userselect(text);
} }
.dis{ .dis{
@ -403,72 +452,94 @@ xm-select{
} }
} }
.xm-select-default{ .xm-select-default{
display: none !important; display: none !important;
} }
.xm-select-disabled{ .xm-select-disabled{
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
top: 0; top: 0;
bottom: 0; bottom: 0;
cursor: no-drop; cursor: no-drop;
z-index: 2; z-index: 2;
opacity: 0.3; opacity: 0.3;
background-color: #FFF; background-color: #FFF;
} }
} }
//不同尺寸下的数据调整 //不同尺寸下的数据调整
.mixin(@size){ .mixin(@size){
@height: @size; @height: @size;
@heightLabel: @height - 6px; @heightLabel: @height - 6px;
@heightItem: @heightLabel - 4px; @heightItem: @heightLabel - 4px;
@iconSize: @size / 2; @iconSize: @size / 2;
min-height: @height; min-height: @height;
line-height: @height; line-height: @height;
.xm-input{ .xm-input{
height: @height; height: @height;
} }
.xm-label{ .xm-label{
.scroll .label-content{ .scroll .label-content{
line-height: @heightLabel; line-height: @heightLabel;
} }
.xm-label-block{ .xm-label-block{
height: @heightItem; height: @heightItem;
line-height: @heightItem; line-height: @heightItem;
} }
} }
.xm-body .xm-option .xm-option-icon{ .xm-body .xm-option .xm-option-icon{
height: @iconSize; height: @iconSize;
width: @iconSize; width: @iconSize;
font-size: @iconSize; font-size: @iconSize;
} }
.xm-paging>span{ .xm-paging>span{
height: @heightLabel; height: @heightLabel;
line-height: @heightLabel; line-height: @heightLabel;
} }
.xm-tree{
.left-line{
height: calc(100% - @size);
top: @size / 2;
bottom: @size / 2;
&.expand{
height: 100%;
bottom: 0;
}
}
&:last-child{
.left-line{
height: calc(100% - @size);
}
}
.xm-tree-icon.hidden+.top-line{
top: @size / 2 - 1px;
}
.xm-tree-icon+.top-line{
margin-left: 1px;
}
}
} }
xm-select[size='large']{ xm-select[size='large']{
.mixin(40px) .mixin(40px)
} }
xm-select{//[size='medium'] xm-select{//[size='medium']
.mixin(36px) .mixin(36px)
} }
xm-select[size='small']{ xm-select[size='small']{
.mixin(32px) .mixin(32px)
} }
xm-select[size='mini']{ xm-select[size='mini']{
.mixin(28px) .mixin(28px)
} }
//layui的一些样式兼容 //layui的一些样式兼容
.layui-form-pane{ .layui-form-pane{
xm-select{ xm-select{
margin: -1px -1px -1px 0; margin: -1px -1px -1px 0;
} }
} }