123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540 |
- /**
- *
- * @name: 子表格扩展
- * @author: yelog
- * @version: v1.4.4
- */
- layui.define(['table' ,'element', 'form', 'laytpl'], function (exports) {
- var $ = layui.jquery,
- table = layui.table,
- laytpl = layui.laytpl,
- tableChildren={},
- ELEM_HOVER='soul-table-hover';
- // 封装方法
- var mod = {
- /**
- * 渲染入口
- * @param myTable
- */
- render: function (myTable) {
- var _this = this,
- $table = $(myTable.elem),
- $tableBox = $table.next().children('.layui-table-box'),
- tableId = myTable.id,
- $tableHead = $tableBox.children('.layui-table-header').children('table'),
- $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'),
- $noFixedBody = $tableBox.children('.layui-table-body').children('table'),
- $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody),
- columns = _this.getCompleteCols(myTable.cols),
- childIndex = [],
- soulSort = typeof myTable.soulSort === 'undefined' || myTable.soulSort,
- i;
- // 修复hover样式
- _this.fixHoverStyle(myTable)
- // 获取子表配置信息
- for (i=0;i<columns.length;i++) {
- if (columns[i].children && columns[i].children.length>0) {
- childIndex.push(i);
- }
- }
- if (typeof $table.attr('lay-filter') === 'undefined') {
- $table.attr('lay-filter', tableId);
- }
- // 绑定一下主表事件
- if ($table.parents('.childTr').length === 0) {
- if (typeof myTable.rowEvent === 'function') {
- table.on('row('+$table.attr('lay-filter')+')', function (obj) {
- var index = $(this).data('index');
- obj.tr = $tableBody.children('tbody').children('tr[data-index="'+index+'"]');
- myTable.rowEvent(obj);
- })
- }
- if (typeof myTable.rowDoubleEvent === 'function') {
- table.on('rowDouble('+$table.attr('lay-filter')+')', function (obj) {
- var index = $(this).data('index');
- obj.tr = $tableBody.children('tbody').children('tr[data-index="'+index+'"]');
- myTable.rowDoubleEvent(obj);
- })
- }
- }
- if (childIndex.length>0) {
- for ( i = 0; i < childIndex.length; i++) {
- (function f() {
- var child = columns[childIndex[i]]
- ,curIndex = childIndex[i]
- ,icon = child.icon || ['layui-icon layui-icon-right', 'layui-icon layui-icon-down'];
- if (soulSort && !(myTable.url && myTable.page)) {
- // 前台排序
- table.on('sort(' + $table.attr('lay-filter') + ')', function () {
- _this.render(myTable)
- });
- }
- if (child.isChild && typeof child.isChild === 'function') {
- $tableBody.find('tr').find('td[data-key$="'+child.key+'"]>div').each(function (index) {
- if (child.isChild(layui.table.cache[tableId][index])) {
- if (child.field) {
- $(this).prepend('<i style="cursor: pointer" class="childTable '+icon[0]+'"></i>');
- } else {
- $(this).html('<i style="cursor: pointer" class="childTable '+icon[0]+'"></i>');
- }
- }
- })
- } else {
- if (child.field) {
- $tableBody.find('tr').find('td[data-key$="'+child.key+'"]>div').prepend('<i style="cursor: pointer" class="childTable '+icon[0]+'"></i>');
- } else {
- $tableBody.find('tr').find('td[data-key$="'+child.key+'"]>div').html('<i style="cursor: pointer" class="childTable '+icon[0]+'"></i>');
- }
- }
- $tableBody.children('tbody').children('tr').each(function () {
- $(this).children('td:eq('+curIndex+')').find('.childTable').on('click', function (e) {
- layui.stope(e)
- var rowIndex = $(this).parents('tr:eq(0)').data('index'),
- key = $(this).parents('td:eq(0)').data('key'),
- $this = $noFixedBody.children('tbody').children('tr[data-index=' + rowIndex + ']').children('td[data-key="'+key+'"]').find('.childTable:eq(0)'),
- $fixedThis = $fixedBody.find('tr[data-index=' + rowIndex + ']').children('td[data-key="'+key+'"]').find('.childTable:eq(0)'),
- data = table.cache[myTable.id][rowIndex],
- children = child.children;
- if (typeof child.children === 'function') {
- children = child.children(data)
- }
- if (child.show === 2) { // 弹窗模式
- layer.open($.extend({type: 1, title: '子表', maxmin: true ,content: _this.getTables(this, data, child, myTable, children), area: '1000px', offset: '100px'}, child.layerOption || {}));
- _this.renderTable(this, data, child, myTable, children, icon);
- } else { // 展开模式
- // 开启手风琴模式
- if (!$this.hasClass(icon[1]) && child.collapse) {
- $tableBody.children('tbody').children('tr').children('td').find('.childTable').each(function () {
- if ($(this).hasClass(icon[1])) {
- _this.destroyChildren($(this).parents('tr:eq(0)').data('index'), myTable, icon)
- }
- })
- }
- // 多个入口时,关闭其他入口
- if (!$this.hasClass(icon[1])) {
- $this.parents('tr:eq(0)').children('td').find('.childTable').each(function () {
- if ($(this).hasClass(icon[1])) {
- $(this).removeClass(icon[1]).addClass(icon[0])
- _this.destroyChildren($(this).parents('tr:eq(0)').data('index'), myTable, icon)
- }
- })
- }
- if ($this.hasClass(icon[1])) {
- $this.removeClass(icon[1]).addClass(icon[0])
- $fixedThis.removeClass(icon[1]).addClass(icon[0])
- } else {
- $this.removeClass(icon[0]).addClass(icon[1])
- $fixedThis.removeClass(icon[0]).addClass(icon[1])
- }
- var rowspanIndex=$this.parents('td:eq(0)').attr("rowspan");
- if ($this.hasClass(icon[1])) {
- var newTr = [];
- newTr.push('<tr class="noHover childTr"><td colspan="'+$tableHead.find('th:visible').length+'" style="cursor: inherit; padding: 0; width: '+$this.parents('tr:eq(0)').width()+'px">');
- newTr.push(_this.getTables(this, data, child, myTable, children));
- newTr.push('</td></tr>');
- if(rowspanIndex){
- var index=parseInt($this.parents('tr:eq(0)').data("index"))+parseInt(rowspanIndex)-1;
- $this.parents('table:eq(0)').children().children("[data-index='"+index+"']").after(newTr.join(''));
- }else{
- $this.parents('tr:eq(0)').after(newTr.join(''));
- }
- _this.renderTable(this, data, child, myTable, children, icon);
- if ($fixedBody.length>0) {
- var $tr = $this.parents('tr:eq(0)').next(),
- height = $tr.children('td').height(),
- $patchDiv = '<div class="soul-table-child-patch" style="height: '+height+'px"></div>';
- $tr.children('td').children('.layui-tab-card').css({
- position: 'absolute',
- top: 0,
- width: '100%',
- background: 'white',
- 'z-index': 200
- })
- $tr.children('td').append($patchDiv);
- $fixedBody.find('tr[data-index="'+rowIndex+'"]').each(function () {
- $(this).after('<tr><td style="padding: 0;" colspan="'+$(this).children('[data-key]').length+'">'+$patchDiv+'</td></tr>')
- })
- table.resize(tableId)
- }
- if (child.show === 3) {
- $this.parents('tr:eq(0)').next().find('.layui-table-view').css({margin:0, 'border-width':0});
- $this.parents('tr:eq(0)').next().find('.layui-table-header').css('display', 'none');
- }
- // 阻止事件冒泡
- $this.parents('tr:eq(0)').next().children('td').children('.layui-tab').children('.layui-tab-content').on('click', function (e) {
- e.stopPropagation()
- }).off('dblclick').on('dblclick', function (e) {
- e.stopPropagation()
- }).on('mouseenter', 'td', function (e) {
- e.stopPropagation()
- })
- } else {
- _this.destroyChildren(rowIndex, myTable, icon);
- table.resize(tableId)
- }
- }
- })
- })
- if (child.spread && child.show !== 2) {
- $tableBody.children('tbody').children('tr').children('td').find('.childTable').trigger('click');
- }
- })()
- }
- }
- },
- /**
- * 生成子表内容
- * @param _this
- * @param data
- * @param child
- * @param myTable
- * @param children 子表配置
- * @returns {string}
- */
- getTables: function (_this, data, child, myTable, children) {
- var tables = [],
- $table = $(myTable.elem),
- tableId = myTable.id,
- rowTableId = tableId + $(_this).parents('tr:eq(0)').data('index'),
- $tableMain = $table.next().children('.layui-table-box').children('.layui-table-body'),
- $tableBody = $tableMain.children('table'),
- scrollWidth = 0,
- i;
- tables.push('<div class="layui-tab layui-tab-card" lay-filter="table-child-'+rowTableId+'" style="margin: 0;border: 0;box-shadow: none;');
- if (child.show === 2) {
- tables.push('max-width: '+ ($tableBody.width()-2) +'px">')
- } else if (child.show === 3) {
- //不限制宽度
- tables.push('">')
- } else {
- if (child.childWidth === 'full') {
- //不限制宽度
- tables.push('">')
- } else {
- if ($tableMain.prop('scrollHeight') + (children.length>0?children[0].height:0) > $tableMain.height()) {
- scrollWidth = this.getScrollWidth();
- }
- tables.push('max-width: '+ ($tableMain.width() - 1 - scrollWidth) +'px">')
- }
- }
- if (child.show !== 3 && (typeof child.childTitle === 'undefined' || child.childTitle)) {
- tables.push('<ul class="layui-tab-title">')
- for (i=0;i<children.length;i++) {
- tables.push('<li class="'+(i===0?'layui-this':'')+'">'+(typeof children[i].title === 'function' ? children[i].title(data) :children[i].title)+'</li>');
- }
- tables.push('</ul>')
- }
- if (child.show === 3) {
- tables.push('<div class="layui-tab-content" style="padding: 0">');
- } else {
- tables.push('<div class="layui-tab-content" style="padding: 0 10px">');
- }
- for (i=0;i<children.length;i++) {
- var childTableId = rowTableId + i;
- tables.push('<div class="layui-tab-item layui-show"><form action="" class="layui-form" ><table id="'+childTableId+'" lay-filter="'+childTableId+'"></table></form></div>');
- }
- tables.push('</div></div>');
- return tables.join('')
- },
- /**
- * 渲染子表
- * @param _this
- * @param data 父表当前行数据
- * @param child 子表列
- * @param myTable 父表配置
- * @param children 子表配置
- */
- renderTable: function (_this, data, child, myTable, children, icon) {
- var tables = []
- ,_that = this
- ,tableId = myTable.id
- ,rowTableId = tableId + $(_this).parents('tr:eq(0)').data('index');
- if (child.lazy) {
- tables.push(renderChildTable(_that, _this, data, child, myTable, 0, children, icon));
- } else {
- for (var i=0; i<children.length; i++) {
- tables.push(renderChildTable(_that, _this, data, child, myTable, i, children, icon));
- }
- }
- tableChildren[rowTableId]=tables;
- layui.element.on('tab(table-child-'+rowTableId+')', function(tabData){
- if (child.lazy) {
- var isRender = false; // 是否已经渲染
- for(i=0; i<tableChildren[rowTableId].length; i++) {
- if (tableChildren[rowTableId][i].config.id === (rowTableId + tabData.index)) {
- isRender = true;
- break;
- }
- }
- if (!isRender) {
- tableChildren[rowTableId].push(renderChildTable(_that, _this, data, child, myTable, tabData.index, children))
- }
- }
- var rowIndex = $(_this).parents('tr:eq(0)').data('index'),
- height = $(tabData.elem).height();
- $(_this).parents('.layui-table-box:eq(0)').children('.layui-table-body').children('table').children('tbody').children('tr[data-index=' + rowIndex + ']').next().children().children('.soul-table-child-patch').css('height', height)
- $(_this).parents('.layui-table-box:eq(0)').children('.layui-table-fixed').children('.layui-table-body').children('table').children('tbody').children('tr[data-index=' + rowIndex + ']').next().children().children('.soul-table-child-patch').css('height', height)
- table.resize(tableId)
- });
- function renderChildTable(_that, _this, data, child, myTable, i, children, icon) {
- var param = _that.deepClone(children[i]), thisTableChild,
- tableId = myTable.id,
- rowIndex = $(_this).parents('tr:eq(0)').data('index'),
- childTableId = tableId + rowIndex + i,
- $table = $(myTable.elem),
- $tableBox = $table.next().children('.layui-table-box'),
- $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table')),
- tr = $tableBody.children('tbody').children('tr[data-index="'+rowIndex+'"]'),
- row = table.cache[tableId][rowIndex],
- // 父表当前行对象
- pobj = {
- data: row,
- tr: tr,
- del: function() {
- table.cache[tableId][rowIndex] = [];
- _that.destroyChildren(rowIndex, myTable, icon)
- tr.remove();
- table.resize(tableId);
- },
- update: function(fields) {
- fields = fields || {};
- layui.each(fields, function(key, value){
- if(key in row){
- var templet, td = tr.children('td[data-field="'+ key +'"]');
- row[key] = value;
- table.eachCols(tableId, function(i, item2){
- if(item2.field == key && item2.templet){
- templet = item2.templet;
- }
- });
- td.children('.layui-table-cell').html(function(){
- return templet ? function(){
- return typeof templet === 'function'
- ? templet(row)
- : laytpl($(templet).html() || value).render(row)
- }() : value;
- }());
- td.data('content', value);
- }
- });
- },
- close: function () {
- _that.destroyChildren(rowIndex, myTable, icon)
- table.resize(tableId);
- }
- };
- param.id = childTableId;
- param.elem = '#'+childTableId;
- typeof param.where === 'function' && (param.where = param.where(data));
- typeof param.data === 'function' && (param.data = param.data(data));
- typeof param.url === 'function' && (param.url = param.url(data));
- thisTableChild = table.render(param);
- if (!child.lazy && i!==0) {
- $('#'+childTableId).parents('.layui-tab-item:eq(0)').removeClass('layui-show'); //解决隐藏时计算表格高度有问题
- }
- // 绑定 checkbox 事件
- if (typeof param.checkboxEvent === 'function') {
- table.on('checkbox('+childTableId+')', function (obj) {
- param.checkboxEvent(obj, pobj)
- })
- }
- // 绑定 edit 事件
- if (typeof param.editEvent === 'function') {
- table.on('edit('+childTableId+')', function (obj) {
- obj.oldValue = $(this).prev().text();
- param.editEvent(obj, pobj)
- })
- }
- // 绑定 tool 事件
- if (typeof param.toolEvent === 'function') {
- table.on('tool('+childTableId+')', function (obj) {
- param.toolEvent(obj, pobj)
- })
- }
- // 绑定 toolbar 事件
- if (typeof param.toolbarEvent === 'function') {
- table.on('toolbar('+childTableId+')', function (obj) {
- param.toolbarEvent(obj, pobj)
- })
- }
- // 绑定单击行事件
- if (typeof param.rowEvent === 'function') {
- table.on('row('+childTableId+')', function (obj) {
- param.rowEvent(obj, pobj)
- })
- }
- // 绑定双击行事件
- if (typeof param.rowDoubleEvent === 'function') {
- table.on('rowDouble('+childTableId+')', function (obj) {
- param.rowDoubleEvent(obj, pobj)
- })
- }
- return thisTableChild;
- }
- },
- destroyChildren: function (rowIndex, myTable, icon) {
- var tableId = myTable.id,
- $table = $(myTable.elem),
- $tableBox = $table.next().children('.layui-table-box'),
- $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'),
- $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody),
- $tr = $tableBody.children('tbody').children('tr[data-index="'+rowIndex+'"]');
- $tr.find('.childTable').removeClass(icon[1]).addClass(icon[0]);
- // 暂时不处理 rowspan 情况
- // var rowspanIndex = $this.parents('td:eq(0)').attr("rowspan");
- // if(rowspanIndex){
- // var index=$this.parents('tr:eq(0)').index()+parseInt(rowspanIndex);
- // $this.parents('table:eq(0)').children().children('tr:eq('+index+')').remove()
- // }else{
- // $this.parents('tr:eq(0)').next().remove();
- // }
- $tr.next().remove()
- var tables = tableChildren[tableId + rowIndex];
- if (layui.tableFilter) { //如果使用了筛选功能,怎同时清理筛选渲染的数据
- layui.tableFilter.destroy(tables);
- }
- delete tableChildren[tableId + rowIndex]
- },
- cloneJSON: function (obj) {
- var JSON_SERIALIZE_FIX = {
- PREFIX : "[[JSON_FUN_PREFIX_",
- SUFFIX : "_JSON_FUN_SUFFIX]]"
- };
- var sobj = JSON.stringify(obj,function(key, value){
- if(typeof value === 'function'){
- return JSON_SERIALIZE_FIX.PREFIX+value.toString()+JSON_SERIALIZE_FIX.SUFFIX;
- }
- return value;
- });
- return JSON.parse(sobj,function(key, value){
- if(typeof value === 'string' &&
- value.indexOf(JSON_SERIALIZE_FIX.SUFFIX)>0 && value.indexOf(JSON_SERIALIZE_FIX.PREFIX)===0){
- return eval("("+value.replace(JSON_SERIALIZE_FIX.PREFIX,"").replace(JSON_SERIALIZE_FIX.SUFFIX,"")+")");
- }
- return value;
- })||{};
- },
- fixHoverStyle: function(myTable) {
- var $table = $(myTable.elem)
- ,$tableBody = $table.next().children('.layui-table-box').children('.layui-table-body').children('table')
- ,$tableFixed = $table.next().children('.layui-table-box').children('.layui-table-fixed').children('.layui-table-body').children('table')
- ,style = $table.next().find('style')[0],
- sheet = style.sheet || style.styleSheet || {};
- // 屏蔽掉layui原生 hover 样式
- this.addCSSRule(sheet, '.layui-table-hover', 'background-color: inherit');
- this.addCSSRule(sheet, '.layui-table-hover.soul-table-hover', 'background-color: #F2F2F2');
- $.merge($tableFixed.children('tbody').children('tr'), $tableBody.children('tbody').children('tr'))
- .on('mouseenter', function () {
- var othis = $(this)
- ,index = $(this).data('index');
- if(othis.data('off')) return;
- $tableFixed.children('tbody').children('tr[data-index='+index+']').addClass(ELEM_HOVER);
- $tableBody.children('tbody').children('tr[data-index='+index+']').addClass(ELEM_HOVER);
- }).on('mouseleave', function () {
- var othis = $(this)
- ,index = $(this).data('index');
- if(othis.data('off')) return;
- $tableFixed.children('tbody').children('tr[data-index='+index+']').removeClass(ELEM_HOVER);
- $tableBody.children('tbody').children('tr[data-index='+index+']').removeClass(ELEM_HOVER);
- })
- },
- addCSSRule: function(sheet, selector, rules, index) {
- if ('insertRule' in sheet) {
- sheet.insertRule(selector + '{' + rules + '}', index)
- } else if ('addRule' in sheet) {
- sheet.addRule(selector, rules, index)
- }
- },
- // 深度克隆-不丢失方法
- deepClone: function (obj) {
- var newObj = Array.isArray(obj) ? [] : {}
- if (obj && typeof obj === "object") {
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- newObj[key] = (obj && typeof obj[key] === 'object') ? this.deepClone(obj[key]) : obj[key];
- }
- }
- }
- return newObj
- },
- getCompleteCols: function (origin) {
- var cols = this.deepClone(origin);
- var i,j,k, cloneCol;
- for (i = 0; i < cols.length; i++) {
- for (j = 0; j < cols[i].length; j++) {
- if (!cols[i][j].exportHandled) {
- if (cols[i][j].rowspan > 1) {
- cloneCol = this.deepClone(cols[i][j])
- cloneCol.exportHandled = true;
- k = i+1;
- while (k < cols.length) {
- cols[k].splice(j, 0, cloneCol)
- k++
- }
- }
- if (cols[i][j].colspan > 1) {
- cloneCol = this.deepClone(cols[i][j])
- cloneCol.exportHandled = true;
- for (k = 1; k < cols[i][j].colspan; k++) {
- cols[i].splice(j, 0, cloneCol)
- }
- j = j + cols[i][j].colspan - 1
- }
- }
- }
- }
- return cols[cols.length-1];
- },
- getScrollWidth: function (elem) {
- var width = 0;
- if(elem){
- width = elem.offsetWidth - elem.clientWidth;
- } else {
- elem = document.createElement('div');
- elem.style.width = '100px';
- elem.style.height = '100px';
- elem.style.overflowY = 'scroll';
- document.body.appendChild(elem);
- width = elem.offsetWidth - elem.clientWidth;
- document.body.removeChild(elem);
- }
- return width;
- }
- };
- // 输出
- exports('tableChild', mod);
- });
|