diff --git a/gulpfile.js b/gulpfile.js
index 8fd2aafc..96bc0230 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -21,7 +21,7 @@ const config = {
,{pkg: pkg, js: ';'}
]
//模块
- ,modules: 'lay,laytpl,laypage,laydate,jquery,layer,util,dropdown,slider,colorpicker,element,upload,form,table,tree,transfer,carousel,rate,flow,code'
+ ,modules: 'lay,laytpl,laypage,laydate,jquery,layer,util,dropdown,slider,colorpicker,element,upload,form,table,treeTable,tree,transfer,carousel,rate,flow,code'
};
// 获取参数
diff --git a/src/css/layui.css b/src/css/layui.css
index e966169f..e329af71 100644
--- a/src/css/layui.css
+++ b/src/css/layui.css
@@ -55,7 +55,7 @@ a cite{font-style: normal; *cursor:pointer;}
url('../font/iconfont.ttf?v=280') format('truetype'),
url('../font/iconfont.svg?v=280#layui-icon') format('svg');
}
-
+
.layui-icon{
font-family:"layui-icon" !important;
font-size: 16px;
@@ -367,7 +367,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-show-md-block{display: block!important;}
.layui-show-md-inline{display: inline!important;}
.layui-show-md-inline-block{display: inline-block!important;}
-
+
.layui-col-md1, .layui-col-md2, .layui-col-md3, .layui-col-md4, .layui-col-md5, .layui-col-md6, .layui-col-md7, .layui-col-md8, .layui-col-md9, .layui-col-md10, .layui-col-md11, .layui-col-md12{float: left;}
.layui-col-md1{width: 8.33333333%;}
.layui-col-md2{width: 16.66666667%;}
@@ -402,7 +402,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-show-lg-block{display: block!important;}
.layui-show-lg-inline{display: inline!important;}
.layui-show-lg-inline-block{display: inline-block!important;}
-
+
.layui-col-lg1, .layui-col-lg2, .layui-col-lg3, .layui-col-lg4, .layui-col-lg5, .layui-col-lg6, .layui-col-lg7, .layui-col-lg8, .layui-col-lg9, .layui-col-lg10, .layui-col-lg11, .layui-col-lg12{float: left;}
.layui-col-lg1{width: 8.33333333%;}
.layui-col-lg2{width: 16.66666667%;}
@@ -437,7 +437,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-show-xl-block{display: block!important;}
.layui-show-xl-inline{display: inline!important;}
.layui-show-xl-inline-block{display: inline-block!important;}
-
+
.layui-col-xl1, .layui-col-xl2, .layui-col-xl3, .layui-col-xl4, .layui-col-xl5, .layui-col-xl6, .layui-col-xl7, .layui-col-xl8, .layui-col-xl9, .layui-col-xl10, .layui-col-xl11, .layui-col-xl12{float: left;}
.layui-col-xl1{width: 8.33333333%;}
.layui-col-xl2{width: 16.66666667%;}
@@ -532,7 +532,7 @@ a cite{font-style: normal; *cursor:pointer;}
/*
面板
-
+
*/
@@ -566,8 +566,8 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-scollbar-hide{overflow: hidden !important;}
-/*
- * 默认主题
+/*
+ * 默认主题
*/
@@ -583,11 +583,11 @@ a cite{font-style: normal; *cursor:pointer;}
/* 边框 */
.layui-border,
-.layui-quote-nm,
+.layui-quote-nm,
.layui-elem-field,
-.layui-collapse,
+.layui-collapse,
.layui-panel,
-.layui-colla-item,
+.layui-colla-item,
.layui-colla-content,
.layui-badge-rim,
.layui-tab-title,
@@ -597,7 +597,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-input, .layui-textarea, .layui-select,
.layui-input-split,
-.layui-form-pane .layui-form-label,
+.layui-form-pane .layui-form-label,
.layui-form-pane .layui-form-item[pane]{border-color: #eee;}
.layui-border{border-width: 1px; border-style: solid; color: #5F5F5F!important;}
@@ -666,8 +666,8 @@ a cite{font-style: normal; *cursor:pointer;}
/*
-
- 按钮
+
+ 按钮
*/
@@ -719,7 +719,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-input:focus, .layui-textarea:focus{border-color: #d2d2d2 !important;}
.layui-textarea{position: relative; min-height: 100px; height: auto; line-height: 20px; padding: 6px 10px; resize: vertical;}
.layui-select{padding: 0 10px;}
-.layui-form select,
+.layui-form select,
.layui-form input[type=checkbox],
.layui-form input[type=radio]{display: none;}
.layui-form *[lay-ignore]{display: initial;}
@@ -834,6 +834,8 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-form-checked.layui-checkbox-disabled[lay-skin="primary"] i{background: #eee!important; border-color: #eee!important;}
.layui-checkbox-disabled[lay-skin="primary"]:hover i{border-color: #d2d2d2;}
.layui-form-item .layui-form-checkbox[lay-skin="primary"]{margin-top: 10px;}
+.layui-form-checkbox[lay-skin="primary"] > i.layui-icon-subtraction,
+.layui-form-checkbox[lay-skin="primary"]:hover i.layui-icon-subtraction {color: darkgray;}
/* 复选框-开关风格 */.layui-form-switch{position: relative; display: inline-block; vertical-align: middle; height: 22px; line-height: 22px; min-width: 35px; padding: 0 5px; margin-top: 8px; border: 1px solid #d2d2d2; border-radius: 20px; cursor: pointer; background-color: #fff; -webkit-transition: .1s linear; transition: .1s linear;}
.layui-form-switch i{position: absolute; left: 5px; top: 3px; width: 16px; height: 16px; border-radius: 20px; background-color: #d2d2d2; -webkit-transition: .1s linear; transition: .1s linear;}
@@ -868,7 +870,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-form-pane .layui-form-text .layui-input-block{margin: 0; left: 0; top: -1px;}
.layui-form-pane .layui-form-text .layui-textarea{min-height: 100px; border-radius: 0 0 2px 2px;}
.layui-form-pane .layui-form-checkbox{margin: 4px 0 4px 10px;}
-.layui-form-pane .layui-form-switch,
+.layui-form-pane .layui-form-switch,
.layui-form-pane .layui-form-radio{margin-top: 6px; margin-left: 10px; }
.layui-form-pane .layui-form-item[pane]{position: relative; border-width: 1px; border-style: solid;}
.layui-form-pane .layui-form-item[pane] .layui-form-label{position: absolute; left: 0; top: 0; height: 100%; border-width: 0px; border-right-width: 1px;}
@@ -894,7 +896,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-laypage>*:last-child{margin-right: 0!important;}
.layui-laypage a,
.layui-laypage span,
-.layui-laypage input,
+.layui-laypage input,
.layui-laypage button,
.layui-laypage select{border: 1px solid #eee;}
.layui-laypage a,
@@ -1108,7 +1110,13 @@ body .layui-table-tips .layui-layer-content{background: none; padding: 0; box-sh
.layui-table-tips-c:hover{background-color: #777;}
.layui-table-tips-c:before{position: relative; right: -2px;}
-/** 文件上传 **/
+/** 树表 **/
+.layui-table-tree-nodeIcon {width: 20px;}
+.layui-table-tree-nodeIcon > * {width: 100%;}
+.layui-table-tree-flexIcon,.layui-table-tree-nodeIcon {margin-right: 2px;}
+.layui-table-tree-flexIcon {cursor: pointer;}
+
+ /** 文件上传 **/
.layui-upload-file{display: none!important; opacity: .01; filter: Alpha(opacity=1);}
.layui-upload-list{margin: 11px 0;}
.layui-upload-choose{max-width: 200px; padding: 0 10px; color: #999; font-size: 14px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;}
@@ -1238,7 +1246,7 @@ body .layui-table-tips .layui-layer-content{background: none; padding: 0; box-sh
.layui-nav-tree .layui-nav-child a:hover,
.layui-nav-tree .layui-nav-child{background: none; color: #fff;}
-.layui-nav-itemed>.layui-nav-child{display: block; background-color: rgba(0,0,0,.3) !important;}
+.layui-nav-itemed>.layui-nav-child{display: block; background-color: rgba(0,0,0,.3) !important;}
.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display: block;}
/* 侧边 */.layui-nav-side{position: fixed; top: 0; bottom: 0; left: 0; overflow-x: hidden; z-index: 999;}
@@ -1479,7 +1487,7 @@ body .layui-util-face .layui-layer-content{padding:0; background-color:#fff; co
.layui-slider-wrap{width: 36px; height: 36px; position: absolute; top: -16px; -webkit-transform: translateX(-50%); transform: translateX(-50%); z-index: 10; text-align: center;}
.layui-slider-wrap-btn{width: 12px; height: 12px; border-radius: 50%; background: #FFF; display: inline-block; vertical-align: middle; cursor: pointer; transition: 0.3s;}
.layui-slider-wrap:after{content: ""; height: 100%; display: inline-block; vertical-align: middle;}
-.layui-slider-wrap-btn:hover,
+.layui-slider-wrap-btn:hover,
.layui-slider-wrap-btn.layui-slider-hover{transform: scale(1.2);}
.layui-slider-wrap-btn.layui-disabled:hover{transform: scale(1) !important;}
.layui-slider-tips{position: absolute; top: -42px; z-index: 77777777; white-space:nowrap; display: none; -webkit-transform: translateX(-50%); transform: translateX(-50%); color: #FFF; background: #000; border-radius: 3px; height: 25px; line-height: 25px; padding: 0 10px;}
@@ -1644,7 +1652,7 @@ body .layui-util-face .layui-layer-content{padding:0; background-color:#fff; co
.layui-anim-fadein{-webkit-animation-name: layui-fadein; animation-name: layui-fadein;}
/* 渐隐 */
-@-webkit-keyframes layui-fadeout {
+@-webkit-keyframes layui-fadeout {
0% {opacity: 1;}
100% {opacity: 0;}
}
diff --git a/src/layui.js b/src/layui.js
index 57c1024c..20016bdf 100644
--- a/src/layui.js
+++ b/src/layui.js
@@ -60,6 +60,7 @@
,transfer: 'transfer' //穿梭框
,tree: 'tree' //树结构
,table: 'table' //表格
+ ,treeTable: 'treeTable' //树表
,element: 'element' //常用元素操作
,rate: 'rate' //评分组件
,colorpicker: 'colorpicker' //颜色选择器
diff --git a/src/modules/dropdown.js b/src/modules/dropdown.js
index adefe8cd..60425d65 100644
--- a/src/modules/dropdown.js
+++ b/src/modules/dropdown.js
@@ -48,6 +48,9 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){
,reload: function(options){
that.reload.call(that, options);
}
+ ,reloadData: function(options){
+ dropdown.reloadData(id, options);
+ }
,close: function () {
that.remove()
}
@@ -83,14 +86,14 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){
};
//重载实例
- Class.prototype.reload = function(options){
+ Class.prototype.reload = function(options, type){
var that = this;
that.config = $.extend({}, that.config, options);
- that.init(true);
+ that.init(true, type);
};
// 初始化准备
- Class.prototype.init = function(rerender){
+ Class.prototype.init = function(rerender, type){
var that = this;
var options = that.config;
@@ -113,7 +116,7 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){
var newThat = thisModule.getThis(elem.data(MOD_INDEX));
if(!newThat) return;
- return newThat.reload(options);
+ return newThat.reload(options, type);
}
options.elem = $(options.elem);
@@ -122,13 +125,13 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){
options.id = 'id' in options ? options.id : (
elem.attr('id') || that.index
);
-
- if(options.show) that.render(rerender); // 初始即显示
+
+ if(options.show || (type === 'reloadData' && that.elemView && $('body').find(that.elemView.get(0)).length)) that.render(rerender, type); //初始即显示或者面板弹出之后执行了刷新数据
that.events(); // 事件
};
//渲染
- Class.prototype.render = function(rerender){
+ Class.prototype.render = function(rerender, type){
var that = this
,options = that.config
,elemBody = $('body')
@@ -234,7 +237,7 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){
}
//主模板
- ,TPL_MAIN = ['
'
+ ,TPL_MAIN = ['
'
,'
'].join('');
//如果是右键事件,则每次触发事件时,将允许重新渲染
@@ -244,26 +247,39 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){
if(!rerender && options.elem.data(MOD_INDEX +'_opened')) return;
//记录模板对象
- that.elemView = $(TPL_MAIN);
- that.elemView.append(options.content || getDefaultView());
-
- //初始化某些属性
- if(options.className) that.elemView.addClass(options.className);
- if(options.style) that.elemView.attr('style', options.style);
-
-
- //记录当前执行的实例索引
- dropdown.thisId = options.id;
-
- //插入视图
- that.remove(); //移除非当前绑定元素的面板
- elemBody.append(that.elemView);
- options.elem.data(MOD_INDEX +'_opened', true);
+ that.elemView = $('.' + STR_ELEM + '[lay-id="' + options.id + '"]');
+ if (type === 'reloadData' && that.elemView.length) {
+ that.elemView.html(options.content || getDefaultView());
+ } else {
+ that.elemView = $(TPL_MAIN);
+ that.elemView.append(options.content || getDefaultView());
+
+ //初始化某些属性
+ if(options.className) that.elemView.addClass(options.className);
+ if(options.style) that.elemView.attr('style', options.style);
+
+ //记录当前执行的实例索引
+ dropdown.thisId = options.id;
+
+ //插入视图
+ that.remove(); //移除非当前绑定元素的面板
+ elemBody.append(that.elemView);
+ options.elem.data(MOD_INDEX +'_opened', true);
+
+ //遮罩
+ var shade = options.shade ? ('
') : '';
+ that.elemView.before(shade);
+
+ //如果是鼠标移入事件,则鼠标移出时自动关闭
+ if(options.trigger === 'mouseenter'){
+ that.elemView.on('mouseenter', function(){
+ clearTimeout(thisModule.timer);
+ }).on('mouseleave', function(){
+ that.delayRemove();
+ });
+ }
+ }
- //遮罩
- var shade = options.shade ? ('
') : '';
- that.elemView.before(shade);
-
//坐标定位
that.position();
thisModule.prevElem = that.elemView; //记录当前打开的元素,以便在下次关闭
@@ -304,15 +320,6 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){
thisModule.spread(elemGroup);
}
});
-
- //如果是鼠标移入事件,则鼠标移出时自动关闭
- if(options.trigger === 'mouseenter'){
- that.elemView.on('mouseenter', function(){
- clearTimeout(thisModule.timer);
- }).on('mouseleave', function(){
- that.delayRemove();
- });
- }
// 组件打开完毕的事件
typeof options.ready === 'function' && options.ready(
@@ -545,14 +552,34 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){
};
// 重载实例
- dropdown.reload = function(id, options){
+ dropdown.reload = function(id, options, type){
var that = thisModule.getThis(id);
if(!that) return this;
- that.reload(options);
+ that.reload(options, type);
return thisModule.call(that);
};
+ // 仅重载数据
+ dropdown.reloadData = function(){
+ var args = $.extend([], arguments);
+ args[2] = 'reloadData';
+
+ // 重载时,与数据相关的参数
+ var dataParams = new RegExp('^('+ [
+ 'data', 'templet', 'content'
+ ].join('|') + ')$');
+
+ // 过滤与数据无关的参数
+ layui.each(args[1], function (key, value) {
+ if(!dataParams.test(key)){
+ delete args[1][key];
+ }
+ });
+
+ return dropdown.reload.apply(null, args);
+ };
+
// 核心入口
dropdown.render = function(options){
var inst = new Class(options);
diff --git a/src/modules/form.js b/src/modules/form.js
index 9b58e18d..778dde2e 100644
--- a/src/modules/form.js
+++ b/src/modules/form.js
@@ -98,9 +98,7 @@ layui.define(['lay', 'layer', 'util'], function(exports){
itemElem[0].checked = value;
} else if(type === 'radio') { // 如果为单选框
itemElem.each(function(){
- if(this.value == value ){
- this.checked = true
- }
+ this.checked = this.value == value;
});
} else { // 其它类型的表单
itemElem.val(value);
@@ -644,7 +642,12 @@ layui.define(['lay', 'layer', 'util'], function(exports){
var title = (check.attr('title')||'').split('|');
if(check[0].disabled) return;
-
+ if (check[0].indeterminate) {
+ check[0].indeterminate = false;
+ reElem.find('.layui-icon-subtraction').removeClass('layui-icon-subtraction').addClass('layui-icon-ok')
+ }
+
+
check[0].checked ? (
check[0].checked = false
,reElem.removeClass(RE_CLASS[1]).find('em').text(title[1])
@@ -688,7 +691,7 @@ layui.define(['lay', 'layer', 'util'], function(exports){
// 复选框
"checkbox": [
(title[0] ? ('
'+ util.escape(title[0]) +'') : '')
- ,'
'
+ ,'
'
].join(''),
// 开关
diff --git a/src/modules/table.js b/src/modules/table.js
index a979e85c..7782bef6 100644
--- a/src/modules/table.js
+++ b/src/modules/table.js
@@ -1,11 +1,11 @@
/**
- * layui.table
+ * layui.table
* 表格组件
*/
layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
"use strict";
-
+
var $ = layui.$;
var lay = layui.lay;
var laytpl = layui.laytpl;
@@ -26,31 +26,26 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
},
cache: {}, // 数据缓存
index: layui.table ? (layui.table.index + 10000) : 0,
-
+
// 设置全局项
set: function(options){
var that = this;
that.config = $.extend({}, that.config, options);
return that;
},
-
+
// 事件
on: function(events, callback){
return layui.onevent.call(this, MOD_NAME, events, callback);
}
};
-
+
// 操作当前实例
var thisTable = function(){
var that = this;
var options = that.config;
var id = options.id || options.index;
-
- if(id){
- thisTable.that[id] = that; // 记录当前实例对象
- thisTable.config[id] = options; // 记录当前实例配置项
- }
-
+
return {
config: options,
reload: function(options, deep){
@@ -74,14 +69,14 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
if(!that) hint.error(id ? ('The table instance with ID \''+ id +'\' not found') : 'ID argument required');
return that || null;
};
-
+
// 获取当前实例配置项
var getThisTableConfig = function(id){
var config = thisTable.config[id];
if(!config) hint.error(id ? ('The table instance with ID \''+ id +'\' not found') : 'ID argument required');
return config || null;
};
-
+
// 解析自定义模板数据
var parseTempData = function(obj){
obj = obj || {};
@@ -89,27 +84,27 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var options = this.config || {};
var item3 = obj.item3; // 表头数据
var content = obj.content; // 原始内容
-
+
// 是否编码 HTML
var escaped = 'escape' in item3 ? item3.escape : options.escape;
if(escaped) content = util.escape(content);
-
+
// 获取模板
var templet = obj.text && item3.exportTemplet || (item3.templet || item3.toolbar);
// 获取模板内容
if(templet){
- content = typeof templet === 'function'
+ content = typeof templet === 'function'
? templet.call(item3, obj.tplData, obj.obj)
: laytpl($(templet).html() || String(content)).render($.extend({
LAY_COL: item3
}, obj.tplData));
}
-
+
// 是否只返回文本
return obj.text ? $('
'+ content +'
').text() : content;
};
-
+
// 字符
var MOD_NAME = 'table';
var ELEM = '.layui-table';
@@ -119,7 +114,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var HIDE_V = 'layui-hide-v';
var DISABLED = 'layui-disabled';
var NONE = 'layui-none';
-
+
var ELEM_VIEW = 'layui-table-view';
var ELEM_TOOL = '.layui-table-tool';
var ELEM_BOX = '.layui-table-box';
@@ -145,7 +140,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// thead 区域模板
var TPL_HEADER = function(options){
var rowCols = '{{#if(item2.colspan){}} colspan="{{=item2.colspan}}"{{#} if(item2.rowspan){}} rowspan="{{=item2.rowspan}}"{{#}}}';
-
+
options = options || {};
return ['
'
@@ -193,13 +188,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,''
,'
'].join('');
};
-
+
// tbody 区域模板
var TPL_BODY = ['
'].join('');
-
+
// 主模板
var TPL_MAIN = [
,'{{# if(d.data.toolbar){ }}'
@@ -208,14 +203,14 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,'
'
,'
'
,'{{# } }}'
-
+
,''
,'{{# if(d.data.loading){ }}'
,'
'
,''
,'
'
,'{{# } }}'
-
+
,'{{# var left, right; }}'
,''
,'{{# }; }}'
-
+
,'{{# if(right){ }}'
,'
'
,''
,'{{# }; }}'
,'
'
-
+
,'{{# if(d.data.totalRow){ }}'
,'
'
,'
'
].join('');
-
+
var _WIN = $(window);
var _DOC = $(document);
-
+
// constructor
var Class = function(options){
var that = this;
@@ -295,7 +290,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.config = $.extend({}, that.config, table.config, options);
that.render();
};
-
+
// 初始默认配置
Class.prototype.config = {
limit: 10, // 每页显示的数量
@@ -322,16 +317,19 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
options.where = options.where || {};
// 初始化 id 属性 - 优先取 options > 元素 id > 自增索引
- options.id = 'id' in options ? options.id : (
+ var id = options.id = 'id' in options ? options.id : (
options.elem.attr('id') || that.index
);
+ thisTable.that[id] = that; // 记录当前实例对象
+ thisTable.config[id] = options; // 记录当前实例配置项
+
//请求参数的自定义格式
options.request = $.extend({
pageName: 'page'
,limitName: 'limit'
}, options.request)
-
+
// 响应数据的自定义格式
options.response = $.extend({
statusName: 'code' //规定数据状态的字段名称
@@ -341,7 +339,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,totalRowName: 'totalRow' //规定数据统计的字段名称
,countName: 'count'
}, options.response);
-
+
//如果 page 传入 laypage 对象
if(options.page !== null && typeof options.page === 'object'){
options.limit = options.page.limit || options.limit;
@@ -350,7 +348,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
delete options.page.elem;
delete options.page.jump;
}
-
+
if(!options.elem[0]) return that;
// 若元素未设 lay-filter 属性,则取实例 id 值
@@ -372,7 +370,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
//初始化一些其他参数
that.setInit();
-
+
//高度铺满:full-差距值
if(options.height && /^full-\d+$/.test(options.height)){
that.fullHeightGap = options.height.split('-')[1];
@@ -387,7 +385,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
//开始插入替代元素
var othis = options.elem
,hasRender = othis.next('.' + ELEM_VIEW)
-
+
//主容器
,reElem = that.elem = $('');
@@ -420,7 +418,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
//生成替代元素
hasRender[0] && hasRender.remove(); //如果已经渲染,则Rerender
othis.after(reElem);
-
+
//各级容器
that.layTool = reElem.find(ELEM_TOOL);
that.layBox = reElem.find(ELEM_BOX);
@@ -432,20 +430,20 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.layFixRight = reElem.find(ELEM_FIXR);
that.layTotal = reElem.find(ELEM_TOTAL);
that.layPage = reElem.find(ELEM_PAGE);
-
+
// 初始化头部工具栏
that.renderToolbar();
-
+
// 初始化底部分页栏
that.renderPagebar();
-
+
// 让表格平铺
that.fullSize();
-
+
that.pullData(that.page); //请求数据
that.events(); //事件
};
-
+
//根据列类型,定制化参数
Class.prototype.initOpts = function(item){
var that = this
@@ -456,7 +454,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,space: 30
,numbers: 60
};
-
+
//让 type 参数兼容旧版本
if(item.checkbox) item.type = "checkbox";
if(item.space) item.type = "space";
@@ -467,12 +465,12 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
item.width = item.width || initWidth[item.type];
}
};
-
+
//初始化一些参数
Class.prototype.setInit = function(type){
var that = this
,options = that.config;
-
+
options.clientWidth = options.width || function(){ //获取容器宽度
//如果父元素宽度为0(一般为隐藏元素),则继续查找上层元素,直到找到真实宽度为止
var getWidth = function(parent){
@@ -487,7 +485,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
};
return getWidth();
}();
-
+
if(type === 'width') return options.clientWidth;
// 初始化高度配置,如果设置了最高高度,以最高高度形式为准
options.height = options.maxHeight || options.height;
@@ -546,14 +544,14 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
initChildCols(i1, item1, i2, item2);
});
});
-
+
};
-
+
//初始工具栏
Class.prototype.renderToolbar = function(){
var that = this
,options = that.config
-
+
//添加工具栏左侧模板
var leftDefaultTemp = [
'
'
@@ -561,7 +559,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,'
'
].join('')
,elemToolTemp = that.layTool.find('.layui-table-tool-temp');
-
+
if(options.toolbar === 'default'){
elemToolTemp.html(leftDefaultTemp);
} else if(typeof options.toolbar === 'string'){
@@ -570,7 +568,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
laytpl(toolbarHtml).render(options)
);
}
-
+
//添加工具栏右侧面板
var layout = {
filter: {
@@ -589,7 +587,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,icon: 'layui-icon-print'
}
}, iconElem = [];
-
+
if(typeof options.defaultToolbar === 'object'){
layui.each(options.defaultToolbar, function(i, item){
var thisItem = typeof item === 'string' ? layout[item] : item;
@@ -607,9 +605,9 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
Class.prototype.renderPagebar = function(){
var that = this
,options = that.config
-
+
,layPagebar = that.layPagebar = $('')
-
+
//开启分页栏自定义模板
if(options.pagebar){
var pagebarHtml = $(options.pagebar).html() || '';
@@ -617,15 +615,15 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.layPage.append(layPagebar);
}
};
-
+
//同步表头父列的相关值
Class.prototype.setParentCol = function(hide, parentKey){
var that = this
,options = that.config
-
+
,parentTh = that.layHeader.find('th[data-key="'+ parentKey +'"]') //获取父列元素
,parentColspan = parseInt(parentTh.attr('colspan')) || 0;
-
+
if(parentTh[0]){
var arrParentKey = parentKey.split('-')
,getThisCol = options.cols[arrParentKey[1]][arrParentKey[2]];
@@ -637,13 +635,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
getThisCol.colspan = parentColspan; //同步 colspan 参数
getThisCol.hide = parentColspan >= 1 || !hide; //同步 hide 参数
-
+
//递归,继续往上查询是否有父列
var nextParentKey = parentTh.data('parentkey');
nextParentKey && that.setParentCol(hide, nextParentKey);
}
};
-
+
// 多级表头补丁
Class.prototype.setColsPatch = function(){
var that = this;
@@ -704,7 +702,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var autoWidth = 0; // 自动列分配的宽度
var countWidth = 0; // 所有列总宽度和
var cntrWidth = that.setInit('width');
-
+
// 统计列个数
that.eachCols(function(i, item){
item.hide || colNums++;
@@ -753,7 +751,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
autoColNums--;
width = maxWidth;
}
-
+
if(item2.hide) width = 0;
countWidth = countWidth + width;
});
@@ -764,20 +762,20 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
autoWidth = (cntrWidth - countWidth) / autoColNums
);
}
-
+
getAutoWidth();
getAutoWidth(true); // 重新检测分配的宽度是否低于最小列宽
-
+
// 记录自动列数
that.autoColNums = autoColNums = autoColNums > 0 ? autoColNums : 0;
-
+
// 设置列宽
that.eachCols(function(i3, item3){
var minWidth = item3.minWidth || options.cellMinWidth;
var maxWidth = item3.maxWidth || options.cellMaxWidth;
if(item3.colGroup || item3.hide) return;
-
+
// 给未分配宽的列平均分配宽
if(item3.width === 0){
that.getCssRule(item3.key, function(item){
@@ -788,7 +786,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}()) + 'px';
});
}
-
+
// 给设定百分比的列分配列宽
else if(/\d+%$/.test(item3.width)){
that.getCssRule(item3.key, function(item){
@@ -806,20 +804,27 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
});
}
});
-
+
// 填补 Math.floor 造成的数差
var patchNums = that.layMain.width() - that.getScrollWidth(that.layMain[0])
- that.layMain.children('table').outerWidth();
if(that.autoColNums > 0 && patchNums >= -colNums && patchNums <= colNums){
var getEndTh = function(th){
- var field;
- th = th || that.layHeader.eq(0).find('thead > tr:first-child > th:last-child')
- field = th.data('field');
+ var field, thRet;
+ th = th || that.layHeader.eq(0).find('thead th:last-child')
+ layui.each(th, function (thIndex, thElem) {
+ thElem = $(thElem);
+ if (!thElem.children('.'+ELEM_GROUP).length) { // 排除合并表头
+ field = thElem.attr('data-field');
+ thRet = thElem;
+ }
+ })
+
if(!field && th.prev()[0]){
return getEndTh(th.prev())
}
- return th
+ return thRet
};
var th = getEndTh();
var key = th.data('key');
@@ -827,7 +832,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.getCssRule(key, function(item){
var width = item.style.width || th.outerWidth();
item.style.width = (parseFloat(width) + patchNums) + 'px';
-
+
// 二次校验,如果仍然出现横向滚动条(通常是 1px 的误差导致)
if(that.layMain.height() - that.layMain.prop('clientHeight') > 0){
item.style.width = (parseFloat(item.style.width) - 1) + 'px';
@@ -836,7 +841,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
that.setGroupWidth();
-
+
// 如果表格内容为空(无数据 或 请求异常)
if (that.layMain.find('tbody').is(":empty")) {
// 将表格宽度设置为跟表头一样的宽度,使之可以出现底部滚动条,以便滚动查看所有字段
@@ -845,10 +850,10 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
} else {
that.layMain.find('table').width('auto');
}
-
+
that.loading(!0);
};
-
+
// 重置表格尺寸/结构
Class.prototype.resize = function(){
var that = this;
@@ -856,40 +861,40 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.setColsWidth(); //自适应列宽
that.scrollPatch(); //滚动条补丁
};
-
+
// 表格重载
Class.prototype.reload = function(options, deep, type){
var that = this;
-
+
options = options || {};
delete that.haveInit;
-
+
// 防止数组深度合并
layui.each(options, function(key, item){
if(layui.type(item) === 'array') delete that.config[key];
});
-
+
// 对参数进行深度或浅扩展
that.config = $.extend(deep, {}, that.config, options);
// 执行渲染
that.render(type);
};
-
+
// 异常提示
Class.prototype.errorView = function(html){
var that = this
,elemNone = that.layMain.find('.'+ NONE)
,layNone = $(''+ (html || 'Error') +'
');
-
+
if(elemNone[0]){
that.layNone.remove();
elemNone.remove();
}
-
+
that.layFixed.addClass(HIDE);
that.layMain.find('tbody').html('');
-
+
that.layMain.append(that.layNone = layNone);
// 异常情况下对 page 和 total 的内容处理
@@ -899,11 +904,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
table.cache[that.key] = []; //格式化缓存数据
that.syncCheckAll();
+ that.renderForm();
+ that.setColsWidth();
};
-
+
// 初始页码
Class.prototype.page = 1;
-
+
// 获得数据
Class.prototype.pullData = function(curr, opts){
var that = this;
@@ -913,7 +920,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var sort = function(){
if(typeof options.initSort === 'object'){
that.sort({
- field: options.initSort.field,
+ field: options.initSort.field,
type: options.initSort.type,
reloadType: opts.type
});
@@ -921,13 +928,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
};
opts = opts || {};
-
+
// 数据拉取前的回调
typeof options.before === 'function' && options.before(
options
);
that.startTime = new Date().getTime(); // 渲染开始时间
-
+
if(options.url){ // Ajax请求
var params = {};
// 当 page 开启,默认自动传递 page、limit 参数
@@ -935,13 +942,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
params[request.pageName] = curr;
params[request.limitName] = options.limit;
}
-
+
// 参数
var data = $.extend(params, options.where);
if(options.contentType && options.contentType.indexOf("application/json") == 0){ // 提交 json 格式
data = JSON.stringify(data);
}
-
+
that.loading();
$.ajax({
@@ -959,14 +966,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
// 检查数据格式是否符合规范
if(res[response.statusName] != response.statusCode){
- that.renderForm();
that.errorView(
res[response.msgName] ||
('返回的数据不符合规范,正确的成功状态码应为:"'+ response.statusName +'": '+ response.statusCode)
);
} else {
that.renderData({
- res: res,
+ res: res,
curr: curr,
count: res[response.countName],
type: opts.type
@@ -982,10 +988,6 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
,error: function(e, msg){
that.errorView('请求异常,错误提示:'+ msg);
-
- that.renderForm();
- that.setColsWidth();
-
typeof options.error === 'function' && options.error(e, msg);
}
});
@@ -993,19 +995,19 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var res = {};
var startLimit = curr*options.limit - options.limit;
var newData = options.data.concat();
-
- res[response.dataName] = options.page
+
+ res[response.dataName] = options.page
? newData.splice(startLimit, options.limit)
: newData;
res[response.countName] = options.data.length;
-
+
//记录合计行数据
if(typeof options.totalRow === 'object'){
res[response.totalRowName] = $.extend({}, options.totalRow);
}
that.renderData({
- res: res,
+ res: res,
curr: curr,
count: res[response.countName],
type: opts.type
@@ -1018,7 +1020,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
);
}
};
-
+
// 遍历表头
Class.prototype.eachCols = function(callback){
var that = this;
@@ -1037,6 +1039,152 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
};
+ Class.prototype.getTrHtml = function(data, sort, curr, trsObj) {
+ var that = this;
+ var options = that.config;
+ var trs = trsObj && trsObj.trs || [];
+ var trs_fixed = trsObj && trsObj.trs_fixed || [];
+ var trs_fixed_r = trsObj && trsObj.trs_fixed_r || [];
+ curr = curr || 1
+
+ layui.each(data, function(i1, item1){
+ var tds = [], tds_fixed = [], tds_fixed_r = []
+ ,numbers = i1 + options.limit*(curr - 1) + 1; // 序号
+
+ // 数组值是否为 object,如果不是,则自动转为 object
+ if(typeof item1 !== 'object'){
+ data[i1] = item1 = {LAY_KEY: item1};
+ try {
+ table.cache[that.key][i1] = item1;
+ } catch(e) {}
+ }
+
+ //若数据项为空数组,则不往下执行(因为删除数据时,会将原有数据设置为 [])
+ if(layui.type(item1) === 'array' && item1.length === 0) return;
+
+ // 加入序号保留字段
+ item1[table.config.numbersName] = numbers;
+
+ // 记录下标索引,用于恢复排序
+ if(!sort) item1[table.config.indexName] = i1;
+
+ // 遍历表头
+ that.eachCols(function(i3, item3){
+ var field = item3.field || i3;
+ var key = item3.key;
+ var content = item1[field];
+
+ if(content === undefined || content === null) content = '';
+ if(item3.colGroup) return;
+
+ // td 内容
+ var td = [''
+ ,' '
+ + function(){
+ var tplData = $.extend(true, {
+ LAY_COL: item3
+ }, item1);
+ var checkName = table.config.checkName;
+ var disabledName = table.config.disabledName;
+
+ //渲染不同风格的列
+ switch(item3.type){
+ case 'checkbox': // 复选
+ return '';
+ break;
+ case 'radio': // 单选
+ if(tplData[checkName]){
+ that.thisCheckedRowIndex = i1;
+ }
+ return '';
+ break;
+ case 'numbers':
+ return numbers;
+ break;
+ };
+
+ //解析工具列模板
+ if(item3.toolbar){
+ return laytpl($(item3.toolbar).html()||'').render(tplData);
+ }
+ return parseTempData.call(that, {
+ item3: item3
+ ,content: content
+ ,tplData: tplData
+ });
+ }()
+ ,' | '].join('');
+
+ tds.push(td);
+ if(item3.fixed && item3.fixed !== 'right') tds_fixed.push(td);
+ if(item3.fixed === 'right') tds_fixed_r.push(td);
+ });
+
+ trs.push(''+ tds.join('') + '
');
+ trs_fixed.push(''+ tds_fixed.join('') + '
');
+ trs_fixed_r.push(''+ tds_fixed_r.join('') + '
');
+ });
+
+ return {
+ trs: trs,
+ trs_fixed: trs_fixed,
+ trs_fixed_r: trs_fixed_r
+ }
+ }
+
+ // 返回行节点代码
+ table.getTrHtml = function (id, data) {
+ var that = getThisTable(id);
+ return that.getTrHtml(data);
+ }
// 数据渲染
Class.prototype.renderData = function(opts){
@@ -1053,146 +1201,26 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var trs = [];
var trs_fixed = [];
var trs_fixed_r = [];
-
+
// 渲染视图
var render = function(){ // 后续性能提升的重点
// 同步表头父列的相关值
options.HAS_SET_COLS_PATCH || that.setColsPatch();
options.HAS_SET_COLS_PATCH = true;
- var thisCheckedRowIndex;
+ that.thisCheckedRowIndex = '';
if(!sort && that.sortKey){
return that.sort({
- field: that.sortKey.field,
- type: that.sortKey.sort,
+ field: that.sortKey.field,
+ type: that.sortKey.sort,
pull: true,
reloadType: opts.type
});
}
- layui.each(data, function(i1, item1){
- var tds = [], tds_fixed = [], tds_fixed_r = []
- ,numbers = i1 + options.limit*(curr - 1) + 1; // 序号
-
- // 数组值是否为 object,如果不是,则自动转为 object
- if(typeof item1 !== 'object'){
- data[i1] = item1 = {LAY_KEY: item1};
- try {
- table.cache[that.key][i1] = item1;
- } catch(e) {}
- }
-
- //若数据项为空数组,则不往下执行(因为删除数据时,会将原有数据设置为 [])
- if(layui.type(item1) === 'array' && item1.length === 0) return;
-
- // 加入序号保留字段
- item1[table.config.numbersName] = numbers;
-
- // 记录下标索引,用于恢复排序
- if(!sort) item1[table.config.indexName] = i1;
-
- // 遍历表头
- that.eachCols(function(i3, item3){
- var field = item3.field || i3;
- var key = item3.key;
- var content = item1[field];
-
- if(content === undefined || content === null) content = '';
- if(item3.colGroup) return;
-
- // td 内容
- var td = [''
- ,' '
- + function(){
- var tplData = $.extend(true, {
- LAY_COL: item3
- }, item1);
- var checkName = table.config.checkName;
- var disabledName = table.config.disabledName;
-
- //渲染不同风格的列
- switch(item3.type){
- case 'checkbox': // 复选
- return '';
- break;
- case 'radio': // 单选
- if(tplData[checkName]){
- thisCheckedRowIndex = i1;
- }
- return '';
- break;
- case 'numbers':
- return numbers;
- break;
- };
-
- //解析工具列模板
- if(item3.toolbar){
- return laytpl($(item3.toolbar).html()||'').render(tplData);
- }
- return parseTempData.call(that, {
- item3: item3
- ,content: content
- ,tplData: tplData
- });
- }()
- ,' | '].join('');
-
- tds.push(td);
- if(item3.fixed && item3.fixed !== 'right') tds_fixed.push(td);
- if(item3.fixed === 'right') tds_fixed_r.push(td);
- });
-
- trs.push(''+ tds.join('') + '
');
- trs_fixed.push(''+ tds_fixed.join('') + '
');
- trs_fixed_r.push(''+ tds_fixed_r.join('') + '
');
+ that.getTrHtml(data, sort, curr, {
+ trs: trs,
+ trs_fixed: trs_fixed,
+ trs_fixed_r: trs_fixed_r
});
// 容器的滚动条位置
@@ -1211,9 +1239,9 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.renderForm();
// 标注选中行样式
- typeof thisCheckedRowIndex === 'number' && that.setRowChecked({
+ typeof that.thisCheckedRowIndex === 'number' && that.setRowChecked({
type: 'radio',
- index: thisCheckedRowIndex
+ index: that.thisCheckedRowIndex
}, true);
that.syncCheckAll();
@@ -1226,10 +1254,10 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.scrollPatch();
}, 50);
that.haveInit = true;
-
+
layer.close(that.tipsIndex);
};
-
+
table.cache[that.key] = data; //记录数据
//显示隐藏合计栏
@@ -1242,20 +1270,19 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
? 'addClass'
: 'removeClass'
](HIDE_V);
-
+
//如果无数据
if(data.length === 0){
- that.renderForm();
return that.errorView(options.text.none);
} else {
that.layFixLeft.removeClass(HIDE);
}
-
+
//如果执行初始排序
if(sort){
return render();
}
-
+
//正常初始化数据渲染
render(); //渲染数据
that.renderTotal(data, totalRowData); //数据合计
@@ -1287,29 +1314,29 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
laypage.render(options.page);
}
};
-
+
// 数据合计行
Class.prototype.renderTotal = function(data, totalRowData){
var that = this;
var options = that.config;
var totalNums = {};
-
+
if(!options.totalRow) return;
layui.each(data, function(i1, item1){
// 若数据项为空数组,则不往下执行(因为删除数据时,会将原有数据设置为 [])
if(layui.type(item1) === 'array' && item1.length === 0) return;
-
+
that.eachCols(function(i3, item3){
var field = item3.field || i3
,content = item1[field];
- if(item3.totalRow){
+ if(item3.totalRow){
totalNums[field] = (totalNums[field] || 0) + (parseFloat(content) || 0);
}
});
});
-
+
that.dataTotal = []; // 记录合计行结果
var tds = [];
@@ -1321,26 +1348,26 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 合计数据的小数点位数处理
var decimals = 'totalRowDecimals' in item3 ? item3.totalRowDecimals : 2;
- var thisTotalNum = totalNums[field]
+ var thisTotalNum = totalNums[field]
? parseFloat(totalNums[field] || 0).toFixed(decimals)
: '';
-
+
// td 显示内容
var content = function(){
var text = item3.totalRowText || '';
var tplData = {
LAY_COL: item3
};
-
+
tplData[field] = thisTotalNum;
-
+
// 获取自动计算的合并内容
var getContent = item3.totalRow ? (parseTempData.call(that, {
item3: item3
,content: thisTotalNum
,tplData: tplData
}) || text) : text;
-
+
// 如果直接传入了合计行数据,则不输出自动计算的结果
return TOTAL_NUMS || getContent;
}();
@@ -1387,21 +1414,21 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
return content;
}()
,''].join('');
-
+
tds.push(td);
});
var patchElem = that.layTotal.find('.layui-table-patch'); // 可能存在滚动条补丁
that.layTotal.find('tbody').html('' + tds.join('') + (patchElem.length ? patchElem.get(0).outerHTML : '') + '
');
};
-
+
//找到对应的列元素
Class.prototype.getColElem = function(parent, key){
var that = this
,options = that.config;
return parent.eq(0).find('.laytable-cell-'+ key + ':eq(0)');
};
-
+
//渲染表单
Class.prototype.renderForm = function(type){
var that = this
@@ -1409,7 +1436,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,filter = that.elem.attr('lay-filter');
form.render(type, filter);
};
-
+
// 标记行选中状态
Class.prototype.setRowChecked = function(opts, selectedStyle){
var that = this;
@@ -1423,7 +1450,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
type: 'checkbox', // 选中方式
checked: true // 选中状态
}, opts);
-
+
// 标注当前行选中样式
if(opts.type !== 'checkbox' && opts.index !== 'all'){
tr.addClass(ELEM_CLICK).siblings('tr').removeClass(ELEM_CLICK);
@@ -1434,7 +1461,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 同步数据选中属性值
var thisData = table.cache[that.key];
-
+
// 设置数据选中属性
layui.each(thisData, function(i, item){
if(opts.index === i || opts.index === 'all'){
@@ -1453,7 +1480,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.syncCheckAll();
that.renderForm(opts.type);
};
-
+
// 数据排序
Class.prototype.sort = function(opts){ // field, type, pull, fromEvent
var that = this;
@@ -1464,7 +1491,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var data = table.cache[that.key], thisData;
opts = opts || {};
-
+
// 字段匹配
if(typeof opts.field === 'string'){
field = opts.field;
@@ -1482,7 +1509,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
try {
var field = field || opts.field.data('field')
,key = opts.field.data('key');
-
+
// 如果欲执行的排序已在状态中,则不执行渲染
if(that.sortKey && !opts.pull){
if(field === that.sortKey.field && opts.type === that.sortKey.sort){
@@ -1497,13 +1524,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
} catch(e){
hint.error('Table modules: sort field \''+ field +'\' not matched');
}
-
+
// 记录排序索引和类型
that.sortKey = {
field: field
,sort: opts.type
};
-
+
// 默认为前端自动排序。如果否,则需自主排序(通常为服务端处理好排序)
if(options.autoSort){
if(opts.type === 'asc'){ //升序
@@ -1516,18 +1543,18 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
delete options.initSort;
}
}
-
+
res[options.response.dataName] = thisData || data;
// 重载数据
that.renderData({
- res: res,
- curr: that.page,
- count: that.count,
+ res: res,
+ curr: that.page,
+ count: that.count,
sort: true,
type: opts.reloadType
});
-
+
// 排序是否来自于点击表头事件触发
if(opts.fromEvent){
options.initSort = {
@@ -1539,7 +1566,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}, options.initSort));
}
};
-
+
//请求loading
Class.prototype.loading = function(hide){
var that = this
@@ -1557,7 +1584,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
}
};
-
+
//同步选中值状态
Class.prototype.setCheckData = function(index, checked){
var that = this
@@ -1567,7 +1594,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
if(layui.type(thisData[index]) === 'array') return;
thisData[index][options.checkName] = checked;
};
-
+
// 同步全选按钮状态
Class.prototype.syncCheckAll = function(){
var that = this
@@ -1581,7 +1608,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
});
return checked;
};
-
+
if(!checkAllElem[0]) return;
if(table.checkStatus(that.key).isAll){
@@ -1598,7 +1625,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
syncColsCheck(false);
}
};
-
+
// 获取 cssRule
Class.prototype.getCssRule = function(key, callback){
var that = this;
@@ -1612,7 +1639,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
});
};
-
+
//让表格铺满
Class.prototype.fullSize = function(){
var that = this
@@ -1641,12 +1668,12 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
thElem.height(headerMain.find('th[data-key="' + thElem.attr('data-key') + '"]').height() + 'px');
})
}
-
+
if(!height) return;
//减去列头区域的高度
bodyHeight = parseFloat(height) - (that.layHeader.outerHeight() || 38); //此处的数字常量是为了防止容器处在隐藏区域无法获得高度的问题,暂时只对默认尺寸的表格做支持。
-
+
//减去工具栏的高度
if(options.toolbar){
bodyHeight -= (that.layTool.outerHeight() || 50);
@@ -1656,7 +1683,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
if(options.totalRow){
bodyHeight -= (that.layTotal.outerHeight() || 40);
}
-
+
//减去分页栏的高度
if(options.page || options.pagebar){
bodyHeight -= (that.layPage.outerHeight() || 43);
@@ -1673,7 +1700,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.layMain.outerHeight(bodyHeight);
}
};
-
+
//获取滚动条宽度
Class.prototype.getScrollWidth = function(elem){
var width = 0;
@@ -1691,7 +1718,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
return width;
};
-
+
//滚动条补丁
Class.prototype.scrollPatch = function(){
var that = this;
@@ -1700,7 +1727,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var scollHeight = that.layMain.height() - that.layMain.prop('clientHeight'); // 横向滚动条高度
var getScrollWidth = that.getScrollWidth(that.layMain[0]); // 获取主容器滚动条宽度,如果有的话
var outWidth = layMainTable.outerWidth() - that.layMain.width(); // 表格内容器的超出宽度
-
+
// 添加补丁
var addPatch = function(elem){
if(scollWidth && scollHeight){
@@ -1716,28 +1743,28 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
elem.find('.layui-table-patch').remove();
}
};
-
+
addPatch(that.layHeader);
addPatch(that.layTotal);
-
+
// 固定列区域高度
var mainHeight = that.layMain.height();
var fixHeight = mainHeight - scollHeight;
that.layFixed.find(ELEM_BODY).css(
- 'height',
+ 'height',
layMainTable.height() >= fixHeight ? fixHeight : 'auto'
);
// 表格宽度小于容器宽度时,隐藏固定列
that.layFixRight[
- (table.cache[that.key] && table.cache[that.key].length) && outWidth > 0
- ? 'removeClass'
+ (table.cache[that.key] && table.cache[that.key].length) && outWidth > 0
+ ? 'removeClass'
: 'addClass'
](HIDE);
-
+
// 操作栏
- that.layFixRight.css('right', scollWidth - 1);
+ that.layFixRight.css('right', scollWidth - 1);
};
// 事件处理
@@ -1751,7 +1778,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var _BODY = $('body');
var dict = {};
-
+
// 工具栏操作事件
that.layTool.on('click', '*[lay-event]', function(e){
var othis = $(this)
@@ -1759,35 +1786,35 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,openPanel = function(sets){
var list = $(sets.list)
,panel = $('');
-
+
panel.html(list);
-
+
// 限制最大高度
if(options.height){
panel.css('max-height', options.height - (that.layTool.outerHeight() || 50));
}
-
+
// 插入元素
othis.find('.' + ELEM_TOOL_PANEL)[0] || othis.append(panel);
that.renderForm();
-
+
panel.on('click', function(e){
layui.stope(e);
});
-
+
sets.done && sets.done(panel, list)
};
-
+
layui.stope(e);
_DOC.trigger('table.tool.panel.remove');
layer.close(that.tipsIndex);
-
+
switch(events){
case 'LAYTABLE_COLS': // 筛选列
openPanel({
list: function(){
var lis = [];
- that.eachCols(function(i, item){
+ that.eachCols(function(i, item){
if(item.field && item.type == 'normal'){
lis.push('');
}
@@ -1860,7 +1887,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,'*.layui-hide{display: none}'
,''].join('')
,html = $(that.layHeader.html()); //输出表头
-
+
html.append(that.layMain.find('table').html()); //输出表体
html.append(that.layTotal.find('table').html()) //输出合计行
@@ -1877,7 +1904,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
printWin.close();
break;
}
-
+
layui.event.call(this, MOD_NAME, 'toolbar('+ filter +')', $.extend({
event: events
,config: options
@@ -1888,13 +1915,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.layPagebar.on('click', '*[lay-event]', function(e){
var othis = $(this);
var events = othis.attr('lay-event');
-
+
layui.event.call(this, MOD_NAME, 'pagebar('+ filter +')', $.extend({
event: events
,config: options
},{}));
});
-
+
// 拖拽调整宽度
th.on('mousemove', function(e){
var othis = $(this)
@@ -1915,7 +1942,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var key = othis.data('key');
e.preventDefault();
dict.offset = [e.clientX, e.clientY]; //记录初始坐标
-
+
that.getCssRule(key, function(item){
var width = item.style.width || othis.outerWidth();
dict.rule = item;
@@ -1929,16 +1956,16 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
thisTable.eventMoveElem = othis;
}
});
-
+
// 拖拽中
if(!thisTable.docEvent){
_DOC.on('mousemove', function(e){
if(thisTable.eventMoveElem){
var dict = thisTable.eventMoveElem.data(DATA_MOVE_NAME) || {};
-
+
thisTable.eventMoveElem.data('resizing', 1);
e.preventDefault();
-
+
if(dict.rule){
var setWidth = dict.ruleWidth + e.clientX - dict.offset[0];
var id = thisTable.eventMoveElem.closest('.' + ELEM_VIEW).attr('lay-id');
@@ -1990,7 +2017,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 已给 document 执行全局事件,避免重复绑定
thisTable.docEvent = true;
-
+
// 排序
th.on('click', function(e){
var othis = $(this);
@@ -2001,8 +2028,8 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 排序不触发的条件
if(!elemSort[0] || othis.data('resizing') === 1){
return othis.removeData('resizing');
- }
-
+ }
+
if(nowType === 'asc'){
type = 'desc';
} else if(nowType === 'desc'){
@@ -2011,8 +2038,8 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
type = 'asc';
}
that.sort({
- field: othis,
- type: type,
+ field: othis,
+ type: type,
fromEvent: true
});
}).find(ELEM_SORT+' .layui-edge ').on('click', function(e){
@@ -2022,19 +2049,19 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
layui.stope(e);
if(index === 0){
that.sort({
- field: field,
- type: 'asc',
+ field: field,
+ type: 'asc',
fromEvent: true
});
} else {
that.sort({
- field: field,
- type: 'desc',
+ field: field,
+ type: 'desc',
fromEvent: true
});
}
});
-
+
//数据行中的事件返回的公共对象成员
var commonMember = that.commonMember = function(sets){
var othis = $(this);
@@ -2075,7 +2102,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}, data)
}));
td.data('content', value);
- }
+ }
// 更新其他包含自定义模板且可能有所关联的列视图
else if(related && (item3.templet || item3.toolbar)){
var thisTd = tr.children('td[data-field="'+ (item3.field || i) +'"]');
@@ -2103,10 +2130,10 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
// 获取当前列
};
-
+
return $.extend(obj, sets);
};
-
+
// 复选框选择(替代元素的 click 事件)
that.elem.on('click', 'input[name="layTableCheckbox"]+', function(){
var checkbox = $(this).prev()
@@ -2129,18 +2156,18 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.setCheckData(index, checked);
that.syncCheckAll();
}
-
+
// 事件
layui.event.call(
- checkbox[0],
- MOD_NAME, 'checkbox('+ filter +')',
+ checkbox[0],
+ MOD_NAME, 'checkbox('+ filter +')',
commonMember.call(checkbox[0], {
checked: checked,
type: isAll ? 'all' : 'one'
})
);
});
-
+
// 单选框选择
that.elem.on('click', 'input[lay-type="layTableRadio"]+', function(){
var radio = $(this).prev();
@@ -2157,14 +2184,14 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 事件
layui.event.call(
- radio[0],
- MOD_NAME, 'radio('+ filter +')',
+ radio[0],
+ MOD_NAME, 'radio('+ filter +')',
commonMember.call(radio[0], {
checked: checked
})
);
});
-
+
// 行事件
that.layBody.on('mouseenter', 'tr', function(){ //鼠标移入行
var othis = $(this);
@@ -2184,7 +2211,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
if (!options.defaultContextmenu) e.preventDefault();
setRowEvent.call(this, 'rowContextmenu');
});;
-
+
// 创建行单击、双击、菜单事件
var setRowEvent = function(eventType){
var othis = $(this);
@@ -2194,7 +2221,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
commonMember.call(othis.children('td')[0])
);
};
-
+
// 渲染单元格编辑状态
var renderGridEdit = function(othis, e){
othis = $(othis);
@@ -2210,10 +2237,10 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 是否开启编辑
// 若 edit 传入函数,则根据函数的返回结果判断是否开启编辑
- var editType = typeof col.edit === 'function'
- ? col.edit(data)
+ var editType = typeof col.edit === 'function'
+ ? col.edit(data)
: col.edit;
-
+
// 显示编辑表单
if(editType){
var input = $(function(){
@@ -2223,7 +2250,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
return inputElem;
}());
-
+
input[0].value = othis.data('content') || data[field] || elemCell.text();
othis.find('.'+ELEM_EDIT)[0] || othis.append(input);
input.focus();
@@ -2281,26 +2308,26 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}).on('mouseleave', 'td', function(){
gridExpand.call(this, 'hide');
});
-
+
//单元格展开图标
var ELEM_GRID = 'layui-table-grid', ELEM_GRID_DOWN = 'layui-table-grid-down', ELEM_GRID_PANEL = 'layui-table-grid-panel'
,gridExpand = function(hide){
var othis = $(this)
,elemCell = othis.children(ELEM_CELL);
-
+
if(othis.data('off')) return; //不触发事件
-
+
if(hide){
othis.find('.layui-table-grid-down').remove();
} else if((
- elemCell.prop('scrollWidth') > elemCell.outerWidth() ||
+ elemCell.prop('scrollWidth') > elemCell.outerWidth() ||
elemCell.find("br").length > 0
) && !options.lineStyle){
if(elemCell.find('.'+ ELEM_GRID_DOWN)[0]) return;
othis.append('
');
}
};
-
+
//单元格展开事件
that.layBody.on('click', '.'+ ELEM_GRID_DOWN, function(e){
var othis = $(this)
@@ -2333,19 +2360,19 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
});
}
});
-
+
layui.stope(e);
});
-
+
// 行工具条操作事件
var toolFn = function(type){
var othis = $(this);
var index = othis.parents('tr').eq(0).data('index');
-
+
layui.event.call(
- this,
- MOD_NAME,
- (type || 'tool') + '('+ filter +')',
+ this,
+ MOD_NAME,
+ (type || 'tool') + '('+ filter +')',
commonMember.call(this, {
event: othis.attr('lay-event')
})
@@ -2365,17 +2392,17 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
toolFn.call(this, 'toolDouble');
layui.stope(e);
});
-
+
//同步滚动条
that.layMain.on('scroll', function(){
var othis = $(this)
,scrollLeft = othis.scrollLeft()
,scrollTop = othis.scrollTop();
-
+
that.layHeader.scrollLeft(scrollLeft);
that.layTotal.scrollLeft(scrollLeft);
that.layFixed.find(ELEM_BODY).scrollTop(scrollTop);
-
+
layer.close(that.tipsIndex);
});
@@ -2384,20 +2411,20 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.resize();
});
};
-
+
//一次性事件
;(function(){
//全局点击
_DOC.on('click', function(){
_DOC.trigger('table.remove.tool.panel');
});
-
+
//工具面板移除事件
_DOC.on('table.remove.tool.panel', function(){
$('.' + ELEM_TOOL_PANEL).remove();
});
})();
-
+
// 初始化
table.init = function(filter, settings){
settings = settings || {};
@@ -2418,7 +2445,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
attr: attrData ? 'lay-data' : null,
errorText: errorTips + (attrData || othis.attr('lay-options'))
});
-
+
var options = $.extend({
elem: this
,cols: []
@@ -2427,9 +2454,9 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,size: othis.attr('lay-size') //尺寸
,even: typeof othis.attr('lay-even') === 'string' //偶数行背景
}, table.config, settings, tableData);
-
+
filter && othis.hide();
-
+
//获取表头数据
othis.find('thead>tr').each(function(i){
options.cols[i] = [];
@@ -2440,7 +2467,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
attr: attrData ? 'lay-data' : null,
errorText: errorTips + (attrData || th.attr('lay-options'))
});
-
+
var row = $.extend({
title: th.text()
,colspan: parseInt(th.attr('colspan')) || 0 //列单元格
@@ -2478,7 +2505,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
return that;
};
-
+
//记录所有实例
thisTable.that = {}; //记录所有实例对象
thisTable.config = {}; //记录所有实例配置项
@@ -2515,7 +2542,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
table.eachCols = function(id, callback, cols){
var config = thisTable.config[id] || {}
,arrs = [], index = 0;
-
+
cols = $.extend(true, [], cols || config.cols);
//重新整理表头结构
@@ -2535,10 +2562,10 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
typeof callback === 'function' && callback(i, item);
});
};
-
+
eachArrs();
};
-
+
// 获取表格选中状态
table.checkStatus = function(id){
var nums = 0
@@ -2571,7 +2598,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
if(!that) return;
that.setRowChecked(opts);
};
-
+
// 获取表格当前页的所有行数据
table.getData = function(id){
var arr = []
@@ -2591,16 +2618,16 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
if(id){
var config = getThisTableConfig(id); // 获取当前实例配置项
if(!config) return;
-
+
getThisTable(id).resize();
-
+
} else { // 否则重置所有表格实例尺寸
layui.each(thisTable.that, function(){
this.resize();
});
}
};
-
+
// 表格导出
table.exportFile = function(id, data, opts){
data = data || table.clearCacheKey(table.cache[id]);
@@ -2618,15 +2645,15 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
,xls: 'application/vnd.ms-excel'
})[type];
var alink = document.createElement("a");
-
+
if(device.ie) return hint.error('IE_NOT_SUPPORT_EXPORTS');
-
+
alink.href = 'data:'+ textType +';charset=utf-8,\ufeff'+ encodeURIComponent(function(){
var dataTitle = [];
var dataMain = [];
var dataTotal = [];
var fieldsIsHide = {};
-
+
// 表头和表体
layui.each(data, function(i1, item1){
var vals = [];
@@ -2648,7 +2675,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var content = item1[item3.field];
if(content === undefined || content === null) content = '';
-
+
i1 == 0 && dataTitle.push(item3.fieldTitle || item3.title || item3.field || '');
// 解析内容
@@ -2677,24 +2704,24 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
dataMain.push(vals.join(','));
});
-
+
// 表合计
thatTable && layui.each(thatTable.dataTotal, function(i, o){
fieldsIsHide[o.field] || dataTotal.push(o.total + '\t');
});
-
+
return dataTitle.join(',') + '\r\n' + dataMain.join('\r\n') + '\r\n' + dataTotal.join(',');
}());
-
+
alink.download = (opts.title || config.title || 'table_'+ (config.index || '')) + '.' + type;
document.body.appendChild(alink);
alink.click();
- document.body.removeChild(alink);
+ document.body.removeChild(alink);
};
// 获取表格配置信息
table.getOptions = function (id) {
- return $.extend(true, {}, getThisTableConfig(id));
+ return getThisTableConfig(id);
}
// 显示或隐藏列
@@ -2744,15 +2771,15 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 重新适配尺寸
that.resize();
}
-
+
// 重载
table.reload = function(id, options, deep, type){
var config = getThisTableConfig(id); //获取当前实例配置项
if(!config) return;
-
+
var that = getThisTable(id);
that.reload(options, deep, type);
-
+
return thisTable.call(that);
};
@@ -2761,22 +2788,20 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var args = $.extend([], arguments);
args[3] = 'reloadData';
- // 重载时,与数据相关的参数
+ // 重载时,影响整个结构的参数,不适合更新的参数
var dataParams = new RegExp('^('+ [
- 'data', 'url', 'method', 'contentType',
- 'dataType','jsonpCallback',
- 'headers', 'where', 'page', 'limit',
- 'request', 'response', 'parseData',
- 'scrollPos'
+ 'elem', 'id', 'cols', 'width', 'height', 'maxHeight',
+ 'toolbar', 'defaultToolbar',
+ 'className', 'css', 'totalRow', 'page', 'pagebar'
].join('|') + ')$');
// 过滤与数据无关的参数
layui.each(args[1], function (key, value) {
- if(!dataParams.test(key)){
+ if(dataParams.test(key)){
delete args[1][key];
}
});
-
+
return table.reload.apply(null, args);
};
@@ -2785,7 +2810,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var inst = new Class(options);
return thisTable.call(inst);
};
-
+
// 清除临时 Key
table.clearCacheKey = function(data){
data = $.extend({}, data);
@@ -2795,12 +2820,12 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
delete data[table.config.disabledName];
return data;
};
-
+
// 自动完成渲染
$(function(){
table.init();
});
-
+
exports(MOD_NAME, table);
});
diff --git a/src/modules/treeTable.js b/src/modules/treeTable.js
new file mode 100644
index 00000000..019b010b
--- /dev/null
+++ b/src/modules/treeTable.js
@@ -0,0 +1,1469 @@
+/**
+ * layui.treeTable
+ * 树表组件
+ */
+
+layui.define(['table'], function (exports) {
+ "use strict";
+
+ var $ = layui.$;
+ var form = layui.form;
+ var table = layui.table;
+ var hint = layui.hint();
+
+ // api
+ var treeTable = {
+ config: {},
+ // 事件
+ on: table.on,
+ // 遍历字段
+ eachCols: table.eachCols,
+ index: table.index,
+ set: function (options) {
+ var that = this;
+ that.config = $.extend({}, that.config, options);
+ return that;
+ },
+ resize: table.resize
+ };
+
+ // 操作当前实例
+ var thisTreeTable = function () {
+ var that = this
+ , options = that.config
+ , id = options.id || options.index;
+
+ return {
+ config: options,
+ reload: function (options, deep) {
+ that.reload.call(that, options, deep);
+ },
+ reloadData: function (options, deep) {
+ treeTable.reloadData(id, options, deep);
+ }
+ }
+ }
+
+ // 获取当前实例
+ var getThisTable = function (id) {
+ var that = thisTreeTable.that[id];
+ if (!that) hint.error(id ? ('The treeTable instance with ID \'' + id + '\' not found') : 'ID argument required');
+ return that || null;
+ }
+
+ // 获取当前实例配置项
+ var getThisTableConfig = function (id) {
+ return getThisTable(id).config;
+ }
+
+ // 字符
+ var MOD_NAME = 'treeTable'
+ , ELEMTREE = '.layui-table-tree'
+ , THIS = 'layui-this'
+ , SHOW = 'layui-show'
+ , HIDE = 'layui-hide'
+ , HIDE_V = 'layui-hide-v'
+ , DISABLED = 'layui-disabled'
+ , NONE = 'layui-none'
+
+ , ELEM_VIEW = '.layui-table-view'
+ , ELEM_TOOL = '.layui-table-tool'
+ , ELEM_BOX = '.layui-table-box'
+ , ELEM_INIT = '.layui-table-init'
+ , ELEM_HEADER = '.layui-table-header'
+ , ELEM_BODY = '.layui-table-body'
+ , ELEM_MAIN = '.layui-table-main'
+ , ELEM_FIXED = '.layui-table-fixed'
+ , ELEM_FIXL = '.layui-table-fixed-l'
+ , ELEM_FIXR = '.layui-table-fixed-r'
+ , ELEM_TOTAL = '.layui-table-total'
+ , ELEM_PAGE = '.layui-table-page'
+ , ELEM_SORT = '.layui-table-sort'
+ , ELEM_EDIT = 'layui-table-edit'
+ , ELEM_HOVER = 'layui-table-hover'
+ , ELEM_GROUP = 'laytable-cell-group'
+
+ var LAY_DATA_INDEX = 'LAY_DATA_INDEX';
+ var LAY_DATA_INDEX_HISTORY = 'LAY_DATA_INDEX_HISTORY';
+ var LAY_PARENT_INDEX = 'LAY_PARENT_INDEX';
+ var LAY_CHECKBOX_HALF = 'LAY_CHECKBOX_HALF';
+ var LAY_EXPAND = 'LAY_EXPAND';
+ var LAY_HAS_EXPANDED = 'LAY_HAS_EXPANDED';
+
+ // 构造器
+ var Class = function (options) {
+ var that = this;
+ that.index = ++treeTable.index;
+ that.config = $.extend(true, {}, that.config, treeTable.config, options);
+ // 处理一些属性
+ that.init();
+ that.render();
+ };
+
+ var updateCache = function (id, childrenKey, data) {
+ var tableCache = table.cache[id];
+ layui.each(data || tableCache, function (index, item) {
+ var itemDataIndex = item[LAY_DATA_INDEX];
+ if (itemDataIndex.indexOf('-') !== -1) {
+ tableCache[itemDataIndex] = item
+ }
+ item[childrenKey] && updateCache(id, childrenKey, item[childrenKey]);
+ })
+ }
+
+ Class.prototype.init = function () {
+ var that = this;
+ var options = that.config;
+
+ // 先初始一个空的表格以便拿到对应的表格实例信息
+ var tableIns = table.render($.extend({}, options, {
+ data: [],
+ url: '',
+ done: null
+ }))
+ var id = tableIns.config.id;
+ thisTreeTable.that[id] = that; // 记录当前实例对象
+ that.tableIns = tableIns;
+
+ var treeOptions = options.tree;
+ var isParentKey = treeOptions.data.key.isParent;
+ var childrenKey = treeOptions.data.key.children;
+
+ // 处理属性
+ var parseData = options.parseData;
+ var done = options.done;
+
+ if (options.url) {
+ // 异步加载的时候需要处理parseData进行转换
+ options.parseData = function () {
+ var parseDataThat = this;
+ var args = arguments;
+ var retData = args[0];
+ if (layui.type(parseData) === 'function') {
+ retData = parseData.apply(parseDataThat, args) || args[0];
+ }
+ var dataName = parseDataThat.response.dataName;
+ // 处理simpleData
+ if (treeOptions.data.simpleData.enable && !treeOptions.async.enable) { // 异步加载和simpleData不应该一起使用
+ retData[dataName] = that.flatToTree(retData[dataName]);
+ }
+
+ that.initData(retData[dataName]);
+
+ return retData;
+ }
+ } else {
+ options.data = options.data || [];
+ // 处理simpleData
+ if (treeOptions.data.simpleData.enable) {
+ options.data = that.flatToTree(options.data);
+ }
+ if (options.initSort && options.initSort.type) {
+ options.data = layui.sort(options.data, options.initSort.field, options.initSort.type === 'desc')
+ }
+ that.initData(options.data);
+ }
+
+ options.done = function () {
+ var args = arguments;
+ var doneThat = this;
+
+ var tableView = this.elem.next();
+ that.updateStatus(null, {
+ LAY_HAS_EXPANDED: false // 去除已经打开过的状态
+ });
+ // 更新cache中的内容 将子节点也存到cache中
+ updateCache(id, childrenKey);
+ // 更新全选框的状态
+ var layTableAllChooseElem = tableView.find('[name="layTableCheckbox"][lay-filter="layTableAllChoose"]');
+ if (layTableAllChooseElem.length) {
+ var checkStatus = treeTable.checkStatus(id);
+ layTableAllChooseElem.prop({
+ checked: checkStatus.isAll && checkStatus.data.length,
+ indeterminate: !checkStatus.isAll && checkStatus.data.length
+ })
+ }
+
+ that.renderTreeTable(tableView);
+
+ if (layui.type(done) === 'function') {
+ return done.apply(doneThat, args);
+ }
+ }
+ }
+
+ // 初始默认配置
+ Class.prototype.config = {
+ tree: {
+ view: {
+ indent: 14, // 层级缩进量
+ flexIconClose: '', // 关闭时候的折叠图标
+ flexIconOpen: '', // 打开时候的折叠图标
+ showIcon: true, // 是否显示图标(节点类型图标)
+ icon: '', // 节点图标,如果设置了这个属性或者数据中有这个字段信息,不管打开还是关闭都以这个图标的值为准
+ iconClose: '', // 打开时候的图标
+ iconOpen: '', // 关闭时候的图标
+ iconLeaf: '', // 叶子节点的图标
+ showFlexIconIfNotParent: false, // 当节点不是父节点的时候是否显示折叠图标
+ dblClickExpand: true, // 双击节点时,是否自动展开父节点的标识
+ },
+ data: {
+ key: {
+ checked: 'LAY_CHECKED', // 节点数据中保存 check 状态的属性名称
+ children: "children", // 节点数据中保存子节点数据的属性名称
+ isParent: "isParent", // 节点数据保存节点是否为父节点的属性名称
+ isHidden: "hidden", // 节点数据保存节点是否隐藏的属性名称
+ name: "name", // 节点数据保存节点名称的属性名称
+ title: "", // 节点数据保存节点提示信息的属性名称
+ url: "url", // 节点数据保存节点链接的目标 URL 的属性名称
+ },
+ simpleData: {
+ enable: false, // 是否简单数据模式
+ idKey: "id", // 唯一标识的属性名称
+ pIdKey: "parentId",
+ rootPId: null
+ }
+ },
+ async: {
+ enable: false, // 是否开启异步加载模式,只有开启的时候其他参数才起作用
+ url: '', // 异步加载的接口,可以根据需要设置与顶层接口不同的接口,如果相同可以不设置该参数
+ type: null, // 请求的接口类型,设置可缺省同上
+ contentType: null, // 提交参数的数据类型,设置可缺省同上
+ headers: null, // 设置可缺省同上
+ where: null, // 设置可缺省同上
+ autoParam: [], // 自动参数
+ },
+ callback: {
+ beforeExpand: null, // 展开前的回调 return false 可以阻止展开的动作
+ onExpand: null, // 展开之后的回调
+ }
+ },
+ autoSort: false
+ };
+
+ Class.prototype.getOptions = function () {
+ var that = this;
+ if (that.tableIns) {
+ return table.getOptions(that.tableIns.config.id); // 获取表格的实时配置信息
+ } else {
+ return that.config;
+ }
+ };
+
+ function flatToTree(flatArr, idKey, pIdKey, childrenKey, rootPId) {
+ idKey = idKey || 'id';
+ pIdKey = pIdKey || 'parentId';
+ childrenKey = childrenKey || 'children';
+ // 创建一个空的 nodes 对象,用于保存所有的节点
+ var nodes = {};
+ // 遍历所有节点,将其加入 nodes 对象中
+ layui.each(flatArr, function (index, item) {
+ nodes[item[idKey]] = $.extend({}, item);
+ nodes[item[idKey]][childrenKey] = [];
+ })
+ // 遍历所有节点,将其父子关系加入 nodes 对象
+ layui.each(nodes, function (index, item) {
+ if (item[pIdKey] && nodes[item[pIdKey]]) {
+ nodes[item[pIdKey]][childrenKey].push(item);
+ }
+ })
+ // 返回顶层节点
+ return Object.values(nodes).filter(function (item) {
+ return rootPId ? item[pIdKey] === rootPId : !item[pIdKey];
+ })
+ }
+
+ Class.prototype.flatToTree = function (tableData) {
+ var that = this;
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var simpleDataOptions = treeOptions.data.simpleData;
+ var tableId = options.id;
+
+ tableData = tableData || table.cache[tableId];
+
+ return flatToTree(tableData, simpleDataOptions.idKey, simpleDataOptions.pIdKey, treeOptions.data.key.children, simpleDataOptions.rootPId)
+ }
+
+ Class.prototype.treeToFlat = function (tableData, parentId, parentIndex) {
+ var that = this;
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var childrenKey = treeOptions.data.key.children;
+ var pIdKey = treeOptions.data.simpleData.pIdKey;
+
+ var flat = [];
+ layui.each(tableData, function (i1, item1) {
+ var dataIndex = (parentIndex ? parentIndex + '-' : '') + i1;
+ var dataNew = $.extend({}, item1);
+ dataNew[childrenKey] = null;
+ dataNew[pIdKey] = item1[pIdKey] || parentId;
+ flat.push(dataNew);
+ flat = flat.concat(that.treeToFlat(item1[childrenKey], item1[treeOptions.data.simpleData.idKey], dataIndex));
+ });
+
+ return flat;
+ }
+
+ // 通过index获取节点数据
+ Class.prototype.getNodeDataByIndex = function (index, clone, newValue) {
+ var that = this;
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var tableId = options.id;
+
+ var dataCache = table.cache[tableId][index];
+ if (newValue !== 'delete' && dataCache) {
+ return clone ? $.extend({}, dataCache) : dataCache;
+ }
+
+ var tableData = that.getTableData();
+ index += '';
+ var indexArr = index.split('-');
+
+ var dataRet = tableData;
+ var tableCache = (options.url || indexArr.length > 1) ? null : table.cache[tableId]; // 只有在删除根节点的时候才需要处理
+ for (var i = 0, childrenKey = treeOptions.data.key.children; i < indexArr.length; i++) {
+ if (newValue && i === indexArr.length - 1) {
+ if (newValue === 'delete') {
+ // 删除
+ if (tableCache) {
+ // 同步cache
+ // tableCache.splice(tableCache.findIndex(function (value) {
+ // return value[LAY_DATA_INDEX] === index;
+ // }), 1);
+ layui.each(tableCache, function (i1, item1) {
+ if (item1[LAY_DATA_INDEX] === index) {
+ tableCache.splice(i1, 1);
+ return true;
+ }
+ })
+ }
+ return (i ? dataRet[childrenKey] : dataRet).splice(indexArr[i], 1)[0];
+ } else {
+ // 更新值
+ $.extend((i ? dataRet[childrenKey] : dataRet)[indexArr[i]], newValue);
+ }
+ }
+ dataRet = i ? dataRet[childrenKey][indexArr[i]] : dataRet[indexArr[i]];
+ }
+ return clone ? $.extend({}, dataRet) : dataRet;
+ }
+
+ treeTable.getNodeDataByIndex = function (id, index) {
+ var that = getThisTable(id);
+ return that.getNodeDataByIndex(index, true);
+ }
+
+ // 判断是否是父节点
+ var checkIsParent = function (data, isParentKey, childrenKey) {
+ isParentKey = isParentKey || 'isParent';
+ childrenKey = childrenKey || 'children';
+ layui.each(data, function (i1, item1) {
+ if (!(isParentKey in item1)) {
+ item1[isParentKey] = !!(item1[childrenKey] && item1[childrenKey].length);
+ checkIsParent(item1[childrenKey]);
+ }
+ })
+ }
+
+ Class.prototype.initData = function (data, parentIndex) {
+ var that = this;
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var tableId = options.id;
+ data = data || that.getTableData();
+ var isParentKey = treeOptions.data.key.isParent;
+ var childrenKey = treeOptions.data.key.children;
+
+ layui.each(data, function (i1, item1) {
+ if (!(isParentKey in item1)) {
+ item1[isParentKey] = !!(item1[childrenKey] && item1[childrenKey].length);
+ }
+ item1[LAY_DATA_INDEX_HISTORY] = item1[LAY_DATA_INDEX];
+ item1[LAY_PARENT_INDEX] = parentIndex = parentIndex || '';
+ var dataIndex = item1[LAY_DATA_INDEX] = (parentIndex ? parentIndex + '-' : '') + i1;
+ that.initData(item1[childrenKey] || [], dataIndex);
+ });
+
+ parentIndex || updateCache(tableId, childrenKey);
+
+ return data;
+ }
+
+ var expandNode = function (treeNode, expandFlag, sonSign, focus, callbackFlag) {
+ // treeNode // 需要展开的节点
+ var trElem = treeNode.trElem;
+ var tableViewElem = trElem.closest(ELEM_VIEW);
+ var tableViewFilterId = tableViewElem.attr('lay-filter');
+ var tableId = tableViewElem.attr('lay-id');
+ var options = table.getOptions(tableId);
+ var treeOptions = options.tree || {};
+ var isParentKey = treeOptions.data.key.isParent;
+ var trIndex = trElem.attr('lay-data-index'); // 可能出现多层
+ var treeTableThat = getThisTable(tableId);
+ var tableData = treeTableThat.getTableData();
+
+ var trData = treeTableThat.getNodeDataByIndex(trIndex);
+
+ var dataLevel = trElem.data('level');
+ var dataLevelNew = (dataLevel || 0) + 1;
+
+ // 后续调优:对已经展开的节点进行展开和已经关闭的节点进行关闭应该做优化减少不必要的代码执行 todo
+ var isToggle = layui.type(expandFlag) !== 'boolean';
+ var trExpand = isToggle ? !trData[LAY_EXPAND] : expandFlag;
+ var retValue = trData[isParentKey] ? trExpand : null;
+
+ if (callbackFlag && trExpand != trData[LAY_EXPAND] && (!trData['LAY_ASYNC_STATUS'] || trData['LAY_ASYNC_STATUS'] === 'local')) {
+ var beforeExpand = treeOptions.callback.beforeExpand;
+ if (layui.type(beforeExpand) === 'function') {
+ if (beforeExpand(tableId, trData, expandFlag) === false) {
+ return retValue;
+ }
+ }
+ }
+
+ var trExpanded = trData[LAY_HAS_EXPANDED]; // 展开过,包括异步加载
+
+ // 找到表格中的同类节点(需要找到lay-data-index一致的所有行)
+ var trsElem = tableViewElem.find('tr[lay-data-index="' + trIndex + '"]');
+ // 处理折叠按钮图标
+ var flexIconElem = trsElem.find('.layui-table-tree-flexIcon');
+ flexIconElem.html(trExpand ? treeOptions.view.flexIconOpen : treeOptions.view.flexIconClose)
+ trData[isParentKey] && flexIconElem.css('visibility', 'visible');
+ // 处理节点图标
+ if (treeOptions.view.showIcon && trData[isParentKey] && !trData.icon && !treeOptions.view.icon) {
+ var nodeIconElem = trsElem.find('.layui-table-tree-nodeIcon');
+ nodeIconElem.html(trExpand ? treeOptions.view.iconOpen : treeOptions.view.iconClose);
+ }
+
+ var childNodes = trData[treeOptions.data.key.children] || []; // 测试用后续需要改成子节点的字段名称
+ // 处理子节点展示与否
+ if (trExpand) {
+ // 展开
+ if (trExpanded) { // 已经展开过
+ trData[LAY_EXPAND] = trExpand;
+ tableViewElem.find(childNodes.map(function (value, index, array) {
+ return 'tr[lay-data-index="' + value[LAY_DATA_INDEX] + '"]'
+ }).join(',')).removeClass('layui-hide');
+ layui.each(childNodes, function (i1, item1) {
+ if (sonSign && !isToggle) { // 非状态切换的情况下
+ // 级联展开子节点
+ expandNode({trElem: tableViewElem.find('tr[lay-data-index="' + item1.LAY_DATA_INDEX + '"]').first()}, expandFlag, sonSign, focus, callbackFlag);
+ } else if (item1[LAY_EXPAND]) {
+ // 级联展开
+ expandNode({trElem: tableViewElem.find('tr[lay-data-index="' + item1.LAY_DATA_INDEX + '"]').first()}, true);
+ }
+ })
+ } else {
+ var asyncSetting = treeOptions.async || {};
+ var asyncUrl = asyncSetting.url || options.url;
+ // 提供一个能支持用户在获取子数据转换调用的回调,这样让子节点数据获取更加灵活 todo
+ if (asyncSetting.enable && asyncUrl && !trData['LAY_ASYNC_STATUS']) {
+ trData['LAY_ASYNC_STATUS'] = 'loading';
+ var params = {};
+ // 参数
+ var data = $.extend(params, asyncSetting.where || options.where);
+ var asyncAutoParam = asyncSetting.autoParam;
+ layui.each(asyncAutoParam, function (index, item) {
+ var itemStr = item;
+ var itemArr = item.split('=');
+ data[itemArr[0].trim()] = trData[(itemArr[1] || itemArr[0]).trim()]
+ })
+
+ var asyncContentType = asyncSetting.contentType || options.contentType;
+ if (asyncContentType && asyncContentType.indexOf("application/json") == 0) { // 提交 json 格式
+ data = JSON.stringify(data);
+ }
+ var asyncType = asyncSetting.method || options.method;
+ var asyncDataType = asyncSetting.dataType || options.dataType;
+ var asyncJsonpCallback = asyncSetting.jsonpCallback || options.jsonpCallback;
+ var asyncHeaders = asyncSetting.headers || options.headers;
+ var asyncParseData = asyncSetting.parseData || options.parseData;
+ var asyncResponse = asyncSetting.response || options.response;
+
+ // that.loading();
+ flexIconElem.html('')
+ $.ajax({
+ type: asyncType || 'get'
+ , url: asyncUrl
+ , contentType: asyncContentType
+ , data: data
+ , dataType: asyncDataType || 'json'
+ , jsonpCallback: asyncJsonpCallback
+ , headers: asyncHeaders || {}
+ , success: function (res) {
+ trData['LAY_ASYNC_STATUS'] = 'success';
+ // 若有数据解析的回调,则获得其返回的数据
+ if (typeof asyncParseData === 'function') {
+ res = asyncParseData.call(options, res) || res;
+ }
+ // 检查数据格式是否符合规范
+ if (res[asyncResponse.statusName] != asyncResponse.statusCode) {
+ trData['LAY_ASYNC_STATUS'] = 'error';
+ // 异常处理 todo
+ flexIconElem.html('');
+ // 事件
+ } else {
+ trData[treeOptions.data.key.children] = res[asyncResponse.dataName];
+ treeTableThat.initData(trData[treeOptions.data.key.children], trData[LAY_DATA_INDEX])
+ // 正常返回
+ expandNode(treeNode, true, isToggle ? false : sonSign, focus, callbackFlag);
+ }
+ }
+ , error: function (e, msg) {
+ trData['LAY_ASYNC_STATUS'] = 'error';
+ // 异常处理 todo
+ typeof options.error === 'function' && options.error(e, msg);
+ }
+ });
+ return retValue;
+ }
+ trData[LAY_EXPAND] = trExpand;
+ trExpanded = trData[LAY_HAS_EXPANDED] = true;
+ if (childNodes.length) {
+ // 判断是否需要排序
+ if (options.initSort && !options.url) {
+ var initSort = options.initSort;
+ if (initSort.type) {
+ childNodes = trData[treeOptions.data.key.children] = layui.sort(childNodes, initSort.field, initSort.type === 'desc');
+ } else {
+ // 恢复默认
+ childNodes = trData[treeOptions.data.key.children] = layui.sort(childNodes, table.config.indexName);
+ }
+ }
+ treeTableThat.initData(trData[treeOptions.data.key.children], trData[LAY_DATA_INDEX]);
+ // 将数据通过模板得出节点的html代码
+ var str2 = table.getTrHtml(tableId, childNodes, null, null, trIndex);
+
+ var str2Obj = {
+ trs: $(str2.trs.join('')),
+ trs_fixed: $(str2.trs_fixed.join('')),
+ trs_fixed_r: $(str2.trs_fixed_r.join(''))
+ }
+ layui.each(childNodes, function (childIndex, childItem) {
+ str2Obj.trs.eq(childIndex).attr({
+ 'data-index': childItem[LAY_DATA_INDEX],
+ 'lay-data-index': childItem[LAY_DATA_INDEX],
+ 'data-level': dataLevelNew
+ })
+ str2Obj.trs_fixed.eq(childIndex).attr({
+ 'data-index': childItem[LAY_DATA_INDEX],
+ 'lay-data-index': childItem[LAY_DATA_INDEX],
+ 'data-level': dataLevelNew
+ })
+ str2Obj.trs_fixed_r.eq(childIndex).attr({
+ 'data-index': childItem[LAY_DATA_INDEX],
+ 'lay-data-index': childItem[LAY_DATA_INDEX],
+ 'data-level': dataLevelNew
+ })
+ })
+
+ tableViewElem.find(ELEM_MAIN).find('tbody tr[lay-data-index="' + trIndex + '"]').after(str2Obj.trs);
+ tableViewElem.find(ELEM_FIXL).find('tbody tr[lay-data-index="' + trIndex + '"]').after(str2Obj.trs_fixed);
+ tableViewElem.find(ELEM_FIXR).find('tbody tr[lay-data-index="' + trIndex + '"]').after(str2Obj.trs_fixed_r);
+
+ // 初始化新增的节点中的内容
+ layui.each(str2Obj, function (key, item) {
+ treeTableThat.renderTreeTable(item, dataLevelNew);
+ })
+
+ if (sonSign && !isToggle) { // 非状态切换的情况下
+ // 级联展开/关闭子节点
+ layui.each(childNodes, function (i1, item1) {
+ expandNode({trElem: tableViewElem.find('tr[lay-data-index="' + item1.LAY_DATA_INDEX + '"]').first()}, expandFlag, sonSign, focus, callbackFlag);
+ })
+ }
+ }
+ }
+ } else {
+ trData[LAY_EXPAND] = trExpand;
+ // 折叠
+ if (sonSign && !isToggle) { // 非状态切换的情况下
+ layui.each(childNodes, function (i1, item1) {
+ expandNode({trElem: tableViewElem.find('tr[lay-data-index="' + item1.LAY_DATA_INDEX + '"]').first()}, expandFlag, sonSign, focus, callbackFlag);
+ });
+ tableViewElem.find(childNodes.map(function (value, index, array) { // 只隐藏直接子节点,其他由递归的处理
+ return 'tr[lay-data-index="' + value[LAY_DATA_INDEX] + '"]'
+ }).join(',')).addClass('layui-hide');
+ } else {
+ var childNodesFlat = treeTableThat.treeToFlat(childNodes, trData[treeOptions.data.simpleData.idKey], trIndex);
+ tableViewElem.find(childNodesFlat.map(function (value, index, array) {
+ return 'tr[lay-data-index="' + value[LAY_DATA_INDEX] + '"]'
+ }).join(',')).addClass('layui-hide');
+ }
+
+ }
+ table.resize(tableId);
+
+ if (callbackFlag && trData['LAY_ASYNC_STATUS'] !== 'loading') {
+ var onExpand = treeOptions.callback.onExpand;
+ layui.type(onExpand) === 'function' && onExpand(tableId, trData, expandFlag);
+ }
+
+ return retValue;
+ }
+
+ treeTable.expandNode = function (id, index, expandFlag, sonSign, callbackFlag) {
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ var tableViewElem = options.elem.next();
+ return expandNode({trElem: tableViewElem.find('tr[lay-data-index="' + index + '"]').first()}, expandFlag, sonSign, null, callbackFlag)
+ }
+
+ // 目前还有性能问题特别是在data模式需要优化暂时不能使用 todo
+ treeTable.expandAll = function (id, expandFlag) {
+ if (layui.type(expandFlag) !== 'boolean') {
+ return hint.error('expandAll的展开状态参数只接收true/false')
+ }
+ // 调用expandNode一个个去处理会有性能问题重新实现该方法
+ // layui.each(table.cache[id], function (i1, item1) {
+ // treeTable.expandNode(id, item1['LAY_DATA_INDEX'], expandFlag, true);
+ // })
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var tableView = options.elem.next();
+
+ if (!expandFlag) {
+ // 关闭所有
+ // 将所有已经打开的节点的状态设置为关闭,
+ that.updateStatus(null, {LAY_EXPAND: false}); // 只处理当前页,如果需要处理全部表格,需要用treeTable.updateStatus
+ // 隐藏所有非顶层的节点
+ tableView.find('tbody tr[data-level!="0"]').addClass('layui-hide');
+ // 处理顶层节点的图标
+ var trLevel0 = tableView.find('tbody tr[data-level="0"]');
+ trLevel0.find('.layui-table-tree-flexIcon').html(treeOptions.view.flexIconClose);
+ trLevel0.find('.layui-table-tree-nodeIcon').html(treeOptions.view.iconClose);
+
+ treeTable.resize();
+ } else {
+ console.log('目前暂时不支持展开全部');
+ return;
+ // 展开所有
+ if (treeOptions.async.enable) {
+ // 存在异步加载
+
+ } else {
+ // 先判断是否全部打开过了
+ var tableDataFlat = treeTable.getData(id, true);
+ var isAllExpanded = true;
+ layui.each(tableDataFlat, function (i1, item1) {
+ if (!item1[LAY_HAS_EXPANDED]) {
+ isAllExpanded = false;
+ return true;
+ }
+ })
+ // 如果全部节点已经都打开过,就可以简单处理跟隐藏所有节点反操作
+ if (isAllExpanded) {
+ that.updateStatus(null, {LAY_EXPAND: true}); // 只处理当前页,如果需要处理全部表格,需要用treeTable.updateStatus
+ // 隐藏所有非顶层的节点
+ tableView.find('tbody tr[data-level!="0"]').removeClass('layui-hide');
+ // 处理顶层节点的图标
+ // var trLevel0 = tableView.find('tbody tr[data-level="0"]');
+ tableView.find('.layui-table-tree-flexIcon').html(treeOptions.view.flexIconOpen);
+ tableView.find('.layui-table-tree-nodeIcon').html(treeOptions.view.iconOpen);
+
+ treeTable.resize();
+ } else {
+ // 如果有未打开过的父节点,将内容全部生成
+ that.updateStatus(null, {LAY_EXPAND: true, LAY_HAS_EXPANDED: true});
+ var trsAll = table.getTrHtml(id, tableDataFlat);
+
+ }
+
+ }
+
+
+ // 如果是异步加载子节点模式 如何处理
+ // 如果有部分节点未打开过,也需要重新
+ }
+
+ }
+
+ Class.prototype.renderTreeTable = function (tableView, level, sonSign) {
+ var that = this;
+ var options = that.getOptions();
+ var tableViewElem = options.elem.next();
+ tableViewElem.addClass('layui-table-tree');
+ var tableId = options.id;
+ var treeOptions = options.tree || {};
+ var treeOptionsData = treeOptions.data || {};
+ var treeOptionsView = treeOptions.view || {};
+ var isParentKey = treeOptionsData.key.isParent;
+ var tableFilterId = tableViewElem.attr('lay-filter');
+ var treeTableThat = that;
+ // var tableData = treeTableThat.getTableData();
+
+ level = level || 0;
+
+ if (!level) {
+ // 初始化的表格里面没有level信息,可以作为顶层节点的判断
+ tableViewElem.find('.layui-table-body tr:not([data-level])').attr('data-level', level);
+ layui.each(table.cache[tableId], function (dataIndex, dataItem) {
+ tableViewElem.find('.layui-table-main tbody tr[data-level="0"]:eq(' + dataIndex + ')').attr('lay-data-index', dataItem[LAY_DATA_INDEX]);
+ tableViewElem.find('.layui-table-fixed-l tbody tr[data-level="0"]:eq(' + dataIndex + ')').attr('lay-data-index', dataItem[LAY_DATA_INDEX]);
+ tableViewElem.find('.layui-table-fixed-r tbody tr[data-level="0"]:eq(' + dataIndex + ')').attr('lay-data-index', dataItem[LAY_DATA_INDEX]);
+ })
+ }
+
+ var dataExpand = {}; // 记录需要展开的数据
+ var nameKey = treeOptions.data.key.name;
+ var indent = treeOptions.view.indent || 14;
+ layui.each(tableView.find('td[data-field="' + nameKey + '"]'), function (index, item) {
+ item = $(item);
+ var trElem = item.closest('tr');
+ var itemCell = item.children('.layui-table-cell');
+ if (itemCell.hasClass('layui-table-tree-item')) {
+ return;
+ }
+ itemCell.addClass('layui-table-tree-item');
+ var trIndex = trElem.attr('lay-data-index');
+ if (!trIndex) { // 排除在统计行中的节点
+ return;
+ }
+ var trData = treeTableThat.getNodeDataByIndex(trIndex);
+ if (trData[LAY_EXPAND]) {
+ // 需要展开
+ dataExpand[trIndex] = true;
+ }
+
+ var tableCellElem = item.find('div.layui-table-cell');
+ var htmlTemp = tableCellElem.html();
+
+ var flexIconElem = item.find('div.layui-table-cell')
+ .html(['',
+ treeOptions.view.flexIconClose, // 折叠图标
+ '
',
+ '',
+ treeOptions.view.showIcon ? (trData.icon || treeOptions.view.icon || (trData[isParentKey] ? treeOptions.view.iconClose : treeOptions.view.iconLeaf) || '') : '',
+ '
', // 区分父子节点
+ htmlTemp].join('')) // 图标要可定制
+ .find('.layui-table-tree-flexIcon');
+
+ // 添加展开按钮的事件
+ flexIconElem.on('click', function (event) {
+ layui.stope(event);
+ // 处理数据
+ // var trElem = item.closest('tr');
+ expandNode({trElem}, null, null, null, true);
+ });
+ });
+
+ // 当前层的数据看看是否需要展开
+ sonSign !== false && layui.each(dataExpand, function (index, item) {
+ var trDefaultExpand = tableViewElem.find('tr[lay-data-index="' + index + '"]');
+ trDefaultExpand.find('.layui-table-tree-flexIcon').html(treeOptions.view.flexIconOpen);
+ expandNode({trElem: trDefaultExpand.first()}, true);
+ });
+
+ treeTable.formatNumber(tableId);
+ form.render(null, tableFilterId);
+ }
+
+
+ /**
+ * 重新编号
+ * @param {String} id 表格id
+ * @return {Object} layui.treeTable
+ * */
+ treeTable.formatNumber = function (id) {
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ var tableViewElem = options.elem.next();
+
+ var num = 0;
+ layui.each(that.treeToFlat(table.cache[id]), function (i1, item1) {
+ if (layui.isArray(item1)) {
+ return;
+ }
+ var itemData = that.getNodeDataByIndex(item1.LAY_DATA_INDEX);
+ itemData['LAY_NUM'] = ++num;
+ tableViewElem.find('tr[lay-data-index="' + item1.LAY_DATA_INDEX + '"] .laytable-cell-numbers').html(itemData['LAY_NUM']);
+ })
+ return treeTable;
+ }
+
+ // 树表渲染
+ Class.prototype.render = function (type) {
+ var that = this;
+ that.tableIns = table[type === 'reloadData' ? 'reloadData' : 'reload'](that.tableIns.config.id, $.extend(true, {}, that.config));
+ that.config = that.tableIns.config;
+ };
+
+ // 表格重载
+ Class.prototype.reload = function (options, deep, type) {
+ var that = this;
+
+ options = options || {};
+ delete that.haveInit;
+
+ // 防止数组深度合并
+ layui.each(options, function (key, item) {
+ if (layui.type(item) === 'array') delete that.config[key];
+ });
+
+ // 对参数进行深度或浅扩展
+ that.config = $.extend(deep, {}, that.config, options, {autoSort: false});
+
+ // 执行渲染
+ that.render(type);
+ };
+
+ // 仅重载数据
+ treeTable.reloadData = function () {
+ var args = $.extend(true, [], arguments);
+ args[3] = 'reloadData';
+
+ return treeTable.reload.apply(null, args);
+ };
+
+ var updateStatus = function (data, statusObj, childrenKey) {
+ var dataUpdated = [];
+ layui.each(data, function (i1, item1) {
+ if (layui.type(statusObj) === 'function') {
+ statusObj(item1);
+ } else {
+ $.extend(item1, statusObj);
+ }
+ dataUpdated.push($.extend({}, item1));
+ dataUpdated = dataUpdated.concat(updateStatus(item1[childrenKey], statusObj, childrenKey));
+ });
+ return dataUpdated;
+ }
+
+ Class.prototype.updateStatus = function (data, statusObj) {
+ var that = this;
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ data = data || table.cache[options.id];
+
+ return updateStatus(data, statusObj, treeOptions.data.key.children);
+ }
+
+ Class.prototype.getTableData = function () {
+ var that = this;
+ var options = that.getOptions();
+ return options.url ? table.cache[options.id] : options.data;
+ }
+
+ treeTable.updateStatus = function (id, statusObj, data) {
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ if (!data) {
+ if (options.url) {
+ data = table.cache[options.id];
+ } else {
+ data = options.data;
+ }
+ }
+ return that.updateStatus(data, statusObj);
+ }
+
+ treeTable.sort = function (id) {
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ var initSort = options.initSort;
+
+ if (!options.url) {
+ if (initSort.type) {
+ options.data = layui.sort(options.data, initSort.field, initSort.type === 'desc');
+ } else {
+ options.data = layui.sort(options.data, table.config.indexName);
+ }
+ that.initData(options.data);
+ treeTable.reloadData(id);
+ } else {
+ // url异步取数的表格一般需要自己添加监听之后进行reloadData并且把排序参数加入到where中
+ }
+ }
+
+ // 处理事件
+ var updateObjParams = function (obj) {
+ var tableId = obj.config.id;
+ var tableThat = getThisTable(tableId);
+ var trData = obj.data = treeTable.getNodeDataByIndex(tableId, obj.index); // 克隆的
+ var trIndex = trData[LAY_DATA_INDEX];
+ obj.dataIndex = trIndex;
+
+ // 处理update方法
+ var updateFn = obj.update;
+ obj.update = function () {
+ var updateThat = this;
+ var args = arguments;
+ $.extend(tableThat.getNodeDataByIndex(trIndex), args[0]);
+ var ret = updateFn.apply(updateThat, args); // 主要负责更新节点内容
+ tableThat.renderTreeTable(obj.tr, obj.tr.attr('data-level'), false);
+ return ret;
+ }
+
+ // 处理del方法
+ obj.del = function () {
+ treeTable.removeNode(tableId, trData);
+ }
+
+ // 处理setRowChecked
+ obj.setRowChecked = function (checked) {
+ treeTable.checkNode(tableId, trData, checked);
+ }
+ }
+
+ // 更新数据
+ treeTable.updateNode = function (id, index, newNode) {
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var tableView = options.elem.next();
+ var trElem = tableView.find('tr[lay-data-index="' + index + '"]');
+ var trIndex = trElem.attr('data-index');
+ var trLevel = trElem.attr('data-level')
+
+ if (!newNode) {
+ return;
+ }
+ // 更新值
+ var newNodeTemp = that.getNodeDataByIndex(index, false, newNode);
+ // 获取新的tr替换
+ var trNew = table.getTrHtml(id, [newNodeTemp]);
+ // 重新渲染tr
+ layui.each(['main', 'fixed-l', 'fixed-r'], function (i, item) {
+ tableView.find('.layui-table-' + item + ' tbody tr[lay-data-index="' + index + '"]').replaceWith($(trNew[['trs', 'trs_fixed', 'trs_fixed_r'][i]].join('')).attr({
+ 'data-index': trIndex,
+ 'lay-data-index': index,
+ }));
+ });
+ that.renderTreeTable(tableView.find('tr[lay-data-index="' + index + '"]'), trLevel);
+ }
+
+ // 删除数据
+ treeTable.removeNode = function (id, node) {
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var tableView = options.elem.next();
+ var delNode;
+ var indexArr = [];
+ delNode = that.getNodeDataByIndex(layui.type(node) === 'string' ? node : node[LAY_DATA_INDEX], false, 'delete');
+ var nodeP = that.getNodeDataByIndex(delNode[LAY_PARENT_INDEX]);
+ that.updateCheckStatus(nodeP, true);
+ var delNodesFlat = that.treeToFlat([delNode], delNode[treeOptions.data.simpleData.pIdKey], delNode[LAY_PARENT_INDEX]);
+ layui.each(delNodesFlat, function (i2, item2) {
+ indexArr.push('tr[lay-data-index="' + item2[LAY_DATA_INDEX] + '"]');
+ })
+
+ tableView.find(indexArr.join(',')).remove(); // 删除行
+ // 重新整理数据
+ var tableData = that.initData();
+ // index发生变化需要更新页面tr中对应的lay-data-index 新增和删除都要注意数据结构变动之后的index问题
+ layui.each(that.treeToFlat(tableData), function (i3, item3) {
+ if (item3[LAY_DATA_INDEX_HISTORY] && item3[LAY_DATA_INDEX_HISTORY] !== item3[LAY_DATA_INDEX]) {
+ tableView.find('tr[lay-data-index="' + item3[LAY_DATA_INDEX_HISTORY] + '"]').attr({
+ 'data-index': item3[LAY_DATA_INDEX],
+ 'lay-data-index': item3[LAY_DATA_INDEX],
+ });
+ // item3[LAY_DATA_INDEX_HISTORY] = item3[LAY_DATA_INDEX]
+ }
+ });
+ // 重新更新顶层节点的data-index;
+ layui.each(table.cache[id], function (i4, item4) {
+ tableView.find('tr[data-level="0"][lay-data-index="' + item4[LAY_DATA_INDEX] + '"]').attr('data-index', i4);
+ })
+ treeTable.formatNumber(id);
+ }
+
+ /**
+ * 新增数据节点
+ * @param {String} id 树表id
+ * @param {String|Number} parentIndex 指定的父节点,如果增加根节点,请设置 parentIndex 为 null 即可
+ * @param {Number} index:Number 新节点插入的位置(从 0 开始)index = -1(默认) 时,插入到最后
+ * @param {Object|Array} newNodes 新增的节点,单个或者多个
+ * @param {Boolean} focus 新增的节点,单个或者多个
+ * @return {Array} 新增的节点
+ * */
+ treeTable.addNodes = function (id, parentIndex, index, newNodes, focus) {
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var tableViewElem = options.elem.next();
+
+ parentIndex = layui.type(parentIndex) === 'number' ? parentIndex.toString() : parentIndex;
+ var parentNode = parentIndex ? that.getNodeDataByIndex(parentIndex) : null;
+ index = layui.type(index) === 'number' ? index : -1;
+
+ // 添加数据
+ newNodes = $.extend(true, [], (layui.isArray(newNodes) ? newNodes : [newNodes]));
+
+ var tableData = that.getTableData(), dataAfter;
+ if (!parentNode) {
+ // 添加到根节点
+ dataAfter = table.cache[id].splice(index === -1 ? table.cache[id].length : index);
+ table.cache[id] = table.cache[id].concat(newNodes, dataAfter);
+ if (!options.url) {
+ // 静态data模式
+ if (!options.page) {
+ options.data = table.cache[id];
+ } else {
+ var pageOptions = options.page;
+ options.data.splice.apply(options.data, [pageOptions.limit * (pageOptions.curr - 1), pageOptions.limit].concat(table.cache[id]))
+ }
+ }
+ // 将新节点添加到页面
+ tableData = that.initData();
+
+ var newNodesHtml = table.getTrHtml(id, newNodes);
+ var newNodesHtmlObj = {
+ trs: $(newNodesHtml.trs.join('')),
+ trs_fixed: $(newNodesHtml.trs_fixed.join('')),
+ trs_fixed_r: $(newNodesHtml.trs_fixed_r.join(''))
+ }
+
+ layui.each(newNodes, function (newNodeIndex, newNodeItem) {
+ newNodesHtmlObj.trs.eq(newNodeIndex).attr({
+ 'data-index': newNodeItem[LAY_DATA_INDEX],
+ 'lay-data-index': newNodeItem[LAY_DATA_INDEX],
+ 'data-level': '0'
+ })
+ newNodesHtmlObj.trs_fixed.eq(newNodeIndex).attr({
+ 'data-index': newNodeItem[LAY_DATA_INDEX],
+ 'lay-data-index': newNodeItem[LAY_DATA_INDEX],
+ 'data-level': '0'
+ })
+ newNodesHtmlObj.trs_fixed_r.eq(newNodeIndex).attr({
+ 'data-index': newNodeItem[LAY_DATA_INDEX],
+ 'lay-data-index': newNodeItem[LAY_DATA_INDEX],
+ 'data-level': '0'
+ })
+ })
+ var trIndexPrev = parseInt(newNodes[0][LAY_DATA_INDEX]) - 1;
+ var tableViewElemMAIN = tableViewElem.find(ELEM_MAIN);
+ var tableViewElemFIXL = tableViewElem.find(ELEM_FIXL);
+ var tableViewElemFIXR = tableViewElem.find(ELEM_FIXR);
+ if (trIndexPrev === -1) {
+ // 插入到开头
+ tableViewElemMAIN.find('tr[data-level="0"][data-index="0"]').before(newNodesHtmlObj.trs);
+ tableViewElemFIXL.find('tr[data-level="0"][data-index="0"]').before(newNodesHtmlObj.trs_fixed);
+ tableViewElemFIXR.find('tr[data-level="0"][data-index="0"]').before(newNodesHtmlObj.trs_fixed_r);
+ } else {
+ if (index === -1) {
+ // 追加到最后
+ tableViewElemMAIN.find('tbody').append(newNodesHtmlObj.trs);
+ tableViewElemFIXL.find('tbody').append(newNodesHtmlObj.trs_fixed);
+ tableViewElemFIXR.find('tbody').append(newNodesHtmlObj.trs_fixed_r);
+ } else {
+ var trIndexNext = dataAfter[0][LAY_DATA_INDEX_HISTORY];
+ tableViewElemMAIN.find('tr[data-level="0"][data-index="' + trIndexNext + '"]').before(newNodesHtmlObj.trs);
+ tableViewElemFIXL.find('tr[data-level="0"][data-index="' + trIndexNext + '"]').before(newNodesHtmlObj.trs_fixed);
+ tableViewElemFIXR.find('tr[data-level="0"][data-index="' + trIndexNext + '"]').before(newNodesHtmlObj.trs_fixed_r);
+ }
+
+ }
+
+ // 重新更新顶层节点的data-index;
+ layui.each(table.cache[id], function (i4, item4) {
+ tableViewElem.find('tr[data-level="0"][lay-data-index="' + item4[LAY_DATA_INDEX] + '"]').attr('data-index', i4);
+ })
+
+ that.renderTreeTable(tableViewElem.find(newNodes.map(function (value, index, array) {
+ return 'tr[lay-data-index="' + value[LAY_DATA_INDEX] + '"]'
+ }).join(',')));
+ } else {
+ var isParentKey = treeOptions.data.key.isParent;
+ var childKey = treeOptions.data.key.children;
+
+ parentNode[isParentKey] = true;
+ var childrenNodes = parentNode[childKey];
+ if (!childrenNodes) {
+ childrenNodes = parentNode[childKey] = newNodes;
+ } else {
+ dataAfter = childrenNodes.splice(index === -1 ? childrenNodes.length : index);
+ childrenNodes = parentNode[childKey] = childrenNodes.concat(newNodes, dataAfter);
+ }
+ // 删除已经存在的同级节点以及他们的子节点,并且把中间节点的已展开过的状态设置为false
+ that.updateStatus(childrenNodes, function (d) {
+ if (d[isParentKey]) {
+ d[LAY_HAS_EXPANDED] = false;
+ }
+ });
+ var childrenNodesFlat = that.treeToFlat(childrenNodes);
+ tableViewElem.find(childrenNodesFlat.map(function (value) {
+ return 'tr[lay-data-index="' + value[LAY_DATA_INDEX] + '"]'
+ }).join(',')).remove();
+
+ tableData = that.initData();
+ // 去掉父节点的已经展开过的状态,重新执行一次展开的方法
+ parentNode[LAY_HAS_EXPANDED] = false;
+ parentNode['LAY_ASYNC_STATUS'] = 'local'; // 转为本地数据,应该规定异步加载子节点的时候addNodes的规则
+ expandNode({trElem: tableViewElem.find('tr[lay-data-index="' + parentIndex + '"]')}, true)
+ }
+ that.updateCheckStatus(parentNode, true);
+ treeTable.resize(id);
+ if (focus) {
+ // 滚动到第一个新增的节点
+ tableViewElem.find(ELEM_MAIN).find('tr[lay-data-index="' + newNodes[0][LAY_DATA_INDEX] + '"]').get(0).scrollIntoViewIfNeeded();
+ }
+ return newNodes;
+ }
+
+ treeTable.checkStatus = function (id) {
+ var that = getThisTable(id);
+
+ // 需要区分单双选
+ var tableData = treeTable.getData(id, true);
+ var checkedData = tableData.filter(function (value, index, array) {
+ return value[table.config.checkName];
+ });
+
+ var isAll = true;
+ layui.each(table.cache[id], function (i1, item1) {
+ if (!item1[table.config.checkName]) {
+ isAll = false;
+ return true;
+ }
+ })
+
+ return {
+ data: checkedData,
+ isAll: isAll
+ }
+ }
+
+ // 排序之后重新渲染成树表
+ treeTable.on('sort', function (obj) {
+ var options = obj.config;
+ var tableView = options.elem.next();
+ var tableId = options.id;
+
+ if (tableView.hasClass('layui-table-tree')) {
+ treeTable.sort(tableId);
+ }
+ });
+
+ // 行点击
+ treeTable.on('row', function (obj) {
+ var options = obj.config;
+ var tableView = options.elem.next();
+
+ if (tableView.hasClass('layui-table-tree')) {
+ updateObjParams(obj);
+ }
+ })
+
+ // 行双击
+ treeTable.on('rowDouble', function (obj) {
+ var options = obj.config;
+ var tableView = options.elem.next();
+ var tableId = options.id;
+
+ if (tableView.hasClass('layui-table-tree')) {
+ updateObjParams(obj);
+
+ var treeOptions = options.tree || {};
+ if (treeOptions.view.dblClickExpand) {
+ expandNode({trElem: obj.tr.first()}, null, null, null, true);
+ }
+ }
+ })
+
+ // tr中带lay-event节点点击
+ treeTable.on('tool', function (obj) {
+ var options = obj.config;
+ var tableView = options.elem.next();
+ var tableId = options.id;
+
+ if (tableView.hasClass('layui-table-tree')) {
+ updateObjParams(obj);
+ }
+ })
+
+ // 行内编辑
+ treeTable.on('edit', function (obj) {
+ // 如果编辑涉及到关键的name字段需要重新更新一下tr节点
+ var options = obj.config;
+ var tableView = options.elem.next();
+ var tableId = options.id;
+
+ if (tableView.hasClass('layui-table-tree')) {
+ updateObjParams(obj);
+ if (obj.field === options.tree.data.key.name) {
+ obj.tr.find('td[data-field="' + obj.field + '"]').children('div.layui-table-cell').removeClass('layui-table-tree-item')
+ obj.update({}); // 通过update调用执行tr节点的更新
+ }
+ }
+ });
+
+ // 单选
+ treeTable.on('radio', function (obj) {
+ var options = obj.config;
+ var tableView = options.elem.next();
+ var tableId = options.id;
+ var that = getThisTable(tableId);
+
+ if (tableView.hasClass('layui-table-tree')) {
+ updateObjParams(obj);
+ checkNode.call(that, obj.tr, obj.checked)
+ }
+ })
+
+ // 更新表格的复选框状态
+ Class.prototype.updateCheckStatus = function (dataP, checked) {
+ var that = this;
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var tableId = options.id;
+ var tableView = options.elem.next();
+
+ var checkName = table.config.checkName;
+
+ // 如有必要更新父节点们的状态
+ if (dataP) {
+ var trsP = that.updateParentCheckStatus(dataP, checked);
+ layui.each(trsP, function (indexP, itemP) {
+ form.render(tableView.find('tr[lay-data-index="' + itemP[LAY_DATA_INDEX] + '"] input[name="layTableCheckbox"]:not(:disabled)').prop({
+ checked: itemP[checkName],
+ indeterminate: itemP[LAY_CHECKBOX_HALF]
+ }))
+ })
+ }
+
+ // 更新全选的状态
+ var isAll = true;
+ var isIndeterminate = false;
+ layui.each(table.cache[tableId], function (i1, item1) {
+ if (item1[checkName] || item1[LAY_CHECKBOX_HALF]) {
+ isIndeterminate = true;
+ }
+ if (!item1[checkName]) {
+ isAll = false;
+ }
+ })
+ isIndeterminate = isIndeterminate && !isAll;
+ form.render(tableView.find('input[name="layTableCheckbox"][lay-filter="layTableAllChoose"]').prop({
+ 'checked': isAll,
+ indeterminate: isIndeterminate
+ }));
+
+ return isAll
+ }
+
+ // 更新父节点的选中状态
+ Class.prototype.updateParentCheckStatus = function (dataP, checked) {
+ var that = this;
+ var options = that.getOptions();
+ var treeOptions = options.tree;
+ var tableId = options.id;
+ var checkName = table.config.checkName;
+ var childrenKey = treeOptions.data.key.children;
+
+ var dataRet = [];
+ dataP[LAY_CHECKBOX_HALF] = false; // 先设置为非半选,是否为半选又下面逻辑判断
+ if (checked) {
+ // 为真需要判断子节点的情况
+ if (!dataP[childrenKey].length) {
+ checked = false;
+ } else {
+ layui.each(dataP[childrenKey], function (index, item) {
+ if (!item[checkName]) { // 只要有一个子节点为false
+ checked = false;
+ dataP[LAY_CHECKBOX_HALF] = true;
+ return true; // 跳出循环
+ }
+ });
+ }
+ } else {
+ // 判断是否为半选
+ layui.each(dataP[childrenKey], function (index, item) {
+ if (item[checkName] || item[LAY_CHECKBOX_HALF]) { // 只要有一个子节点为选中或者半选状态
+ dataP[LAY_CHECKBOX_HALF] = true;
+ return true;
+ }
+ });
+ }
+ dataP[checkName] = checked;
+ dataRet.push($.extend({}, dataP));
+ if (dataP[LAY_PARENT_INDEX]) {
+ dataRet = dataRet.concat(that.updateParentCheckStatus(table.cache[tableId][dataP[LAY_PARENT_INDEX]], checked));
+ }
+ return dataRet
+ }
+
+ var checkNode = function (trElem, checked, callbackFlag) {
+ var that = this;
+ var options = that.getOptions();
+ var tableId = options.id;
+ var tableView = options.elem.next();
+ var inputElem = (trElem.length ? trElem : tableView).find('.laytable-cell-radio, .laytable-cell-checkbox').children('input').last();
+ // 判断是单选还是多选 不应该同时存在radio列和checkbox列
+ var isRadio = inputElem.attr('type') === 'radio';
+
+ if (callbackFlag) {
+ var triggerEvent = function () {
+ var fn = function (event) {
+ layui.stope(event);
+ }
+ inputElem.parent().on('click', fn); // 添加临时的阻止冒泡事件
+ inputElem.next().click();
+ inputElem.parent().off('click', fn);
+ }
+ // 如果需要触发事件可以简单的触发对应节点的click事件
+ if (isRadio) {
+ // 单选只能选中或者切换其他的不能取消选中 后续看是否有支持的必要 todo
+ if (checked && !inputElem.prop('checked')) {
+ triggerEvent()
+ }
+ } else {
+ if (layui.type(checked) === 'boolean') {
+ if (inputElem.prop('checked') !== checked) {
+ // 如果当前已经是想要修改的状态则不做处理
+ triggerEvent()
+ }
+ } else {
+ // 切换
+ triggerEvent()
+ }
+ }
+ } else {
+ var trData = that.getNodeDataByIndex(trElem.attr('data-index'));
+ var checkName = table.config.checkName;
+ // 如果不触发事件应该有一个方法可以更新数据以及页面的节点
+ if (isRadio) {
+ if (!trData) {
+ // 单选必须是一个存在的行
+ return;
+ }
+ var statusChecked = {};
+ statusChecked[checkName] = false;
+ // that.updateStatus(null, statusChecked); // 取消其他的选中状态
+ that.updateStatus(null, function (d) {
+ if (d[checkName]) {
+ d[checkName] = false;
+ form.render(tableView.find('tr[lay-data-index="' + d[LAY_DATA_INDEX] + '"] input[type="radio"][lay-type="layTableRadio"]').prop('checked', false));
+ }
+ }); // 取消其他的选中状态
+ trData[checkName] = checked;
+ form.render(trElem.find('input[type="radio"][lay-type="layTableRadio"]').prop('checked', checked));
+ } else {
+ var isParentKey = options.tree.data.key.isParent;
+ // 切换只能用到单条,全选到这一步的时候应该是一个确定的状态
+ checked = layui.type(checked) === 'boolean' ? checked : !trData[checkName]; // 状态切换,如果遇到不可操作的节点待处理 todo
+ // 全选或者是一个父节点,将子节点的状态同步为当前节点的状态
+ // if (!trData || trData[isParentKey]) {
+ // 处理不可操作的信息
+ var checkedStatusFn = function (d) {
+ if (!d[table.config.disabledName]) { // 节点不可操作的不处理
+ d[checkName] = checked;
+ d[LAY_CHECKBOX_HALF] = false;
+ }
+ }
+
+ var trs = that.updateStatus(trData ? [trData] : table.cache[tableId], checkedStatusFn);
+ form.render(tableView.find(trs.map(function (value) {
+ return 'tr[lay-data-index="' + value[LAY_DATA_INDEX] + '"] input[name="layTableCheckbox"]:not(:disabled)';
+ }).join(',')).prop({checked: checked, indeterminate: false}));
+ // }
+ var trDataP;
+ // 更新父节点以及更上层节点的状态
+ if (trData && trData[LAY_PARENT_INDEX]) {
+ // 找到父节点,然后判断父节点的子节点是否全部选中
+ trDataP = that.getNodeDataByIndex(trData[LAY_PARENT_INDEX]);
+ }
+
+ return that.updateCheckStatus(trDataP, checked);
+ }
+ }
+ }
+
+ // 多选
+ treeTable.on('checkbox', function (obj) {
+ var options = obj.config;
+ var tableView = options.elem.next();
+ var tableId = options.id;
+ var that = getThisTable(tableId);
+
+ if (tableView.hasClass('layui-table-tree')) {
+ updateObjParams(obj);
+ var checked = obj.checked;
+ obj.isAll = checkNode.call(that, obj.tr, checked);
+ }
+ })
+
+
+ /**
+ * 勾选或取消勾选单个节点
+ * @param {String} id 树表id
+ * @param {Object|String} node 节点
+ * @param {Boolean} checked 选中或取消
+ * @param {Boolean} [callbackFlag] 是否触发事件回调
+ * */
+ treeTable.checkNode = function (id, node, checked, callbackFlag) {
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ var tableView = options.elem.next();
+
+ var dataIndex = layui.type(node) === 'string' ? node : node[LAY_DATA_INDEX];
+ // 判断是否在当前页面中
+ var nodeData = that.getNodeDataByIndex(dataIndex);
+ if (!nodeData) {
+ // 目前只能处理当前页的数据
+ return;
+ }
+ // 判断是否展开过
+ var trElem = tableView.find('tr[lay-data-index="' + dataIndex + '"]');
+ if (!trElem.length) {
+ // 如果还没有展开没有渲染的要先渲染出来
+ treeTable.expandNode(id, nodeData[LAY_PARENT_INDEX], true);
+ trElem = tableView.find('tr[lay-data-index="' + dataIndex + '"]');
+ }
+ checkNode.call(that, trElem, checked, callbackFlag);
+ }
+
+ treeTable.checkAllNodes = function (id, checked) {
+ var that = getThisTable(id);
+ var options = that.getOptions();
+ var tableView = options.elem.next();
+
+ checkNode.call(that, tableView.find('tr[data-index="NONE"]'), !!checked)
+ }
+
+ /**
+ * 获得数据
+ * @param {String} id 表格id
+ * @param {Boolean} simpleData 是否返回平铺结构的数据
+ * @return {Array} 表格数据
+ * */
+ treeTable.getData = function (id, simpleData) {
+ var tableData = [];
+ layui.each($.extend(true, [], table.cache[id] || []), function (index, item) {
+ // 遍历排除掉临时的数据
+ tableData.push(item);
+ })
+ return simpleData ? getThisTable(id).treeToFlat(tableData) : tableData;
+ }
+
+ //记录所有实例
+ thisTreeTable.that = {}; //记录所有实例对象
+ // thisTreeTable.config = {}; //记录所有实例配置项
+
+ // 重载
+ treeTable.reload = function (id, options, deep, type) {
+ deep = deep !== false; // 默认采用深拷贝
+ var config = getThisTableConfig(id); //获取当前实例配置项
+ if (!config) return;
+
+ var that = getThisTable(id);
+ that.reload(options, deep, type);
+
+ return thisTreeTable.call(that);
+ };
+
+ // 核心入口
+ treeTable.render = function (options) {
+ var inst = new Class(options);
+ return thisTreeTable.call(inst);
+ };
+
+ exports(MOD_NAME, treeTable);
+});