formSelects停止维护, 已经迁移至xm-select

formSelects-v4.js 基于Layui的多选解决方案
1、闲谈杂趣
v3传送门     v3文档
其实思考了很久, 还是放弃了v3, 因为开发v3的时候很粗暴, 按照编程角度来看就是硬撸, 也怪自己实力有限, 所以反思了一下, 尝试着继续前行...
2、交流学习
QQ号: 707200833 QQ群: 769620939 技术交流群
重要的事情说三遍, 看文档, 看文档, 看文档, 文档中很多都已经标注了, 文档不清楚的话, 可以加群@群主
群主会在第一时间把代码更新至GitHub, 你可以前往GitHub下载formSelects完整代码, 以便于二次开发

3、下载与使用
下载地址: GitHub
使用文档: GitHub Pages
使用方式:

一个简单的小例子

4、基本参数
属性名 说明 示例
xm-select 多选核心, 标记不同的多选, 多选ID xm-select="id"
xm-select-max 多选最多选择数量 xm-select-max="3"
xm-select-skin 皮肤 xm-select-skin=" default | primary | normal | warm | danger "
xm-select-search 本地搜索 & 远程搜索 xm-select-search, xm-select-search="/search", 值为空时已有条目过滤搜索, 有值时开启远程搜索
xm-select-create 条目不存在时创建, 标记性属性 xm-select-create
xm-select-direction 下拉方向 xm-select-direction="auto|up|down", 自动, 上, 下, 默认自动模式
xm-select-radio 单选模式 xm-select-radio, 最多只能选择一个
xm-select-search-type 搜索框的显示位置 xm-select-search-type="title" 在下拉选title部分显示, xm-select-search-type="dl" 在选项的第二条显示
xm-select-show-count 多选显示的label数量 xm-select-show-count="2", 超出后隐藏
5、基本方法

value

on

maxTips

filter

config

render

disabled

undisabled

data

btns

opened

closed

6、基础示例

基础多选

适用性较广的基础多选,用 Tag 展示已选项

pane模式

layui pane模式

分组多选

基于layui的分组多选

自定义tips

写一个空的option放在第一个

多选上限

xm-select-max="3", 超过3个后, 默认闪烁红框提示

当然, 如果你初始化值就多于max值, 那是可以设置成功滴, 取消了就选不回来了

多选皮肤

xm-select-skin="default"

xm-select-skin="primary", 这个墨绿style已经被内置成为了经典皮肤, 只因他诞生于layui的经典颜色

xm-select-skin="normal"

xm-select-skin="warm"

xm-select-skin="danger"

本地搜索

xm-select-search, 搜索已存在的option

分组中的搜索

远程搜索

xm-select-search="/search", 指定一个url, 将开启远程搜索模式

远程搜索response结构, 其中name, value可以自定义, 请查看method config

code为0时, 表示正常, 不为0时则提示msg信息

{
    "code": 0,
    "msg": "success",
    "data": [
        {"name":"北京","value":1,"selected":"","disabled":""},
        {"name":"上海","value":2,"selected":"","disabled":""},
        {"name":"广州","value":3,"selected":"selected","disabled":""},
        {"name":"深圳","value":4,"selected":"","disabled":"disabled"},
        {"name":"天津","value":5,"selected":"","disabled":""}
    ]
}

当然, 远程搜索也是可以分组的

{
    "code": 0,
    "msg": "success",
    "data": [
    	{"name": "分组-1", "type": "optgroup"},
        {"name":"北京","value":1,"selected":"","disabled":""},
        {"name":"上海","value":2,"selected":"","disabled":""},
        {"name": "分组-2", "type": "optgroup"},
        {"name":"广州","value":3,"selected":"selected","disabled":""},
        {"name":"深圳","value":4,"selected":"","disabled":"disabled"},
        {"name":"天津","value":5,"selected":"","disabled":""}
    ]
}

创建条目

xm-select-create, 不存在时会创建, 选中后长久保留, value为Date.now()生成

下拉方向

方式一: xm-select-direction="auto|up|down", 自动, 上, 下, 默认自动模式

方式二: 使用formSelects.config配置

//配置某一个多选的方向
layui.formSelects.config('select1', {direction: 'up'});

//配置所有多选的方向
layui.formSelects.config({direction: 'up'});

我是朝上的

