diff --git a/CHANGELOG.md b/CHANGELOG.md
index abde392..365fb51 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,21 @@
## 更新日志
+### 1.0.10
+
+*2019-10-20*
+
+#### 新增
+
+- 新增`content`配置, 可自定义下拉框HTML, 具体见 [下拉自定义](https://maplemei.gitee.io/xm-select/#/example-plugin/ZP01)
+- 方法`setValue`新增参数`listenOn`, 可以设置是否通过`on`监听
+
+#### Bug fixes
+
+- 修复初始化渲染也会被`on`监听的bug
+- 修复分组模式下, 搜索后分组显示错误
+- 调整分组模式下也可以使用分页, 选项控制
+
+
### 1.0.9
*2019-10-17*
diff --git a/dist/static/2.js b/dist/static/2.js
index ea50068..9ce5a4a 100644
--- a/dist/static/2.js
+++ b/dist/static/2.js
@@ -1 +1 @@
-(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{361:function(e,t,n){e.exports=n.p+"static/wx.f391ad4.jpg"},363:function(e,t,n){"use strict";n.r(t);var a=function(){var e=this.$createElement,t=this._self._c||e;return t("section",{staticClass:"content element-doc"},[this._m(0),this._m(1),t("demo-block",[t("div",[t("p",[this._v("事实证明分页是好使的 ^_^")])]),t("template",{slot:"source"},[t("element-demo0")],1),t("template",{slot:"highlight"},[t("pre",{pre:!0},[t("code",{pre:!0,attrs:{class:"html"}},[this._v('
\n\n\n\n\n\n
```
:::
diff --git a/docs/mds/XM21.md b/docs/mds/XM21.md
index 0349f9d..9e5032c 100644
--- a/docs/mds/XM21.md
+++ b/docs/mds/XM21.md
@@ -1,12 +1,6 @@
## 分组
-
-:::tip
-使用分组时, 不建议开启分页, 也不建议开启选项数量控制!!!
-:::
-
-
### optgroup模式
:::demo 指定选项中的`optgroup`为`true`
@@ -134,3 +128,37 @@ var demo4 = xmSelect.render({
```
:::
+
+
+### 带有分页的分组
+
+:::demo
+```html
+
+
+
+```
+:::
diff --git a/docs/mds/ZP01.md b/docs/mds/ZP01.md
new file mode 100644
index 0000000..e79986d
--- /dev/null
+++ b/docs/mds/ZP01.md
@@ -0,0 +1,53 @@
+## 下拉自定义
+
+
+
+### 下拉表格
+
+至于能干什么, 就看你们的想象了~~
+
+:::demo
+```html
+
+
+
+
+```
+:::
diff --git a/docs/mds/ZP02.md b/docs/mds/ZP02.md
new file mode 100644
index 0000000..23948ee
--- /dev/null
+++ b/docs/mds/ZP02.md
@@ -0,0 +1,88 @@
+## 下拉树
+
+### eleTree
+
+结合 `layui` 插件中心的 `eleTree`, 传送门
+
+
+:::demo
+```html
+
+
+
+
+```
+:::
diff --git a/docs/mds/ZTEST.md b/docs/mds/ZTEST.md
index 8a02bf2..8052d48 100644
--- a/docs/mds/ZTEST.md
+++ b/docs/mds/ZTEST.md
@@ -7,28 +7,29 @@
```
:::
diff --git a/docs/mds/options.md b/docs/mds/options.md
index 5bd851d..1ea71da 100644
--- a/docs/mds/options.md
+++ b/docs/mds/options.md
@@ -8,6 +8,7 @@
| el | 渲染对象, css选择器 | string | - | - |
| language | 语言选择 | string | zn / en | zn |
| data | 显示的数据 | array | - | [ ] |
+| content | 自定义下拉框html | string | - | - |
| initValue | 初始化选中的数据, 需要在data中存在 | array | - | null |
| tips | 默认提示, 类似于placeholder | string | - | 请选择 |
| empty | 空数据提示 | string | - | 暂无数据 |
@@ -38,7 +39,7 @@
| name | 表单提交时的name | string | - | select |
| toolbar | 工具条, 具体看下表 | object | - | - |
| showCount | 展示在下拉框中的最多选项数量 | int | - | 0 |
-| autoRow | 是否开启自动换行(选项过多时) | boolean | - | false |
+| autoRow | 是否开启自动换行(选项过多时) | boolean | true / false | false |
| size | 尺寸 | string | large / medium / small / mini | medium |
@@ -171,7 +172,7 @@ xmSelect.render()后会返回一个xmSelect对象, 可以进行方法调用
| 事件名 | 说明 | 参数 |
| ------ | ------------------ | -------- |
| getValue | 获取当前选中的数据 | (type: 类型), 可选值: name, nameStr, value, valueStr |
-| setValue | 动态设置数据 | (array: 选中的数据, show: 是否展开下拉, 不传默认当前显示状态, 取值: true/false) |
+| setValue | 动态设置数据 | (array: 选中的数据, show: 是否展开下拉,不传默认当前显示状态,取值: true/false, listenOn: 是否触发on的监听, 默认false) |
| append | 追加赋值 | (array: 追加的数据) |
| delete | 删除赋值 | (array: 删除的数据) |
| opened | 主动展开下拉 | - |
diff --git a/docs/mds/question.md b/docs/mds/question.md
index a2ca485..d85f760 100644
--- a/docs/mds/question.md
+++ b/docs/mds/question.md
@@ -22,3 +22,8 @@
- 打开控制台查看是否报错
- 加群: 660408068, 询问
+
+
+### 4.占位标签为什么是div
+
+演示中使用的是div, 不限制标签, 但是不建议使用`select`, 因为`layui`会渲染`select`标签
\ No newline at end of file
diff --git a/docs/plugins/eleTree/eleTree.css b/docs/plugins/eleTree/eleTree.css
new file mode 100755
index 0000000..ee5598c
--- /dev/null
+++ b/docs/plugins/eleTree/eleTree.css
@@ -0,0 +1,168 @@
+/* #region tree */
+.eleTree{
+ position: relative;
+}
+.eleTree-hide,
+.eleTree-search-hide{
+ display: none;
+}
+.eleTree-loadData{
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ z-index: 1;
+ top: 0px;
+}
+.eleTree-loadData .layui-icon{
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%);
+}
+.eleTree-node-content{
+ cursor: pointer;
+ height: 26px;
+ line-height: 1.3;
+ white-space: nowrap;
+}
+.eleTree-node-content:hover,
+.eleTree-node-content.eleTree-node-content-active{
+ background-color: #eee;
+}
+.eleTree-node-content-icon .layui-icon{
+ padding: 6px 3px;
+ color: #c0c4cc;
+ font-size: 12px;
+ display: inline-block;
+ transform: rotate(0deg);
+ transition: transform .3s ease-in-out;
+}
+.eleTree-node-content-icon .layui-icon.icon-rotate{
+ transform: rotate(90deg);
+}
+.eleTree-node-content .layui-form-checkbox[lay-skin=primary] i{
+ width: 13px;
+ height: 14px;
+ line-height: 1.3;
+}
+.eleTree-node-content-label{
+ padding-left: 5px;
+}
+.eleTree-node-content-input{
+ width: 80px;
+ border: 1px solid #e6e6e6;
+ outline: 0;
+ padding: 3px 5px;
+ font-size: 12px;
+}
+
+/* 线条样式 */
+.eleTree-node{
+ position: relative;
+}
+.eleTree-node .eleTree-node-verticalline{
+ position: absolute;
+ width: 0;
+ height: 100%;
+ border: 1px dotted #ccc;
+ z-index: 1;
+}
+.eleTree-node .eleTree-node-horizontalline{
+ position: absolute;
+ height: 0;
+ top: 13px;
+ border: 1px dotted #ccc;
+ z-index: 1;
+}
+
+/* checkbox第三种状态 */
+input.eleTree-hideen[type=checkbox]{
+ display: none;
+}
+.eleTree-checkbox {
+ height: auto!important;
+ line-height: normal!important;
+ min-height: 12px;
+ border: none!important;
+ margin-right: 0;
+ padding-left: 18px;
+ position: relative;
+ display: inline-block;
+}
+.eleTree-checkbox i {
+ left: 0;
+ border: 1px solid #d2d2d2;
+ font-size: 12px;
+ border-radius: 2px;
+ background-color: #fff;
+ -webkit-transition: .1s linear;
+ transition: .1s linear;
+ position: absolute;
+ top: 0;
+ color: #fff;
+ cursor: pointer;
+ text-align: center;
+ width: 13px;
+ height: 14px;
+ line-height: 1.3;
+}
+.eleTree-checkbox i:hover {
+ border-color: #5FB878;
+}
+.eleTree-checkbox-checked i {
+ border-color: #5FB878;
+ background-color: #5FB878;
+ color: #fff;
+}
+.eleTree-checkbox-line:after{
+ content: "";
+ position: relative;
+ width: 8px;
+ height: 1px;
+ background-color: #fff;
+ display: inline-block;
+ top: -4px;
+}
+
+.eleTree-checkbox.eleTree-checkbox-disabled i{
+ cursor: not-allowed;
+ background-color: #f2f6fc;
+ border-color: #dcdfe6;
+ color: #c2c2c2;
+}
+.eleTree-checkbox.eleTree-checkbox-disabled i.eleTree-checkbox-line:after{
+ background-color: #c2c2c2;
+}
+.eleTree-checkbox.eleTree-checkbox-disabled i:hover{
+ border-color: #dcdfe6;
+}
+
+#tree-menu{
+ margin: 0;
+ padding: 2px;
+ position: absolute;
+ background: #f5f5f5;
+ border: 1px solid #979797;
+ box-shadow: 2px 2px 2px #999;
+ display: none;
+ z-index: 20181205;
+}
+#tree-menu li>a{
+ display: block;
+ padding: 0 1em;
+ text-decoration: none;
+ width: auto;
+ color: #000;
+ white-space: nowrap;
+ line-height: 2.4em;
+ text-shadow: 1px 1px 0 #fff;
+ border-radius: 1px;
+}
+#tree-menu li>a:hover{
+ background-color: #e8eff7;
+ box-shadow: 0 0 2px #0a6aa1;
+}
+.tree-menu-bg{
+ background-color: #ccc;
+}
+/* #endregion */
\ No newline at end of file
diff --git a/docs/plugins/eleTree/eleTree.js b/docs/plugins/eleTree/eleTree.js
new file mode 100755
index 0000000..dba9a9c
--- /dev/null
+++ b/docs/plugins/eleTree/eleTree.js
@@ -0,0 +1,1554 @@
+/**
+ * @Name: 基于layui的tree重写
+ * @Author: 李祥
+ * @License:MIT
+ * 最近修改时间: 2019/09/24
+ */
+
+layui.define(["jquery","laytpl"], function (exports) {
+ var $ = layui.jquery;
+ var laytpl = layui.laytpl;
+ var hint = layui.hint();
+
+ var MOD_NAME="eleTree";
+
+ //外部接口
+ var eleTree={
+ //事件监听
+ on: function(events, callback){
+ return layui.onevent.call(this, MOD_NAME, events, callback);
+ },
+ render: function(options) {
+ var inst = new Class(options);
+ return thisTree.call(inst);
+ }
+ }
+
+ var thisTree=function() {
+ var _self=this;
+ var options = _self.config;
+
+ // 暴漏外面的方法
+ return {
+ // 接收两个参数,1. 节点 key 2. 节点数据的数组
+ updateKeyChildren: function(key,data) {
+ if(options.data.length===0) return;
+ return _self.updateKeyChildren.call(_self,key,data);
+ },
+ updateKeySelf: function(key,data) {
+ if(options.data.length===0) return;
+ return _self.updateKeySelf.call(_self,key,data);
+ },
+ remove: function(key) {
+ if(options.data.length===0) return;
+ return _self.remove.call(_self,key);
+ },
+ append: function(key,data) {
+ if(options.data.length===0) return;
+ return _self.append.call(_self,key,data);
+ },
+ insertBefore: function(key,data) {
+ if(options.data.length===0) return;
+ return _self.insertBefore.call(_self,key,data);
+ },
+ insertAfter: function(key,data) {
+ if(options.data.length===0) return;
+ return _self.insertAfter.call(_self,key,data);
+ },
+ // 接收两个 boolean 类型的参数,1. 是否只是叶子节点,默认值为 false 2. 是否包含半选节点,默认值为 false
+ getChecked: function(leafOnly, includeHalfChecked) {
+ if(options.data.length===0) return;
+ return _self.getChecked.call(_self,leafOnly, includeHalfChecked);
+ },
+ // 接收勾选节点数据的数组
+ setChecked: function(data,isReset) {
+ if(options.data.length===0) return;
+ return _self.setChecked.call(_self,data,isReset);
+ },
+ // 取消选中
+ unCheckNodes: function() {
+ if(options.data.length===0) return;
+ return _self.unCheckNodes.call(_self);
+ },
+ unCheckArrNodes: function(data) {
+ if(options.data.length===0) return;
+ return _self.unCheckArrNodes.call(_self,data);
+ },
+ expandAll: function() {
+ if(options.data.length===0) return;
+ return _self.expandAll.call(_self);
+ },
+ expandNode: function(key) {
+ if(options.data.length===0) return;
+ return _self.expandNode.call(_self,key);
+ },
+ unExpandNode: function(key) {
+ if(options.data.length===0) return;
+ return _self.unExpandNode.call(_self,key);
+ },
+ toggleExpandNode: function(key) {
+ if(options.data.length===0) return;
+ return _self.toggleExpandNode.call(_self,key);
+ },
+ unExpandAll: function() {
+ if(options.data.length===0) return;
+ return _self.unExpandAll.call(_self);
+ },
+ reload: function(options) {
+ return _self.reload.call(_self,options);
+ },
+ search: function(value) {
+ return _self.search.call(_self,value);
+ },
+ getAllNodeData: function() {
+ return _self.getAllNodeData.call(_self);
+ }
+ }
+ }
+
+ // 模板渲染
+ var TPL_ELEM=function(options,floor,parentStatus) {
+ return [
+ '{{# for(var i=0;i',
+ function() {
+ // 是否显示连线
+ if(!options.showLine) return '';
+ if(floor!==0){
+ var s=''+
+ '';
+ return s;
+ }else{
+ var s=''+
+ '';
+ return s;
+ }
+ }(),
+ '',
+ '',
+ '',
+ '{{# }else{ }}',
+ 'leaf-icon" style="color: transparent;" >',
+ '{{# } }}'
+ ].join("");
+ return str;
+ }
+ return ['{{# if(!d[i]["'+options.request.children+'"] || d[i]["'+options.request.children+'"].length===0){ }}',
+ 'leaf-icon" style="color: transparent;"',
+ '{{# } }}',
+ '">'
+ ].join("");
+ }(),
+ '',
+ function() {
+ if(options.showCheckbox){
+ var status="";
+ if(options.checkStrictly){
+ status='"0"';
+ }else if(parentStatus==="1"){
+ status='"1" checked';
+ }else if(parentStatus==="2"){
+ status='"2"';
+ }else{
+ status='"0"';
+ }
+ return [
+ '{{# if(d[i]["'+options.request.checked+'"]) { }}',
+ ''
+ ].join("");
+ }
+ return ''
+ }(),
+ '{{d[i]["'+options.request.name+'"]}}',
+ '
',
+ '',
+ '
',
+ '',
+ '{{# } }}'
+ ].join("");
+ }
+
+ var TPL_NoText=function() {
+ return '{{d.emptText}}
';
+ }
+
+ var Class=function(options) {
+ options.response=$.extend({}, this.config.response, options.response);
+ options.request=$.extend({}, this.config.request, options.request);
+ this.config = $.extend({}, this.config, options);
+ this.config.customKey=this.customKeyInit();
+ this.prevClickEle=null;
+ this.nameIndex=1;
+ this.isRenderAllDom=false;
+ this.render();
+ };
+
+ Class.prototype={
+ constructor: Class,
+ config: {
+ elem: "",
+ data: [],
+ emptText: "暂无数据", // 内容为空的时候展示的文本
+ renderAfterExpand: true, // 是否在第一次展开某个树节点后才渲染其子节点
+ highlightCurrent: false, // 是否高亮当前选中节点,默认值是 false。
+ defaultExpandAll: false, // 是否默认展开所有节点
+ expandOnClickNode: true, // 是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。
+ checkOnClickNode: false, // 是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。
+ defaultExpandedKeys: [], // 默认展开的节点的 key 的数组
+ autoExpandParent: true, // 展开子节点的时候是否自动展开父节点
+ showCheckbox: false, // 节点是否可被选择
+ checkStrictly: false, // 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false
+ defaultCheckedKeys: [], // 默认勾选的节点的 key 的数组
+ accordion: false, // 是否每次只打开一个同级树节点展开(手风琴效果)
+ indent: 16, // 相邻级节点间的水平缩进,单位为像素
+ lazy: false, // 是否懒加载子节点,需与 load 方法结合使用
+ load: function() {}, // 加载子树数据的方法,仅当 lazy 属性为true 时生效
+ draggable: false, // 是否开启拖拽节点功能
+ contextmenuList: [], // 启用右键菜单,支持的操作有:"copy","add","edit","remove"
+ searchNodeMethod: null, // 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏
+ showLine: false, // 是否显示连线,默认false
+
+ method: "get",
+ url: "",
+ contentType: "",
+ headers: {},
+ done: null,
+
+ response: {
+ statusName: "code",
+ statusCode: 0,
+ dataName: "data"
+ },
+ request: {
+ name: "label",
+ key: "id",
+ children: "children",
+ disabled: "disabled",
+ checked: "checked",
+ isLeaf: "isLeaf"
+ },
+ customKey: "id", // 自定义key转义,即appKey=>app-id
+ },
+ render: function() {
+ if(this.config.indent>30){
+ this.config.indent=30;
+ }else if(this.config.indent<10){
+ this.config.indent=10;
+ }
+ var options=this.config;
+ options.where=options.where || {};
+ if(!options.elem) return hint.error("缺少elem参数");
+ options.elem=typeof options.elem === "string" ? $(options.elem) : options.elem;
+ this.filter=options.elem.attr("lay-filter");
+ // load加载框
+ options.elem.append('
')
+
+ // 判断加载方式
+ if(options.data.length===0){
+ this.ajaxGetData();
+ }else{
+ this.renderData();
+ }
+ },
+ renderData: function() {
+ var options=this.config;
+ $(this.config.elem).off(); // 取消事件绑定,防止多次绑定事件
+ // 渲染第一层
+ laytpl(TPL_ELEM(options,0)).render(options.data, function(string){
+ options.elem.html(string);
+ });
+ // 懒加载 > 展开所有 > 初始展开项 > 初始渲染所有子节点 > 初始选中项 > 每次点击只渲染当前层(默认)
+ // 判断所有dom是否全部加载
+ if(!options.lazy){
+ if(!options.renderAfterExpand || options.defaultExpandAll || options.defaultExpandedKeys.length>0 || options.defaultCheckedKeys.length>0){
+ this.initialExpandAll(options.data,[],1);
+ }
+ }
+
+ this.eleTreeEvent();
+ this.checkboxRender();
+ this.checkboxEvent();
+ this.defaultChecked();
+ this.nodeEvent();
+ this.rightClickMenu();
+ if(!options.checkStrictly){
+ this.checkboxInit();
+ }
+ },
+ ajaxGetData: function() {
+ var options=this.config;
+ var _self=this;
+ if(!options.url) {
+ laytpl(TPL_NoText()).render(options, function(string){
+ options.elem.html(string);
+ });
+ return;
+ }
+ var data = $.extend({}, options.where);
+ if(options.contentType && options.contentType.indexOf("application/json") == 0){ //提交 json 格式
+ data = JSON.stringify(data);
+ }
+
+ $.ajax({
+ type: options.method || 'get'
+ ,url: options.url
+ ,contentType: options.contentType
+ ,data: data
+ ,dataType: 'json'
+ ,headers: options.headers || {}
+ ,success: function(res){
+ if(res[options.response.statusName] != options.response.statusCode || !res[options.response.dataName]){
+ hint.error("请检查数据格式是否符合规范");
+ typeof options.done === 'function' && options.done(res);
+ return;
+ }
+ options.data=res[options.response.dataName];
+ _self.renderData();
+ typeof options.done === 'function' && options.done(res);
+ }
+ });
+ },
+ reload: function(options) {
+ var _self=this;
+ if(this.config.data && this.config.data.constructor === Array) this.config.data=[];
+ this.config = $.extend({}, this.config, options);
+ // $(this.config.elem).off(); // 取消事件绑定,防止多次绑定事件
+ // reload记录选中的数据
+ // this.getChecked().forEach(function(val) {
+ // if($.inArray(val.key,this.config.defaultCheckedKeys)===-1){
+ // this.config.defaultCheckedKeys.push(val.key);
+ // }
+ // },this);
+ return eleTree.render(this.config)
+ },
+ // 自定义data属性修改,即 appId=>app-id,解决key包含大写的问题
+ customKeyInit: function() {
+ var options=this.config;
+ var key="";
+ for(var i=0;i.eleTree-node-content-icon";
+ options.elem.on("click",expandOnClickNode,function(e) {
+ e.stopPropagation();
+ var eleTreeNodeContent=$(this).parent(".eleTree-node").length===0?$(this).parent(".eleTree-node-content"):$(this);
+ var eleNode=eleTreeNodeContent.parent(".eleTree-node");
+ var sibNode=eleTreeNodeContent.siblings(".eleTree-node-group");
+ var el=eleTreeNodeContent.children(".eleTree-node-content-icon").children(".layui-icon");
+
+ if(el.hasClass("icon-rotate")){
+ // 合并
+ sibNode.hide("fast");
+ el.removeClass("icon-rotate");
+ return;
+ }
+
+ if(sibNode.children(".eleTree-node").length===0){
+ var floor=Number(eleNode.attr("eletree-floor"))+1;
+
+ // 选择祖父
+ var selectParentsFn=function() {
+ if(!options.checkStrictly){
+ var eleNode1=sibNode.children(".eleTree-node").eq(0);
+ if(eleNode1.length!==0){
+ var siblingNode1=eleNode1.siblings(".eleTree-node");
+ var item1=eleNode1.children(".eleTree-node-content").children(".eleTree-hideen").get(0);
+ _self.selectParents(item1,eleNode1,siblingNode1);
+ }
+ }
+ }
+
+ var data=_self.reInitData(eleNode);
+ var d=data.currentData;
+ // 是否懒加载
+ if(options.lazy && el.hasClass("lazy-icon")){
+ el.removeClass("layui-icon-triangle-r").addClass("layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop");
+ options.load(d,function(getData) {
+ // 如果原来有数据则合并,没有则赋值
+ if(d[options.request.children]){
+ d[options.request.children]=d[options.request.children].concat(getData);
+ }else{
+ d[options.request.children]=getData;
+ }
+ var eletreeStatus=eleTreeNodeContent.children("input.eleTree-hideen").attr("eletree-status");
+ if(d[options.request.children] && d[options.request.children].length>0){
+ // 只渲染获取到的数据
+ laytpl(TPL_ELEM(options,floor,eletreeStatus)).render(getData, function(string){
+ sibNode.append(string).show("fast");
+ });
+ }else{
+ el.css("color","transparent").addClass("leaf-icon");
+ }
+ el.removeClass("lazy-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop").addClass("layui-icon-triangle-r icon-rotate");
+
+ // 懒加载子元素选择祖父
+ selectParentsFn();
+ _self.checkboxRender();
+ })
+ }else{
+ var eletreeStatus=eleTreeNodeContent.children("input.eleTree-hideen").attr("eletree-status");
+ if(d[options.request.children] && d[options.request.children].length>0){
+ laytpl(TPL_ELEM(options,floor,eletreeStatus)).render(d[options.request.children], function(string){
+ sibNode.append(string).show("fast");
+ el.addClass("icon-rotate");
+ });
+ // 选择祖父
+ selectParentsFn();
+ _self.checkboxRender();
+ }
+ }
+ }else{
+ // 有子节点则展开子节点
+ sibNode.show("fast");
+ el.addClass("icon-rotate");
+ }
+
+ // 手风琴效果
+ if(options.accordion){
+ var node=eleTreeNodeContent.parent(".eleTree-node").siblings(".eleTree-node");
+ node.children(".eleTree-node-group").hide("fast");
+ node.children(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").removeClass("icon-rotate");
+ }
+ })
+ },
+ // checkbox选中
+ checkboxEvent: function() {
+ var options=this.config;
+ var _self=this;
+ var checkOnClickNode=options.checkOnClickNode?".eleTree-node-content":".eleTree-checkbox";
+ // input添加属性eleTree-status:即input的三种状态,"0":未选中,"1":选中,"2":子孙部分选中
+ options.elem.on("click",checkOnClickNode,function(e) {
+ e.stopPropagation();
+ var eleTreeNodeContent=$(this).parent(".eleTree-node").length===0?$(this).parent(".eleTree-node-content"):$(this);
+ var checkbox=eleTreeNodeContent.children(".eleTree-checkbox");
+ if(checkbox.hasClass("eleTree-checkbox-disabled")) return;
+ // 获取点击所在数据
+ var node=eleTreeNodeContent.parent(".eleTree-node");
+ // var d=_self.reInitData(node).currentData;
+ // 实际的input
+ var inp=checkbox.siblings(".eleTree-hideen").get(0);
+ var childNode=eleTreeNodeContent.siblings(".eleTree-node-group").find("input[name='eleTree-node']");
+
+ // 添加active背景
+ if(_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active");
+ if(options.highlightCurrent) eleTreeNodeContent.addClass("eleTree-node-content-active");
+ _self.prevClickEle=eleTreeNodeContent;
+
+ if(!inp) return;
+
+ if(inp.checked){
+ // 反选自身
+ $(inp).prop("checked",false).attr("eleTree-status","0").removeAttr("data-checked");
+ // 点击祖父层选中子孙层
+ if(!options.checkStrictly){
+ childNode.prop("checked",false).attr("eleTree-status","0").removeAttr("data-checked");
+ }
+
+ }else{
+ // 反选自身
+ $(inp).prop("checked",true).attr("eleTree-status","1");
+ // 点击祖父层选中子孙层
+ if(!options.checkStrictly){
+ childNode.prop("checked",true).attr("eleTree-status","1");
+ }
+ }
+
+ var eleNode=eleTreeNodeContent.parent(".eleTree-node");
+ // 点击子孙层选中祖父层(递归)
+ if(!options.checkStrictly){
+ var siblingNode=eleNode.siblings(".eleTree-node");
+ // 点击子孙层选中祖父层(递归)
+ _self.selectParents(inp,eleNode,siblingNode);
+ }
+
+ _self.checkboxRender();
+
+ layui.event.call(inp, MOD_NAME, 'nodeChecked('+ _self.filter +')', {
+ node: eleNode,
+ data: _self.reInitData(eleNode),
+ isChecked: inp.checked
+ });
+ })
+ },
+ // 对后台数据有 checked:true 的默认选中项渲染父子层
+ checkboxInit: function() {
+ var options=this.config;
+ var _self=this;
+ options.elem.find("input[data-checked]").each(function(index,item) {
+ var checkboxEl=$(item).siblings(".eleTree-checkbox");
+ var childNode=checkboxEl.parent(".eleTree-node-content").siblings(".eleTree-node-group").find("input[name='eleTree-node']");
+ // 选择当前
+ $(item).prop("checked","checked").attr("eleTree-status","1");
+ checkboxEl.addClass("eleTree-checkbox-checked");
+ checkboxEl.children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
+ if(options.checkStrictly) return;
+ // 选择子孙
+ childNode.prop("checked","checked").attr("eleTree-status","1");
+ childNode.siblings(".eleTree-checkbox").addClass("eleTree-checkbox-checked");
+ childNode.siblings(".eleTree-checkbox").children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
+
+ // 选择祖父
+ var eleNode=checkboxEl.parent(".eleTree-node-content").parent(".eleTree-node");
+ var siblingNode=eleNode.siblings(".eleTree-node");
+ _self.selectParents(item,eleNode,siblingNode);
+ })
+ _self.checkboxRender();
+ },
+ // 通过子元素选中祖父元素
+ selectParents: function(inp,eleNode,siblingNode) {
+ // inp: 实际input(dom元素)
+ // eleNode: input父层类(.eleTree-node)
+ // siblingNode: 父层同级兄弟
+ while (Number(eleNode.attr("eletree-floor"))!==0) {
+ // 同级input状态存入数组
+ var arr=[];
+ arr.push($(inp).attr("eleTree-status"));
+ siblingNode.each(function(index,item) {
+ var siblingIsChecked=$(item).children(".eleTree-node-content").children("input[name='eleTree-node']").attr("eleTree-status");
+ arr.push(siblingIsChecked);
+ })
+ // 父元素的实际input
+ var parentInput=eleNode.parent(".eleTree-node-group").siblings(".eleTree-node-content").children("input[name='eleTree-node']");
+ // 父元素的checkbox替代
+ var parentCheckbox=parentInput.siblings(".eleTree-checkbox");
+ // 子都选中则选中父
+ if(arr.every(function(val) {
+ return val==="1";
+ })){
+ parentInput.prop("checked",true).attr("eleTree-status","1");
+ }
+ // 子有一个未选中则checkbox第三种状态
+ if(arr.some(function(val) {
+ return val==="0" || val==="2";
+ })){
+ parentInput.attr("eleTree-status","2");
+ }
+ // 子全部未选中则取消父选中(并且取消第三种状态)
+ if(arr.every(function(val) {
+ return val==="0";
+ })){
+ parentInput.prop("checked",false);
+ parentInput.attr("eleTree-status","0");
+ }
+
+ var parentNode=eleNode.parents("[eletree-floor='"+(Number(eleNode.attr("eletree-floor"))-1)+"']");
+ var parentCheckbox=parentNode.children(".eleTree-node-content").children("input[name='eleTree-node']").get(0);
+ var parentSiblingNode=parentNode.siblings(".eleTree-node");
+ eleNode=parentNode;
+ inp=parentCheckbox;
+ siblingNode=parentSiblingNode;
+ }
+ },
+ // 初始展开所有
+ initialExpandAll: function(data,arr,floor,isMethodsExpandAll) {
+ var options=this.config;
+ var _self=this;
+ this.isRenderAllDom=true;
+ data.forEach(function(val,index) {
+ arr.push(index);
+ if(val[options.request.children] && val[options.request.children].length>0){
+ var el=options.elem.children(".eleTree-node").eq(arr[0]).children(".eleTree-node-group");
+ for(var i=1;i0) {
+ // 继续展开祖父层
+ var f=function(eleP) {
+ if(options.autoExpandParent){
+ eleP.parents(".eleTree-node").each(function(i,item) {
+ if($(item).data(options.request.key)){
+ $(item).children(".eleTree-node-group").show().siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").addClass("icon-rotate");
+ }
+ })
+ }
+ }
+ // 展开指定id项
+ var id=el.parent(".eleTree-node").data(options.request.key);
+ if($.inArray(id,options.defaultExpandedKeys)!==-1){
+ // 直接展开子节点
+ el.show().siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").addClass("icon-rotate");
+ // 展开子项是否继续展开祖父项
+ f(el.parent(".eleTree-node[data-"+options.customKey+"]"));
+ }else{
+ // 如当前节点的子节点有展开项,则展开当前子节点的祖父层
+ el.children(".eleTree-node").each(function(index, item) {
+ var id=$(item).data(options.request.key);
+ if($.inArray(id,options.defaultExpandedKeys)!==-1){
+ f($(item));
+ return false;
+ }
+ })
+ }
+ }
+ });
+ floor++;
+ _self.initialExpandAll(val[options.request.children],arr,floor,isMethodsExpandAll);
+ floor--;
+ }
+ // 重置数组索引
+ arr.pop();
+ })
+ },
+ // 选中单个节点
+ checkedOneNode: function(nodeContent){
+ var options=this.config;
+ var inp=nodeContent.children("input.eleTree-hideen").get(0);
+ $(inp).prop("checked",true).attr("eleTree-status","1");
+
+ if(options.checkStrictly) return;
+
+ // 点击祖父层选中子孙层
+ var childNode=nodeContent.siblings(".eleTree-node-group").find("input[name='eleTree-node']");
+ childNode.prop("checked",true).attr("eleTree-status","1");
+
+ var eleNode=nodeContent.parent(".eleTree-node");
+ var siblingNode=eleNode.siblings(".eleTree-node");
+ // 点击子孙层选中祖父层(递归)
+ this.selectParents(inp,eleNode,siblingNode);
+ },
+ // 初始默认选中
+ defaultChecked: function(dataChecked) {
+ var options=this.config;
+ var _self=this;
+ var arr=dataChecked || options.defaultCheckedKeys;
+ if(arr.length===0){
+ return false;
+ }
+ arr.forEach(function(val,index) {
+ var nodeContent=options.elem.find("[data-"+options.customKey+"='"+val+"']").children(".eleTree-node-content");
+ nodeContent.length>0 && _self.checkedOneNode(nodeContent);
+ })
+ this.checkboxInit();
+ },
+ // 自定义checkbox解析
+ checkboxRender: function() {
+ var options=this.config;
+ options.elem.find(".eleTree-checkbox").remove();
+ options.elem.find("input.eleTree-hideen[type=checkbox]").each(function(index,item){
+ if($(item).hasClass("eleTree-disabled")){
+ $(item).after('
');
+ }else{
+ $(item).after('
');
+ }
+
+ var checkbox=$(item).siblings(".eleTree-checkbox");
+ if($(item).attr("eletree-status")==="1"){
+ checkbox.addClass("eleTree-checkbox-checked");
+ checkbox.children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line");
+ }else if($(item).attr("eletree-status")==="0"){
+ checkbox.removeClass("eleTree-checkbox-checked");
+ checkbox.children("i").removeClass("layui-icon-ok eleTree-checkbox-line");
+ }else if($(item).attr("eletree-status")==="2"){
+ checkbox.addClass("eleTree-checkbox-checked");
+ checkbox.children("i").removeClass("layui-icon-ok").addClass("eleTree-checkbox-line");
+ }
+
+ })
+ },
+ // 通过dom节点找对应数据
+ reInitData: function(node) {
+ var options=this.config;
+ var i=node.index();
+ var floor=Number(node.attr("eletree-floor"));
+ var arr=[]; // 节点对应的index
+ while (floor>=0) {
+ arr.push(i);
+ floor=floor-1;
+ node=node.parents("[eletree-floor='"+floor+"']");
+ i=node.index();
+ }
+ arr=arr.reverse();
+ var oData=this.config.data;
+ // 当前节点的父节点数据
+ var parentData=oData[arr[0]];
+ // 当前节点的data数据
+ var d = oData[arr[0]];
+ for(var j = 1; j0){
+ fn(data[obj.i][options.request.children]);
+ }
+ }else{
+ callback(data,obj);
+ }
+ }
+ }
+ fn(options.data);
+ },
+ updateKeyChildren: function(key,data) {
+ var options=this.config;
+ var node=options.elem.find("[data-"+options.customKey+"='"+key+"']");
+ var floor=Number(node.attr("eletree-floor"))+1;
+ var _self=this;
+
+ this.keySearchToOpera(key,function(d,obj) {
+ // 数据更新
+ d[obj.i][options.request.children]=data;
+ // dom更新
+ node.length!==0 && laytpl(TPL_ELEM(options,floor)).render(data, function(string){
+ $(node).children(".eleTree-node-group").empty().append(string);
+ options.defaultExpandAll && $(node).children(".eleTree-node-group").show();
+ });
+ _self.unCheckNodes(true);
+ _self.defaultChecked();
+ });
+ },
+ updateKeySelf: function(key,data) {
+ var options=this.config;
+ var node=options.elem.find("[data-"+options.customKey+"='"+key+"']").children(".eleTree-node-content");
+ var floor=Number(node.attr("eletree-floor"))+1;
+ data[options.request.name] && node.children(".eleTree-node-content-label").text(data[options.request.name]);
+ data[options.request.disabled] && node.children(".eleTree-hideen").addClass("eleTree-disabled")
+ .siblings(".eleTree-checkbox").addClass("eleTree-checkbox-disabled");
+ // 数据更新
+ var getData=this.keySearchToOpera(key,function(d,obj) {
+ data[options.request.key]=d[obj.i][options.request.key];
+ data[options.request.children]=d[obj.i][options.request.children];
+ d[obj.i]=$.extend({},d[obj.i],data);
+ console.log(options.data);
+ });
+ },
+ remove: function(key) {
+ var options=this.config;
+ var node=options.elem.find("[data-"+options.customKey+"='"+key+"']");
+ var pElem=node.parent(".eleTree-node-group");
+ // 数据删除
+ this.keySearchToOpera(key,function(data,obj) {
+ data.splice(obj.i,1);
+ obj.i--;
+ obj.len--;
+
+ node.length!==0 && options.elem.find("[data-"+options.customKey+"='"+key+"']").remove();
+ if(pElem.children(".eleTree-node").length===0){
+ pElem.siblings(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon").css("color", "transparent");
+ }
+ });
+ this.unCheckNodes(true);
+ this.defaultChecked();
+ this.checkboxInit();
+ },
+ append: function(key,data) {
+ var options=this.config;
+ // 如果不传key,则直接添加到根节点
+ if(typeof key==="object" && key!==null){
+ data=key;
+ key=null;
+ }
+ if(key===null || key===""){
+ options.data.push(data);
+ laytpl(TPL_ELEM(options,0,"0")).render([data], function(string){
+ $(options.elem).append(string);
+ $(options.elem).children(".eleTree-node:last").show();
+ });
+ this.checkboxRender();
+ return;
+ }
+ // 传key则添加到子节点
+ var node=options.elem.find("[data-"+options.customKey+"='"+key+"']");
+ var floor=Number(node.attr("eletree-floor"))+1;
+ // 数据更新
+ this.keySearchToOpera(key,function(d,obj) {
+ if(d[obj.i][options.request.children]){
+ d[obj.i][options.request.children].push(data);
+ }else{
+ d[obj.i][options.request.children]=[data];
+ }
+ var arr=d[obj.i][options.request.children];
+ var icon=node.children(".eleTree-node-content").find(".eleTree-node-content-icon .layui-icon");
+ // 添加之后长度为1,则原来没有三角,添加三角
+ if(arr.length===1){
+ icon.removeAttr("style");
+ }
+ // 判断原来是否没有展开
+ if(!icon.hasClass("icon-rotate")){
+ var expandOnClickNode=options.expandOnClickNode?node.children(".eleTree-node-content"):node.children(".eleTree-node-content").children(".eleTree-node-content-icon");
+ expandOnClickNode.trigger("click");
+ }
+ // 判断节点是否已存在
+ var isExist=false;
+ node.children(".eleTree-node-group").children(".eleTree-node").each(function(index,item){
+ if(data[options.request.key]==$(item).data(options.request.key)){
+ isExist=true;
+ }
+ })
+ if(!isExist){
+ var len=arr.length;
+ var eletreeStatus=node.children(".eleTree-node-content").children("input.eleTree-hideen").attr("eletree-status");
+ eletreeStatus=eletreeStatus==="2" ? "0" : eletreeStatus;
+ node.length!==0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render([arr[len-1]], function(string){
+ node.children(".eleTree-node-group").append(string).show();
+ });
+ }
+
+ });
+ this.checkboxRender();
+ },
+ insertBefore: function(key,data) {
+ var options=this.config;
+ var node=options.elem.find("[data-"+options.customKey+"='"+key+"']");
+ var floor=Number(node.attr("eletree-floor"));
+ // 数据更新
+ this.keySearchToOpera(key,function(d,obj) {
+ d.splice(obj.i,0,data);
+ obj.i++;
+ obj.len++;
+ var eletreeStatus=node.parent(".eleTree-node-group").length===0 ? "0" : node.parent(".eleTree-node-group").parent(".eleTree-node")
+ .children(".eleTree-node-content").children("input.eleTree-hideen").attr("eletree-status");
+ eletreeStatus=eletreeStatus==="2" ? "0" : eletreeStatus;
+ node.length!==0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render([data], function(string){
+ node.before(string).prev(".eleTree-node");
+ });
+ });
+ this.checkboxRender();
+ },
+ insertAfter: function(key,data) {
+ var options=this.config;
+ var node=options.elem.find("[data-"+options.customKey+"='"+key+"']");
+ var floor=Number(node.attr("eletree-floor"));
+ // 数据更新
+ this.keySearchToOpera(key,function(d,obj) {
+ d.splice(obj.i+1,0,data);
+ obj.i++;
+ obj.len++;
+ var eletreeStatus=node.parent(".eleTree-node-group").length===0 ? "0" : node.parent(".eleTree-node-group").parent(".eleTree-node")
+ .children(".eleTree-node-content").children("input.eleTree-hideen").attr("eletree-status");
+ eletreeStatus=eletreeStatus==="2" ? "0" : eletreeStatus;
+ node.length!==0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render([data], function(string){
+ $(node).after(string).next(".eleTree-node");
+ });
+ });
+ this.checkboxRender();
+ // if(!options.lazy){
+ // if(!options.renderAfterExpand || options.defaultExpandAll || options.defaultExpandedKeys.length>0){
+ // this.initialExpandAll(options.data,[],1);
+ // }
+ // }
+ },
+ getChecked: function(leafOnly, includeHalfChecked) {
+ var options=this.config
+ ,el
+ ,arr=[];
+ leafOnly=leafOnly || false;
+ includeHalfChecked=includeHalfChecked || false;
+ if(leafOnly){
+ el=options.elem.find(".layui-icon.leaf-icon").parent(".eleTree-node-content-icon")
+ .siblings("input.eleTree-hideen[eletree-status='1']");
+ }else if(includeHalfChecked){
+ el=options.elem.find("input.eleTree-hideen[eletree-status='1'],input.eleTree-hideen[eletree-status='2']");
+ }else{
+ el=options.elem.find("input.eleTree-hideen[eletree-status='1']");
+ }
+ el.each(function(index,item) {
+ var obj={};
+ var id=$(item).parent(".eleTree-node-content").parent(".eleTree-node").data(options.request.key);
+ var label=$(item).siblings(".eleTree-node-content-label").text();
+ obj[options.request.key]=id;
+ obj[options.request.name]=label;
+ obj.elem=item;
+ obj.othis=$(item).siblings(".eleTree-checkbox").get(0)
+ arr.push(obj);
+ })
+ return arr;
+ },
+ setChecked: function(arr,isReset) {
+ var options=this.config;
+ isReset=isReset || false;
+ if(isReset){
+ this.unCheckNodes();
+ options.defaultCheckedKeys=$.extend([],arr);
+ }else{
+ this.unCheckNodes(true);
+ arr.forEach(function(val) {
+ if($.inArray(val,options.defaultCheckedKeys)===-1){
+ options.defaultCheckedKeys.push(val);
+ }
+ })
+ }
+ this.defaultChecked();
+ },
+ unCheckNodes: function(_internal) {
+ _internal=_internal || false; // _internal: 是否内部调用
+ var options=this.config;
+ options.elem.find("input.eleTree-hideen[eletree-status='1'],input.eleTree-hideen[eletree-status='2']").each(function(index,item) {
+ $(item).attr("eletree-status","0").prop("checked",false);
+ // 如果外部的取消选中,则所有的记录全部取消
+ if(!_internal){
+ $(item).removeAttr("data-checked");
+ }
+ });
+ this.checkboxRender();
+ },
+ unCheckArrNodes: function(arr) {
+ var options=this.config;
+ var dataChecked=[];
+ options.elem.find(".eleTree-hideen[eletree-status='1']").each(function(index,item) {
+ var id=$(item).parent(".eleTree-node-content").parent(".eleTree-node").data(options.request.key);
+ // 获取所有被选中项,并去除arr中包含的数据
+ if(arr.some(function(val) {
+ return val==id;
+ })){
+ // 如果id在arr数组中,则清除dom上面的checked数据
+ $(item).removeAttr("data-checked");
+ return;
+ }
+ dataChecked.push(id);
+ })
+
+ // 更新defaultCheckedKeys数据
+ for(var j=0;j.layui-icon").addClass("icon-rotate")
+ .parent(".eleTree-node-content-icon").parent(".eleTree-node-content")
+ .siblings(".eleTree-node-group").show();
+ }
+ options.elem.children(".eleTree-node").children(".eleTree-node-group").empty();
+ this.initialExpandAll(options.data,[],1,true);
+ this.unCheckNodes(true);
+ this.defaultChecked();
+ this.checkboxInit();
+ },
+ // 展开某节点的所有子节点
+ expandNode: function(key) {
+ var options=this.config;
+ var parentsEl=options.elem.find("[data-"+options.customKey+"='"+key+"']");
+ var isExpand=parentsEl.children(".eleTree-node-content").find(".eleTree-node-content-icon>.layui-icon.layui-icon-triangle-r").hasClass("icon-rotate");
+ var parentGroup=parentsEl.find(".eleTree-node-group");
+ // 判断是否已经展开
+ if(isExpand) return false;
+ // 判断子节点是否已经渲染(目前只判断所有子节点是否已经全部渲染,而不是当前子节点是否全部渲染)
+ if(this.isRenderAllDom){
+ parentGroup.show("fast");
+ parentsEl.find(".layui-icon.layui-icon-triangle-r").addClass("icon-rotate");
+ return false;
+ }
+ if(options.lazy) return hint.error("展开所有子节点方法暂不支持懒加载");
+
+ var data=this.reInitData(parentsEl);
+ var d=data.currentData;
+ var floor=Number(parentsEl.attr("eletree-floor"))+1;
+ var fn=function(data,arr,floor) {
+ data.forEach(function(val,index) {
+ arr.push(index);
+ if(val[options.request.children] && val[options.request.children].length>0){
+ var el=parentsEl.children(".eleTree-node-group");
+ for(var i=1;i.layui-icon.layui-icon-triangle-r").hasClass("icon-rotate");
+ // 判断是否已经合并
+ if(!isExpand) return false;
+ parentsEl.find(".eleTree-node-group").hide("fast");
+ parentsEl.find(".layui-icon.layui-icon-triangle-r").removeClass("icon-rotate");
+ },
+ // 切换某节点的所有子节点的展开合并状态
+ toggleExpandNode: function(key) {
+ var options=this.config;
+ var parentsEl=options.elem.find("[data-"+options.customKey+"='"+key+"']");
+ var isExpand=parentsEl.children(".eleTree-node-content").find(".eleTree-node-content-icon>.layui-icon.layui-icon-triangle-r").hasClass("icon-rotate");
+ if(isExpand){
+ this.unExpandNode(key);
+ }else{
+ this.expandNode(key);
+ }
+ },
+ // 节点事件
+ nodeEvent: function() {
+ var _self=this;
+ var options=this.config;
+ // 节点被点击的回调事件
+ options.elem.on("click",".eleTree-node-content",function(e) {
+ var eleNode=$(this).parent(".eleTree-node");
+ var eleTreeNodeContent=eleNode.children(".eleTree-node-content");
+ // 添加active背景
+ if(_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active");
+ if(options.highlightCurrent) eleTreeNodeContent.addClass("eleTree-node-content-active");
+ _self.prevClickEle=eleTreeNodeContent;
+
+ $("#tree-menu").hide().remove();
+ layui.event.call(eleNode, MOD_NAME, 'nodeClick('+ _self.filter +')', {
+ node: eleNode,
+ data: _self.reInitData(eleNode),
+ event: e
+ });
+ })
+ // 节点右键的回调事件
+ options.elem.on("contextmenu",".eleTree-node-content",function(e) {
+ var eleNode=$(this).parent(".eleTree-node");
+ layui.event.call(eleNode, MOD_NAME, 'nodeContextmenu('+ _self.filter +')', {
+ node: eleNode,
+ data: _self.reInitData(eleNode),
+ event: e
+ });
+ })
+ // 节点被拖拽的回调事件
+ options.draggable && options.elem.on("mousedown",".eleTree-node-content",function(e) {
+ var time=0;
+ var eleNode=$(this).parent(".eleTree-node");
+ var eleFloor=Number(eleNode.attr("eletree-floor"));
+ var groupNode=eleNode.parent(".eleTree-node-group");
+
+ e.stopPropagation();
+ options.elem.css("user-select","none");
+ var cloneNode=eleNode.clone(true);
+ var temNode=eleNode.clone(true);
+
+ var x=e.clientX-options.elem.offset().left;
+ var y=e.clientY-options.elem.offset().top;
+ options.elem.append(cloneNode);
+ cloneNode.css({
+ "display": "none",
+ "opacity": 0.7,
+ "position": "absolute",
+ "background-color": "#f5f5f5",
+ "width": "100%"
+ })
+
+ var currentData=_self.reInitData(eleNode);
+
+ var isStop=false;
+
+ $(document).on("mousemove",function(e) {
+ // t为了区别click事件
+ time++;
+ if(time>2){
+ var xx=e.clientX-options.elem.offset().left+10;
+ var yy=e.clientY-options.elem.offset().top+$(document).scrollTop()-5; // 加上浏览器滚动高度
+
+ cloneNode.css({
+ display: "block",
+ left: xx+"px",
+ top: yy+"px"
+ })
+ }
+ }).on("mouseup",function(e) {
+ $(document).off("mousemove").off("mouseup");
+ var target=$(e.target).parents(".eleTree-node").eq(0);
+ cloneNode.remove();
+ options.elem.css("user-select","auto");
+
+
+ // 当前点击的是否时最外层
+ var isCurrentOuterMost=eleNode.parent().get(0).isEqualNode(options.elem.get(0))
+ // 目标是否时最外层
+ var isTargetOuterMost=$(e.target).get(0).isEqualNode(options.elem.get(0))
+ if(isTargetOuterMost){
+ target=options.elem;
+ }
+ // 判断是否超出边界
+ if(target.parents(options.elem).length===0 && !isTargetOuterMost){
+ return;
+ }
+ // 判断初始与结束是否是同一个节点
+ if(target.get(0).isEqualNode(eleNode.get(0))){
+ return;
+ }
+ // 判断是否是父节点放到子节点
+ var tFloor=target.attr("eletree-floor");
+ var isInChild=false;
+ eleNode.find("[eletree-floor='"+tFloor+"']").each(function() {
+ if(this.isEqualNode(target.get(0))){
+ isInChild=true;
+ }
+ })
+ if(isInChild){
+ return;
+ }
+
+ var targetData=_self.reInitData(target);
+ layui.event.call(target, MOD_NAME, 'nodeDrag('+ _self.filter +')', {
+ current: {
+ node: eleNode,
+ data: currentData
+ },
+ target: {
+ node: target,
+ data: targetData
+ },
+ stop: function() {
+ isStop=true;
+ }
+ });
+ // 拖拽是否取消
+ if(isStop){
+ return false;
+ }
+
+ // 数据更改
+ var currList=currentData.parentData.data[options.request.children]
+ var currIndex=currentData.parentData.childIndex
+ var currData=currentData.currentData;
+ var tarData=targetData.currentData;
+ // 当前是否是最外层
+ isCurrentOuterMost ? options.data.splice(currIndex,1) : currList.splice(currIndex,1)
+ // 目标是否是最外层
+ isTargetOuterMost ? options.data.push(currData) : (function() {
+ !tarData[options.request.children] ? tarData[options.request.children]=[] : "";
+ tarData[options.request.children].push(currData);
+ })()
+
+ // dom互换
+ eleNode.remove();
+ var floor=null;
+ // 最外层判断
+ if(isTargetOuterMost){
+ target.append(temNode);
+ floor=0;
+ }else{
+ target.children(".eleTree-node-group").append(temNode);
+ floor=Number(target.attr("eletree-floor"))+1;
+ }
+ // 加floor和padding
+ temNode.attr("eletree-floor",String(floor));
+ temNode.children(".eleTree-node-content").css("padding-left",floor*options.indent+"px");
+ // 计算线条的left
+ if(options.showLine){
+ // 判断目标是否是最外层,是的话隐藏线条
+ if(floor===0){
+ temNode.children(".eleTree-node-verticalline,.eleTree-node-horizontalline").hide();
+ }else{
+ temNode.children(".eleTree-node-verticalline,.eleTree-node-horizontalline").css("left",options.indent*(floor-1)+9+"px").show();
+ }
+ }
+ // 通过floor差值计算子元素的floor
+ var countFloor=eleFloor-floor;
+ temNode.find(".eleTree-node").each(function(index,item) {
+ var f=Number($(item).attr("eletree-floor"))-countFloor;
+ $(item).attr("eletree-floor",String(f));
+ $(item).children(".eleTree-node-content").css("padding-left",f*options.indent+"px");
+ options.showLine && $(item).children(".eleTree-node-verticalline,.eleTree-node-horizontalline").css("left",options.indent*(f-1)+9+"px").show();
+ })
+ // 原dom去三角
+ var leaf=groupNode.children(".eleTree-node").length===0;
+ leaf && groupNode.siblings(".eleTree-node-content")
+ .children(".eleTree-node-content-icon").children(".layui-icon")
+ .removeClass("icon-rotate").css("color","transparent");
+ // 当前的增加三角
+ var cLeaf=target.children(".eleTree-node-group").children(".eleTree-node").length===1;
+ cLeaf && target.children(".eleTree-node-content")
+ .children(".eleTree-node-content-icon").children(".layui-icon")
+ .addClass("icon-rotate").removeAttr("style");
+ // 判断当前是否需要显示
+ var isShowNode=target.children(".eleTree-node-content").find(".layui-icon").hasClass("icon-rotate");
+ (isTargetOuterMost || isShowNode) && target.children(".eleTree-node-group").show();
+
+ _self.unCheckNodes(true);
+ _self.defaultChecked();
+ _self.checkboxInit();
+ })
+ })
+ },
+ rightClickMenu: function() {
+ var _self=this;
+ var options=this.config;
+ if(options.contextmenuList.length<=0){
+ return;
+ }
+ $(document).on("click",function() {
+ $("#tree-menu").hide().remove();
+ });
+
+ var customizeMenu=[]; // 用户自定义的
+ var internalMenu=["copy","add","add.async","insertBefore","insertAfter","append","edit","edit.async","remove","remove.async"]; // 系统自带的
+ var customizeStr='';
+ options.contextmenuList.forEach(function(val) {
+ if($.inArray(val,internalMenu)===-1){
+ customizeMenu.push(val);
+ customizeStr+=''+(val.text || val)+'';
+ }
+ })
+ var menuStr=[''].join("");
+ this.treeMenu=$(menuStr);
+ options.elem.off("contextmenu").on("contextmenu",".eleTree-node-content",function(e) {
+ var that=this;
+ e.stopPropagation();
+ e.preventDefault();
+ // 添加active背景
+ if(_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active");
+ $(this).addClass("eleTree-node-content-active");
+ var eleNode=$(this).parent(".eleTree-node");
+ var nodeData=_self.reInitData(eleNode);
+
+ // 菜单位置
+ $(document.body).after(_self.treeMenu);
+ $("#tree-menu").find("li.append,li.insertAfter,li.insertBefore").hide();
+ $("#tree-menu").find(":not(li.append,li.insertAfter,li.insertBefore)").show();
+ $("#tree-menu").css({
+ left: e.clientX+$(document).scrollLeft(),
+ top: e.clientY+$(document).scrollTop()
+ }).show();
+ // 复制
+ $("#tree-menu li.copy").off().on("click",function() {
+ var el = $(that).children(".eleTree-node-content-label").get(0);
+ var selection = window.getSelection();
+ var range = document.createRange();
+ range.selectNodeContents(el);
+ selection.removeAllRanges();
+ selection.addRange(range);
+ document.execCommand('Copy', 'false', null);
+ selection.removeAllRanges();
+ });
+ // 新增
+ $("#tree-menu li.add").off().on("click",function(e) {
+ e.stopPropagation();
+ $(this).hide().siblings("li:not(.append,.insertAfter,.insertBefore)").hide();
+ $(this).siblings(".append,li.insertAfter,li.insertBefore").show();
+ })
+ // 添加的默认数据
+ var obj={};
+ obj[options.request.key]=Date.now();
+ obj[options.request.name]="未命名"+_self.nameIndex;
+ if(options.lazy){
+ obj[options.request.isLeaf]=true;
+ }
+
+ var arr=["Append","InsertBefore","InsertAfter"];
+ arr.forEach(function(val) {
+ var s=val[0].toLocaleLowerCase()+val.slice(1,val.length);
+ $("#tree-menu li."+s).off().on("click",function(e) {
+ var node=$(that).parent(".eleTree-node");
+ var key=node.data(options.request.key);
+ var isStop=false;
+ var s=val[0].toLocaleLowerCase()+val.slice(1,val.length);
+ // 每次只能添加一条数据,不可以批量添加
+ _self[s](key,obj);
+ var nodeArr=[];
+ node.children(".eleTree-node-group").children(".eleTree-node").each(function(i,itemNode) {
+ nodeArr.push(itemNode);
+ })
+ node.siblings(".eleTree-node").each(function(i,itemNode) {
+ nodeArr.push(itemNode);
+ })
+ $.each(nodeArr, function(i,itemNode) {
+ if(obj[options.request.key]===$(itemNode).data(options.request.key)){
+ var label=$(itemNode).children(".eleTree-node-content").children(".eleTree-node-content-label").hide();
+ var text=label.text();
+ var inp="";
+ label.after(inp);
+
+ label.siblings(".eleTree-node-content-input").focus().select().off().on("blur",function() {
+ var v=$(this).val();
+ obj[options.request.name]=v;
+ var inpThis=this;
+
+ layui.event.call(node, MOD_NAME, 'node'+val+'('+ _self.filter +')', {
+ node: node,
+ data: nodeData.currentData,
+ newData: obj,
+ // 重新设置数据
+ setData: function(o) {
+ // obj[options.request.key]=Date.now();
+ obj[options.request.name]=v;
+ if(options.lazy){
+ obj[options.request.isLeaf]=true;
+ }
+ var newObj=$.extend({},obj,o);
+ this.newData=newObj;
+ // 修改数据
+ var d=_self.reInitData($(itemNode)).currentData;
+ d[options.request.name]=newObj[options.request.name];
+ d[options.request.key]=newObj[options.request.key];
+ // 修改dom
+ $(inpThis).siblings(".eleTree-node-content-label").text(newObj[options.request.name]).show();
+ $(itemNode).attr("data-"+options.customKey,newObj[options.request.key]); // 改变页面上面的显示的key,之后可以获取dom
+ $(itemNode).data(options.request.key,newObj[options.request.key]); // 改变data数据,之后可以通过data获取key
+ $(inpThis).remove();
+
+ _self.nameIndex++;
+ isStop=true;
+ },
+ // 停止添加
+ stop: function() {
+ isStop=true;
+ this.newData={};
+ _self.remove(obj[options.request.key]);
+ }
+ });
+
+ // 不是异步添加
+ if($.inArray("add.async",options.contextmenuList)===-1){
+ if(isStop) return;
+ // 修改数据
+ _self.reInitData($(itemNode)).currentData[options.request.name]=v;
+ // 修改dom
+ $(this).siblings(".eleTree-node-content-label").text(v).show();
+ $(this).remove();
+
+ _self.nameIndex++;
+ }
+ }).on("mousedown",function(e) {
+ // 防止input拖拽
+ e.stopPropagation();
+ }).on("click",function(e) {
+ e.stopPropagation();
+ })
+ }
+ })
+ })
+ })
+
+ // 编辑
+ $("#tree-menu li.edit").off().on("click",function(e) {
+ e.stopPropagation();
+ $("#tree-menu").hide().remove();
+ var node=$(that).parent(".eleTree-node");
+ var key=node.data(options.request.key);
+ var label=$(that).children(".eleTree-node-content-label").hide();
+ var text=label.text();
+ var inp="";
+ label.after(inp);
+ label.siblings(".eleTree-node-content-input").focus().select().off().on("blur",function() {
+ var val=$(this).val();
+ var isStop=false;
+ var inpThis=this;
+ layui.event.call(node, MOD_NAME, 'nodeEdit('+ _self.filter +')', {
+ node: node,
+ value: val,
+ data: nodeData.currentData,
+ // 停止添加
+ stop: function() {
+ isStop=true;
+ $(inpThis).siblings(".eleTree-node-content-label").show();
+ $(inpThis).remove();
+ },
+ async: function() {
+ if(isStop) return;
+ // 修改数据
+ _self.reInitData(eleNode).currentData[options.request.name]=val;
+ // 修改dom
+ $(inpThis).siblings(".eleTree-node-content-label").text(val).show();
+ $(inpThis).remove();
+ }
+ });
+ // 不是异步
+ if($.inArray("edit.async",options.contextmenuList)===-1){
+ if(isStop) return;
+ // 修改数据
+ _self.reInitData(eleNode).currentData[options.request.name]=val;
+ // 修改dom
+ $(this).siblings(".eleTree-node-content-label").text(val).show();
+ $(this).remove();
+ }
+
+ }).on("mousedown",function(e) {
+ // 防止input拖拽
+ e.stopPropagation();
+ })
+ })
+ // 删除
+ $("#tree-menu li.remove").off().on("click",function(e) {
+ var node=$(that).parent(".eleTree-node");
+ var key=node.data(options.request.key);
+ var isStop=false;
+ layui.event.call(node, MOD_NAME, 'nodeRemove('+ _self.filter +')', {
+ node: node,
+ data: nodeData.currentData,
+ // 停止添加
+ stop: function() {
+ isStop=true;
+ return this;
+ },
+ async: function() {
+ if(isStop) return;
+ _self.remove(key);
+ return this;
+ }
+ });
+ // 不是异步
+ if($.inArray("remove.async",options.contextmenuList)===-1){
+ if(isStop) return;
+ _self.remove(key);
+ }
+
+ })
+
+ // 自定义菜单回调
+ customizeMenu.forEach(function(val) {
+ var text=val.eventName || val;
+ $("#tree-menu li."+text).off().on("click",function() {
+ var node=$(that).parent(".eleTree-node");
+ var isStop=false;
+ layui.event.call(node, MOD_NAME, 'node'+text.replace(text.charAt(0),text.charAt(0).toUpperCase())+'('+ _self.filter +')', {
+ node: node,
+ data: nodeData.currentData,
+ });
+ });
+ })
+
+ _self.prevClickEle=$(this);
+ })
+ },
+ search: function(value) {
+ var options=this.config;
+ if(!options.searchNodeMethod || typeof options.searchNodeMethod !== "function"){
+ return;
+ }
+ var data=options.data;
+ // 数据递归
+ var traverse=function(data) {
+ data.forEach(function(val,index) {
+ // 所有查找到的节点增加属性
+ val.visible=options.searchNodeMethod(value,val);
+ if(val[options.request.children] && val[options.request.children].length>0){
+ traverse(val[options.request.children]);
+ }
+ //如果当前节点属性为隐藏,判断其子节点是否有显示的,如果有,则当前节点改为显示
+ if(!val.visible){
+ var childSomeShow = false;
+ if(val[options.request.children] && val[options.request.children].length>0){
+ childSomeShow=val[options.request.children].some(function(v,i) {
+ return v.visible;
+ })
+ }
+ val.visible = childSomeShow;
+ }
+ // 通过节点的属性,显示隐藏各个节点,并添加删除搜索类
+ var el=options.elem.find("[data-"+options.customKey+"='"+val[options.request.key]+"']");
+ if(val.visible){
+ el.removeClass("eleTree-search-hide");
+ // 判断父节点是否展开,如果父节点没有展开,则子节点也不要显示
+ var parentEl=el.parent(".eleTree-node-group").parent(".eleTree-node");
+ var isParentOpen=parentEl.children(".eleTree-node-content").children(".eleTree-node-content-icon").children(".layui-icon.layui-icon-triangle-r").hasClass("icon-rotate")
+ if((parentEl.length>0 && isParentOpen) || parentEl.length===0){
+ el.show();
+ }
+ }else{
+ el.hide().addClass("eleTree-search-hide");
+ }
+ // 删除子层属性
+ // if(val[options.request.children] && val[options.request.children].length>0){
+ // val[options.request.children].forEach(function(v,i) {
+ // delete v.visible;
+ // })
+ // }
+ })
+ }
+ traverse(data);
+ // 删除最外层属性
+ var arr=data.map(function (val) {
+ var v=val.visible;
+ // delete val.visible;
+ return v;
+ });
+ var isNotext=options.elem.children(".eleTree-noText");
+ // 如果第一层的所有的都隐藏,则显示文本
+ if(arr.every(function(v) {
+ return v===false;
+ })){
+ if(isNotext.length===0){
+ laytpl(TPL_NoText()).render(options, function(string){
+ options.elem.append(string);
+ });
+ }
+ }else{
+ isNotext.remove();
+ }
+ },
+ getAllNodeData: function() {
+ var options=this.config;
+ return options.data;
+ }
+ }
+
+ exports(MOD_NAME,eleTree);
+})
diff --git a/docs/plugins/index.js b/docs/plugins/index.js
new file mode 100644
index 0000000..75f3757
--- /dev/null
+++ b/docs/plugins/index.js
@@ -0,0 +1,2 @@
+import './eleTree/eleTree.js'
+import './eleTree/eleTree.css'
\ No newline at end of file
diff --git a/docs/router.js b/docs/router.js
index 395a0e3..2b00aa6 100644
--- a/docs/router.js
+++ b/docs/router.js
@@ -1,4 +1,5 @@
import Component from './components/component.vue';
+import { version } from '../package.json'
function importVue(path) {
return r => require.ensure([], () => r(require(`./pages${path}.vue`)));
@@ -20,7 +21,7 @@ export default [{
redirect: '/component',
}, {
path: '/changelog',
- name: '更新日志',
+ name: '更新日志 v' + version,
component: importVue('/changelog'),
}, {
path: '/add',
@@ -84,12 +85,25 @@ export default [{
{ path: '/example-custom/ZM04', name: '远程搜索', component: importMd('/ZM04') },
{ path: '/example-custom/ZM05', name: '动态数据', component: importMd('/ZM05') },
{ path: '/example-custom/ZM06', name: '弹框中的多选', component: importMd('/ZM06') },
- // { path: '/example-custom/ZTEST', name: '测试', component: importMd('/ZTEST') },
+ ]
+ }, {
+ path: '/example-plugin',
+ name: '拓展中心',
+ redirect: '/example-plugin/ZP01',
+ component: Component,
+ children: [
+ { path: '/example-plugin/ZP01', name: '下拉自定义', component: importMd('/ZP01') },
+ { path: '/example-plugin/ZP02', name: '下拉树', component: importMd('/ZP02') },
]
}, {
path: '/question',
name: '常见问题',
component: importMd('/question'),
- },
+ }, {
+ path: '/test',
+ name: '测试',
+ hidden: true,
+ component: importMd('/ZTEST'),
+ },
];
diff --git a/package.json b/package.json
index 644d109..2f2733c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "xm-select",
- "version": "1.0.9",
+ "version": "1.0.10",
"description": "始于Layui的select多选解决方案",
"main": "index.js",
"scripts": {
diff --git a/src/components/common/util.js b/src/components/common/util.js
index 2707ad0..d24736a 100644
--- a/src/components/common/util.js
+++ b/src/components/common/util.js
@@ -146,50 +146,27 @@ export function IEVersion() {
}
}
-export function filterGroupOption(arr, data, prop){
- const { children, optgroup } = prop;
- data.filter(item => !item[optgroup]).forEach(item => {
- let child = item[children];
- if(isArray(child)){
- filterGroupOption(arr, child, children, optgroup);
- }else{
- arr.push(item);
- }
- });
-}
-
-export function findSelected(arr, data, prop){
- const { selected, children, optgroup } = prop;
- data.filter(item => !item[optgroup]).forEach(item => {
- let child = item[children];
- if(isArray(child)){
- findSelected(arr, child, prop);
- }else{
- item[selected] && (arr.push(item));
- }
- });
-}
-
-export function addGroupLabel(arr, prop){
- const { disabled, children, optgroup, value } = prop;
- let group;
- for(let i = 0; i < arr.length; i++){
- let item = arr[i];
- if(item[optgroup]){
- group = item;
- group.__value = [];
- continue;
- }
- let child = item[children];
- if(child && child.length > 0){
- group = null;
- item.__value = child.filter(c => !c[disabled]).map(c => c[value]);
- continue;
- }
- if(!group || item[disabled]){
- continue;
- }
- group.__value.push(item[value]);
- }
- return arr;
+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;
}
diff --git a/src/components/config/options.js b/src/components/config/options.js
index 9a32943..661e8e3 100644
--- a/src/components/config/options.js
+++ b/src/components/config/options.js
@@ -9,6 +9,8 @@ export default function (lan = 'zn') {
return {
//多选数据
data: [],
+ //自定义数据
+ content: '',
//表单提交的name
name: 'select',
//尺寸
diff --git a/src/components/core/index.js b/src/components/core/index.js
index 3375927..4f0b4b9 100644
--- a/src/components/core/index.js
+++ b/src/components/core/index.js
@@ -1,6 +1,6 @@
import { h, Component, render } from '@/components/preact'
import Framework from '@/components/element/framework'
-import { selector, warn, listenerClose, watch, safety, isArray, deepMerge } from '@/components/common/util'
+import { selector, warn, listenerClose, isArray, deepMerge, exchangeOptionsData } from '@/components/common/util'
import defaultOptions from '@/components/config/options'
@@ -46,6 +46,18 @@ class xmOptions {
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;
@@ -93,7 +105,7 @@ class xmOptions {
* 获取多选选中的数据
*/
getValue(type){
- let arr = safety(childs[this.options.el].state.sels);
+ let arr = deepMerge([], childs[this.options.el].state.sels);
if(type === 'name'){
return arr.map(item => item[this.options.prop.name]);
@@ -114,12 +126,12 @@ class xmOptions {
/**
* 设置多选数据
*/
- setValue(sels, show){
+ setValue(sels, show, listenOn = false){
if(!isArray(sels)){
warn('请传入数组结构...')
return ;
}
- childs[this.options.el].value(sels, show);
+ childs[this.options.el].value(sels, show, listenOn);
return this;
}
@@ -134,7 +146,7 @@ class xmOptions {
childs[this.options.el].append(sels);
return this;
}
-
+
/**
* 删除赋值
*/
@@ -146,7 +158,7 @@ class xmOptions {
childs[this.options.el].del(sels);
return this;
}
-
+
/**
* 闪烁警告边框
*/
diff --git a/src/components/element/framework.js b/src/components/element/framework.js
index 03463d6..5a7abe4 100644
--- a/src/components/element/framework.js
+++ b/src/components/element/framework.js
@@ -1,10 +1,11 @@
import { h, Component, render } from '@/components/preact'
-import { checkUserAgent, isFunction, toNum, filterGroupOption, findSelected, mergeArr } from '@/components/common/util'
+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';
/**
* 框架渲染类, 渲染基础的外边框 + 属性变化监听
@@ -28,14 +29,13 @@ class Framework extends Component{
}
findValue(data){
- let list = [];
- findSelected(list, data, this.props.prop);
- return list;
+ const { selected } = this.props.prop;
+ return data.filter(item => item[selected] === true);
}
- resetSelectValue(sels = [], change = [], isAdd){
+ resetSelectValue(sels = [], change = [], isAdd, listenOn = true){
let on = this.props.on;
- if(isFunction(on)){
+ if(isFunction(on) && this.prepare && listenOn){
on({ arr: sels, change, isAdd });
}
this.setState({ sels });
@@ -45,20 +45,19 @@ class Framework extends Component{
this.setState({ data });
}
- value(sels, show){
+ value(sels, show, listenOn){
if(show !== false && show !== true){
show = this.state.show;
}
let changeData = this.exchangeValue(sels);
- this.resetSelectValue(changeData, changeData, true);
+ this.resetSelectValue(changeData, changeData, true, listenOn);
this.setState({ show })
}
exchangeValue(sels){
+ const { optgroup, value } = this.props.prop;
let data = this.state.data;
- let value = this.props.prop.value;
- let list = [];
- filterGroupOption(list, data, this.props.prop);
+ 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);
}
@@ -82,7 +81,7 @@ class Framework extends Component{
auto(arr){
let value = this.props.prop.value;
- let sels = arr.filter(v => this.state.sels.findIndex(item => item[value] === v) != -1);
+ 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);
}
@@ -174,6 +173,10 @@ class Framework extends Component{
}
}
+ 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 };
@@ -194,7 +197,7 @@ class Framework extends Component{
this.updateBorderColor('')
}, 300);
}
-
+
//右边下拉箭头的变化class
const iconClass = show ? 'xm-icon xm-icon-expand' : 'xm-icon';
//提示信息的属性
@@ -256,7 +259,11 @@ class Framework extends Component{
this.bodyView = ref}>
-
+ { config.content ? (
+
+ ) : (
+
+ ) }
);
diff --git a/src/components/element/model/custom.js b/src/components/element/model/custom.js
new file mode 100644
index 0000000..1f5ec07
--- /dev/null
+++ b/src/components/element/model/custom.js
@@ -0,0 +1,30 @@
+import { h, Component, render } from '@/components/preact'
+
+/**
+ * 默认提示
+ */
+class Custom extends Component{
+
+ constructor(options){
+ super(options);
+ }
+
+ blockClick(e){
+ e.stopPropagation();
+ }
+
+ shouldComponentUpdate(){
+ return !this.already;
+ }
+
+ render(config) {
+ this.already = true;
+ return (
+
+
+
+ )
+ }
+}
+
+export default Custom;
diff --git a/src/components/element/model/general.js b/src/components/element/model/general.js
index c3a02b0..697ed7b 100644
--- a/src/components/element/model/general.js
+++ b/src/components/element/model/general.js
@@ -1,5 +1,5 @@
import { h, Component, render } from '@/components/preact'
-import { isFunction, isArray, safety, deepMerge, mergeArr, IEVersion, filterGroupOption, addGroupLabel } from '@/components/common/util'
+import { isFunction, isArray, safety, deepMerge, mergeArr, IEVersion } from '@/components/common/util'
/**
* 普通的多选渲染
@@ -29,13 +29,15 @@ class General extends Component{
}
groupClick(item, e){
- let m = item[this.props.prop.click];
+ const { click, children, disabled } = this.props.prop;
+ let m = item[click], arr = item[children].filter(opt => !opt[disabled]);
+
if(m === 'SELECT'){
- this.props.onReset(item.__value, 'append');
+ this.props.onReset(arr, 'append');
}else if(m === 'CLEAR'){
- this.props.onReset(item.__value, 'delete');
+ this.props.onReset(arr, 'delete');
}else if(m === 'AUTO'){
- this.props.onReset(item.__value, 'auto');
+ this.props.onReset(arr, 'auto');
}else if(isFunction(m)){
m(item);
}
@@ -161,13 +163,9 @@ class General extends Component{
const filterData = (item, index) => {
const isGroup = item[optgroup];
if(isGroup){
+ delete item.__del;
return true;
}
- const child = item[children];
- if(isArray(child) && child.length > 0){//分组模式
- item[children] = child.filter(filterData);
- return item[children].length != 0;
- }
return filterMethod(this.state.filterValue, item, index, prop);
}
arr = arr.filter(filterData);
@@ -175,7 +173,7 @@ class General extends Component{
for(let i = 0; i < arr.length - 1; i++){
let a = arr[i];
let b = arr[i + 1];
- if(a[optgroup] && (b[optgroup] || isArray(b[children]))){
+ if(a[optgroup] && b[optgroup]){
arr[i].__del = true;
}
}
@@ -200,11 +198,15 @@ class General extends Component{
);
+ //如果是分组模式, 要分页先去除分组, 然后在计算分页, 最后再加上分组
+ 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){
-
//计算当前分页的总页码
const size = Math.floor((arr.length - 1) / config.pageSize) + 1;
@@ -260,6 +262,17 @@ class General extends Component{
}
}
+ let newArr = [], group;
+ arr.forEach(item => {
+ let g = groupInfo[item[value]];
+ if(g != group){
+ group = g;
+ newArr.push(group);
+ }
+ newArr.push(item);
+ });
+ arr = newArr;
+
let safetyArr = deepMerge([], arr);
this.tempData = safetyArr;
@@ -272,9 +285,9 @@ class General extends Component{
let info;
if(tool === 'ALL'){
info = { icon: 'xm-iconfont xm-icon-quanxuan', name: '全选', method: (pageData) => {
- const list = [];
- filterGroupOption(list, pageData, prop);
- this.props.onReset(mergeArr(list.filter(item => !item[prop.disabled]), sels, prop), 'sels');
+ 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) => {
@@ -333,18 +346,10 @@ class General extends Component{
)
}
- const child = item[children];
- if(isArray(child) && child.length > 0){//分组模式
- return (
-
-
{ item[name] }
- { child.map(renderItem) }
-
- )
- }
return renderItem(item);
}
- arr = addGroupLabel(arr, prop).map(renderGroup);
+
+ arr = arr.map(renderGroup);
if(!arr.length){
arr.push(
diff --git a/src/style/index.less b/src/style/index.less
index 4a2c722..f0f75f7 100644
--- a/src/style/index.less
+++ b/src/style/index.less
@@ -60,11 +60,13 @@ xm-select{
border-color: #C0C4CC;
}
-
& > .xm-tips{
color: #999999;
padding: 0 10px;
- position: absolute;
+ position: absolute;
+ display: flex;
+ height: 100%;
+ align-items: center;
}
& > .xm-icon{
@@ -337,6 +339,15 @@ xm-select{
}
}
}
+
+ .xm-body-custom{
+ line-height: initial;
+ cursor: default;
+
+ *{
+ box-sizing: initial;
+ }
+ }
}
.xm-input{