123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- /**
- *
- * @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);
- });
|