我是朝下的

其他的都是自动处理的哈, 当然没有朝左朝右的

我是一个动态的

固定高度

xm-select-height="36px", 多选的高度是随便选项的变化而变化的, 当然你也可以固定一个高度, 从此高度将不再变化

禁用select

disabled="disabled", 多选的高度是随便选项的变化而变化的, 当然你也可以固定一个高度, 从此高度将不再变化

动态操作select的启用与禁用

单选模式

xm-select-radio, 单选模式

表单操作

支持layui原生表单验证, lay-verify="xxx"

tips模式, lay-verify="required", lay-verType="tips"

支持表单提交自动赋值, 只需要在select加上name属性即可, 点击提交可查看url的变化

支持reset操作, 选择几项数据, 然后点击重置

多选联动

多选联动, 联动需要使用data来赋值, 先给一个空select标记多选, 记得value不能重复哦

layui.formSelects.data('select15', 'local', { arr: [ { "name": "北京", "value": 1, "children": [ {"name": "北京市1", "value": 12, "children": [ {"name": "朝阳区1", "value": 13, "children": []}, {"name": "朝阳区2", "value": 14, "children": []}, {"name": "朝阳区3", "value": 15, "children": []}, {"name": "朝阳区4", "value": 16, "children": []}, ]}, {"name": "北京市2", "value": 17, "children": []}, {"name": "北京市3", "value": 18, "children": []}, {"name": "北京市4", "value": 19, "children": []}, ] }, { "name": "天津", "value": 2, "children": [ {"name": "天津市1", "value": 51, "children": []}, ] }, ], linkage: true }); //如果有需要默认值的小伙伴请使用formSelects.value formSelects.value('select15', ['1/12/13', '1/12/14'])

多选联动, 使用远程数据实现省市区三级联动

宽度是可以自定义的, linkageWidth: 130, 默认100

formSelects.config('select15_2', { success: function(id, url, val, result){ console.log("success回调: " + url); }, error: function(id, url, val, err){ console.log("err回调: " + url); } }); formSelects.data('select15', 'server', { url: 'http://yapi.demo.qunar.com/mock/9813/layui/citys', linkage: true, linkageWidth: 130 }); //如果有需要默认值的小伙伴请使用formSelects.value formSelects.value('select15', ['1/12/13', '1/12/14'])

快捷操作

设置内置的快捷操作

formSelects.btns('select16_1', ['select', 'remove', 'reverse', 'skin']);

自定义快捷操作

formSelects.btns('select16_2', ['select', 'remove', 'skin', { icon: 'layui-icon layui-icon-ok', //自定义图标, 可以使用layui内置图标 name: '提示名称', click: function(id){ //点击后的操作 alert('点击了自定义快捷操作') } }]);

你是可以换数组位置, 更换显示位置滴

如果内置操作不满意, 完全可以自定义

formSelects.btns('select16_3', ['skin', { icon: 'layui-icon layui-icon-ok', //自定义图标, 可以使用layui内置图标 name: '提示名称', click: function(id){ //点击后的操作 alert('点击了自定义快捷操作') } }, 'remove']);

如果不需要快捷操作, 设置一个空数组就可以了, 它会变回以前的模样

formSelects.btns('select16_4', []);

只显示图标

formSelects.btns('select16_5', ['select', 'remove'], {show: 'icon'});

只显示名称

formSelects.btns('select16_6', ['select', 'remove'], {show: 'name'});

显示图标+名称, 但是是紧凑型的

formSelects.btns('select16_7', ['select', 'remove'], {show: '', space: '10px'});
7、进阶示例

监听select选择

适用于动态操作

选择[北京]时, 会发现选不上哦

layui.formSelects.on('example1', function(id, vals, val, isAdd, isDisabled){ //id: 点击select的id //vals: 当前select已选中的值 //val: 当前select点击的值 //isAdd: 当前操作选中or取消 //isDisabled: 当前选项是否是disabled alert("选择了: " + val.name); //如果return false, 那么将取消本次操作 if(val.value == 1){ return false; } });

获取实时数据

layui.formSelects.on('example1_1', function(id, vals, val, isAdd, isDisabled){ //id: 点击select的id //vals: 当前select已选中的值 //val: 当前select点击的值 //isAdd: 当前操作选中or取消 //isDisabled: 当前选项是否是disabled alert("当前选择了: " + JSON.stringify(vals)); }, true);

赋值与取值

多选取值

layui.formSelects.value('example2_1'); //取值默认数组 layui.formSelects.value('example2_1', 'val'); //取值val数组 layui.formSelects.value('example2_1', 'valStr'); //取值val字符串 layui.formSelects.value('example2_1', 'name'); //取值name数组 layui.formSelects.value('example2_1', 'nameStr'); //取值name字符串

多选赋值

layui.formSelects.value('example2_2', []); //赋值空数组, 清空所有 layui.formSelects.value('example2_2', [1, 2]); //赋值 北京,上海 layui.formSelects.value('example2_2', [5], true); //追加赋值 天津 layui.formSelects.value('example2_2', [1], false); //删除 已选择 [北京]

超选后的提示

如果设置了xm-select-max="3", 当你选择第四个的时候会默认闪烁红框提示, 当然这个提示你可以自定义

layui.formSelects.maxTips('example3', function(id, vals, val, max){ //id: 点击select的id //vals: 当前select已选中的值 //val: 当前select点击的值 //max: 当天多选最大值 alert("选超了, 选择的值: " + val.value); });

自定义搜索

如果设置了xm-select-search="", 当你搜索的时候是默认判断选项文本是否包含搜索的值

如下是检测 全拼,简拼,文本是否包含, 其中汉字转拼音摘录于网络

可以尝试使用拼音进行搜索

layui.formSelects.filter('example4', function(id, inputVal, val, isDisabled){ if( PY.fullPY(val.name).toLowerCase().indexOf(inputVal) != -1 || //拼音全拼是否包含 PY.fullPY(val.name, true).indexOf(inputVal) != -1 || //拼音简拼是否包含 val.name.indexOf(inputVal) != -1 //文本是否包含 ){ return false; } return true; });

友情提示: 远程搜索是不会经过此方法滴

配置

说起来这是个又爱又恨的方法, 设计之初是准备专门配置远程搜索用的, 无奈后面增加了很多东西, 结果变成了专门的配置方法了

好像没啥好说的, 都是点儿配置的东西, 说点儿场景吧

- 默认本地数据, js动态配置成远程搜索, 首先开启搜索模式 xm-select-search="", 然后config中定义url, 适用于url为可变参数的情况下

layui.formSelects.config('example5_1', { searchUrl: 'https://www.fastmock.site/mock/29487363107ab7d242c46305cadf4c52/formSelects/layui/data' });

- 点击加载

layui.formSelects.config('example5_2', { searchUrl: 'https://www.fastmock.site/mock/29487363107ab7d242c46305cadf4c52/formSelects/layui/data' });

- beforeSuccess的用法

layui.formSelects.config('example5_3', { searchUrl: 'https://www.fastmock.site/mock/29487363107ab7d242c46305cadf4c52/formSelects/layui/data', beforeSuccess: function(id, url, searchVal, result){ //我要把数据外层的code, msg, data去掉 result = result.data; //我要反转name $.each(result, function(index, item) { item.name && (item.name = item.name.split('').reverse().join('')) }); //然后返回数据 return result; } });

当然上面的处理方法是用于演示beforeSuccess的用法的, 正确的姿势应该是转换数据结构滴

success, error可以直接打开控制台, 查看console的打印记录

远程数据的赋值

远程数据是使用ajax异步的模式来获取的, 所以赋值不能直接在config之后

方式一: 在返回数据中包含selected属性

方式二: 在success回调中使用value进行赋值

layui.formSelects.config('example5_4', { searchUrl: 'https://www.fastmock.site/mock/29487363107ab7d242c46305cadf4c52/formSelects/layui/data', success: function(id, url, searchVal, result){ formSelects.value('example5_4', [3, 4]); } }); //赋值失败了, 我的天, 什么情况, 结果发现对应3,4的value根本不存在!!! 请往下看

上面好像不太对

layui.formSelects.config('example5_5', { searchUrl: 'https://www.fastmock.site/mock/29487363107ab7d242c46305cadf4c52/formSelects/layui/data', success: function(id, url, searchVal, result){ formSelects.value('example5_5', [result.data[0].value, result.data[4].value]); } });

动态数据

本地数据

layui.formSelects.data('example6_1', 'local', { arr: [ {"name": "分组-1", "type": "optgroup"}, {"name": "北京", "value": 1}, {"name": "上海", "value": 2}, {"name": "分组-2", "type": "optgroup"}, {"name": "广州", "value": 3}, {"name": "深圳", "value": 4}, {"name": "天津", "value": 5} ] }); //佛曰, 格式不可变, 不喜欢 name,value 可以使用config重新定义

远程数据, 也许你只希望加载一次, 而不是搜索一次变一次, 这个更适合你

layui.formSelects.data('example6_2', 'server', { url: 'https://www.fastmock.site/mock/29487363107ab7d242c46305cadf4c52/formSelects/layui/data' }); //佛曰, 格式不可变, 不喜欢 name,value 可以使用config重新定义 //同样适合剥去外皮, 同样可以使用config beforeSuccess处理数据, 不过你需要这么写 layui.formSelects.config('example6_2', { beforeSuccess: function(id, url, searchVal, result){ //我要把数据外层的code, msg, data去掉 result = result.data; //我要反转name $.each(result, function(index, item) { item.name && (item.name = item.name.split('').reverse().join('')) }); //然后返回数据 return result; } }).data('example6_2', 'server', { url: 'https://www.fastmock.site/mock/29487363107ab7d242c46305cadf4c52/formSelects/layui/data' }); //使用了新增的链接写法, 当然你也可以分开写

不知道你们为什么吐槽我的设计, 也许真的是不好, 新增如下写法

layui.formSelects.data('example6_3', 'server', { url: 'https://www.fastmock.site/mock/29487363107ab7d242c46305cadf4c52/formSelects/layui/data', beforeSuccess: function(id, url, searchVal, result){ //我要把数据外层的code, msg, data去掉 result = result.data; //我要反转name $.each(result, function(index, item) { item.name && (item.name = item.name.split('').reverse().join('')) }); //然后返回数据 return result; }, success: function(id, url, searchVal, result){ console.log('id: example6_3, 成功返回数据!!!'); } });

来一发树状结构压压惊

//这里面的自由参数可以在template中使用 //只是加了一个树状展示形式, 过多的还没有做哈~ 有需求的可以提出来 layui.formSelects.data('example6_4', 'local', { arr: [ { "name": "北京", "value": 1, "xslkdf": "123", "children": [ { "name": "朝阳", "value": 11, "children": [ {"name": "酒仙桥", "value": 111}, {"name": "望京东", "value": 121} ] }, {"name": "海淀", "value": 12} ] }, { "name": "深圳", "value": 2, "children": [ {"name": "龙岗", "value": 21} ] } ] });

当输入内容为空时不触发搜索

layui.formSelects.config('example7_1', { searchUrl: 'https://www.fastmock.site/mock/29487363107ab7d242c46305cadf4c52/formSelects/layui/data', beforeSearch: function(id, url, val){ if(!val){ console.log('内容为空, 不进行远程搜索') return false; } return true; } });

主动触发搜索

layui.formSelects.search('example7_2', 'click');

显示数量

默认显示全部, 如果设置了高度的话就是显示指定范围内的label, 当然你也可以控制显示的数量

xm-select-show-count="2", 最多显示2个, 多余的隐藏

自定义模板

选项默认是显示的孤零零的name值, 你也可以自定义格式

比如来一个左边name, 右边拼音的

layui.formSelects.render('example9_1', { template: function(name, value, selected, disabled){ return name + '<span style="position: absolute; right: 0; color: #A0A0A0; font-size: 12px;">' + PY.fullPY(name) + '</span>'; } });

搜索位置

默认是在title上的, 可以设置到选项中, 前提是你打开了搜索

xm-select-search-type="dl"

树状结构

惊喜有没有, 树状结构来一发

layui.formSelects.data('example11_1', 'local', { arr: [ {name: '分组1', type: 'optgroup'}, {name: '北京', value: 1, xslkdf: '123', children: [{name: '朝阳', disabled: true, value: 11}, {name: '海淀', value: 12}]}, {name: '分组2', type: 'optgroup'}, {name: '深圳', value: 2, children: [{name: '龙岗', value: 21}]}, ], tree: { //在点击节点的时候, 如果没有子级数据, 会触发此事件 nextClick: function(id, item, callback){ //需要在callback中给定一个数组结构, 用来展示子级数据 callback([ {name: 'test1', value: Math.random()}, {name: 'test2', value: Math.random()} ]) }, } }); //这里也算是给自己挖了一手好坑吧, 简单的一种处理方式, 在多选第一次打开的时候收缩所有的子节点, 目前处理的很粗鲁, 就是为了一种效果, 收缩全部节点 var isFirst = true; layui.formSelects.opened('example11_1', function(id){ if(isFirst){ isFirst = false; $('[fs_id="example11_1"]').find('.xm-cz i.icon-caidan').click(); } });

监听打开关闭

监听下拉选框的打开与关闭

layui.formSelects.opened('example12_1', function(id){ alert('打开了...'); }); layui.formSelects.closed('example12_1', function(id){ alert('关闭了...'); });
结尾

↓↓↓ 捐赠作者 ↓↓↓

你们的支持, 是我们坚持的动力

[2019-06-24] v4.x
-- 修复 --
1. 修复文档中因为https无法访问http接口的问题, 从 http://yapi.demo.qunar.com 更换为 https://www.fastmock.site
2. 一个简单的手段, 让树状结构能够收起来
3. 修改template中文档写法错误

其实天下没有不散的宴席, 目前来看 jQuery 已经成为了历史, 加油吧, 小伙伴, 努力向最新的技术看齐~~~

	
	
[2018-09-10] v4.0.0.0910
-- bug修复 --
1. 修改多级联动在li中不能使用
2. 修改多级联动在动态赋值中的错误
3. 修改非tree模式下的显示异常
4. 修改render的单独渲染异常
5. 修改template不能够获取到所有数据的问题
6. 修改默认disabled不正常的问题

	
[2018-08-17] v4.0.0.0817
-- bug修复 --
1.在多次render的时候快捷图标的错误
2.修改图标库的标记 `iconfont` -> `xm-iconfont`, 避免冲突

-- 修改 --
1. 树状结构支持收缩
2. 树状结构支持动态获取数据
3. 那个没有用的图标可以全部展开/收缩树状结构
4. 在4.1测试的select不删除拿到此版本使用
5. 更新render的渲染方式, 优化代码
6. 新增方法opened、closed, 可以监听多选的下拉展开与折叠
7. 新增config参数, 可以自定义response结构
8. !!!重点!!! 很多地方回调之前是val属性 -> value, 升级请仔细检查, 涉及: value, on, filter, maxTips
9. 貌似在所有方法中增加了自定义属性, 可以自行尝试


[2018-08-13] v4.0.0.0813
-- bug修复 --
1.修复value在为字符串时, 多级联动的bug
2.修复value在超过int最大值时, 多级联动的bug
3.修复在动态切换radio的时候, 快捷图标不发生变化的bug
4.修改在未渲染的select上调用render, 配置项不生效的bug

-- 修改 --
1.新增formSelects.data的赋值方式, 可以赋值有层级结构的数据
2.在template的时候可以获取到除了name, value以外的其他自定义值
3.同步4.1的on方式, 可以使用后置on获取实时数据 


[2018-07-13] v4.0.0.0713
-- bug修复 --
1.修复render使用searchType不生效
2.修复多级联动点击空白处报错
3.修正label上x号的图标
4.修正不同皮肤下复选框的border颜色色值不正确
5.修正clearInput不生效


[2018-07-11] v4.0.0.0711
-- bug修复 --
1.修复使用show-count模式后, 点击全选下拉框高度位置错误
2.修复当xm-select对应ID不存在时的报错问题
3.修复多级联动赋值不存在时出现//的问题
4.修复条目创建时没有传值搜索内容
5.修复条目创建时name取值错误

-- 修改 --
1.修改多选和单选的图标
2.radio模式下的快捷操作内置为清空
3.新增github pages文档, 迁移文档地址, 使用新的方式撰写


[2018-07-10] v4.0.0.0710
-- bug修复 --
1.修正版本号
2.修改下拉方向down时错误
3.删除横向滚动
4.删除all相关代码
5.修复某些情况下label高度缺失

	
[2018-07-06] v4.0.0.0706
-- 新增 --
1.修改固定高度为默认值34px;
2.当固定高度后, 已选择数据可以通过鼠标滚轮横向滚动
3.0702忘记说了, 新增点击分组名称选中该分组下的数据

-- bug修复 --
1.修复form表单不能正常验证

	
[2018-07-04] v4.0.0.0704
-- bug修复 --
1.修复了render方法的错误, 带来了一连串的影响...
2.修复有搜索内容无匹配直接关闭时, 仍显示无匹配项
3.修复当label为空时, 点击title关闭下拉placeholder不显示
4.修复当搜索框在下拉中时, label上仍然有一个50px的空白
5.修复当不开启搜索模式, label上仍然有一个50px的空白
	
	
[2018-07-02] v4.0.0.0702
-- 新增 --
1.重做了render方法, 支持了N多种操作, 比如多选->单选, 单选->多选
2.新增create创建处理, 也许动态创建的value你并不想使用时间戳~~
3.新增template方式, 你可以重新"画"选项结构
4.新增配置项xm-select-search-type, title|dl, 可以自由选择搜索框的显示位置, tips: 投票结果竟然相等
5.新增xm-select-show-count, 可以设置多选label的显示数量, 超出后隐藏
6.表单验证支持lay-verType

--bug修复--
1.修复当多次使用data函数时, 历史label中的数据不清空
2.修复config函数错误, 指定配置不生效

!! 取消对dom的监听, 不在自动渲染新增的select, 如需渲染, 调用formSelects.render
!! 取消formSelects.all.js, 请使用js + css模式
!! 每一次的更新都是为了更好的发展 ^_^


[2018-06-22] v4.0.0.0622
-- 新增 --
1.config新增beforeSearch方法, 用于确定是否触发搜索
2.config新增clearInput配置, 用于确定是否清空搜索内容
3.config新增searchVal配置, 可自定义搜索内容, 触发一次后失效, 优先级大于搜索框
4.btns新增配置, 可以自定义显示[图标/名称/全部, 间隔]
5.新增search方法, 可以使用js随时随地触发搜索;(只针对于远程搜索)

	
[2018-06-20] v4.0.0.0620
--bug修复--
1.修改联动模式下监听on的时候报错
2.修改pane inline模式下 边框消失的问题
3.想了很久, 还是把预置的快捷操作跳过了禁用的选项, 更新后快捷操作将不再操作被禁用的选项

-_- 也许你们真的感觉 config + data 不好用...
你们现在可以在data中写config参数了, 仅此而已, 具体示例查看 #select_data


[2018-06-18] v4.0.0.0618
--新增--
1.新增快捷操作, 可以 (全选,清空,反选,换肤)
2.新增btns方法, 可以自定义快捷操作
3.提供formSelects.all.js与formSelects.js, 其中formSelects.all.js是使用js的方式加载的css, 不需要手动引入, 而formSelects.js需要引入formSelects.css 

--bug修复--
1.搜索模式下, 点击选项后, 清空已输入数据
2.修复远程搜索赋值与取值时的数据异常与显示异常
3.如果是远程数据, 第一次将不会延迟500ms

接下来的formSelects将进入稳定阶段, 主要以bug修复为主 ^_^

	
[2018-06-13] v4.0.0.0613
这次算正式发布版本更新吧, 之前的都是出于完善 + 测试的阶段
--已有功能--
1.基础多选 + 多选分组
2.自定义提示
3.设置选择上限
4.更换友好的皮肤颜色, 当然如果不满意可以自行配置css
5.本地搜索 + 远程搜搜
6.创建不存在的条目
7.联动多选
更多的功能, 请查看文档自行尝试 ^_^

--新增+修改--
1.config中新增beforeSuccess, 可以在success之前处理数据, 格式化成formSelects需要的格式
2.config中新增keyChildren配置, 可配置联动多选的children key
3.新增链式语法, formSelects.config().on().filter().maxTips().disabled()...
4.弱化远程返回格式, 可省略code, msg, data字段, 直接返回数组
5.新增若干示例

--bug修复--
1.修改config中定义searchUrl后不能触发远程数据请求
2.修改on函数中的文档错误, return false是取消本次选择


[2018-05-28] v4
formSelects-v4, 静悄悄的, 愿它能够茁壮成长...


[2018-05-07] v3
formSelects-v3, 高速开发与更新, 功能越来越多了, 代码越来越看不懂了...


[2018-04-20] v2
formSelects-v2, 粗暴的升级了v1...


[2017-08-29] v1
formSelects-v1, 一个简简单单的layui多选...