LayUI中表格树折叠 --

1、先将插件源码进行下载,新建 tableTree.js 文件,将源码放进去

2、将 tableTree.js 文件 配置之后,在需要使用的页面进行引入:

layui.define(["tableTree"],function (exports) {
    var tableTree = layui.tableTree;

   // 获取树图的数据
	var handleList = function() {
		// 假数据
		let tableData = [{
		    "pid": "0", 
		    "title": "1",
		    "parentTitle": null,
		    "sid": "1111111111",
		    "children": null
		  },
		  {
		    "pid": "1111111111",
		    "title": "1-1",
		    "parentTitle": "1",
		    "sid": "2"
		},
		  {
		    "pid": "1111111111",
		    "title": "1-2",
		    "parentTitle": "1",
		    "sid": "3"
		},
		  {
		    "pid": "0",
		    "title": "2",
		    "parentTitle": null,
		    "sid": "2222222"
		},{
		    "pid": "0",
		    "title": "3",
		    "parentTitle": null,
		    "sid": "3333333"
		},{
		    "pid": "0",
		    "title": "4",
		    "parentTitle": null,
		    "sid": "44444"
		},{
		    "pid": "0",
		    "title": "5",
		    "parentTitle": null,
		    "sid": "5555"
		},{
		    "pid": "5555",
		    "title": "5",
		    "parentTitle": "5",
		    "sid": "6"
		}]
		renderTable(tableData)
	}
	
	// 表格渲染
    var  renderTable = function (tableData) {
		tableTree.render({
			id: 'test',       //做刷新的时候需要用ID
			tree: {
                 iconIndex: 3, // 展开图标显示再第几列
                 isPidData: true, // // pid形式数据转children形式
                 idName: 'sid', // 子id
                 pidName: 'pid', // 父id
                 openName: 'open',// 是否默认展开的字段名
             },
			elem: '#test',	//表格id
			skin: 'line' //表格风格
			, page: false//是否显示分页
			, limit: 100
			,cols: [[ //标题栏
				{ field: 'sid', hide: true },
				{ type: 'radio'}
				, { field: 'title', title: '名称', align: 'left', width: 200 }
				, {
					field: 'opt', title: '操作', templet:
						function (item) {
							if (item.sid < 100000) {
								return ' '
							}
							return ' '
						}
				}
			]],
			data: tableData,
			//数据渲染完的回调
			done: function () {
			}
			, event: true
		})
	};

    // 单选框点击事件
	tableTree.on('checkbox(LAY-model-manager)', function (obj) {
		var data = obj.data;
		console.log('拿到的当前行的数据', data)
	});

	// 表格操作事件
	tableTree.on("tool(LAY-model-manager)", function (obj) {
		var data = obj.data;
		var layEvent = obj.event;
		var tr = obj.tr;
		if ("del" === layEvent) {
			console.log(删除的数据', data)
		} else if ("edit" === layEvent) {
			console.log(操作的数据', data)
		}
	});
		
	var Class = {
		init: function () {
			// 先请求数据
			handleList()
			return this;
		},
	};
  }
);

效果图:

LayUI中表格树折叠 --_第1张图片

插件源码如下:

/** 树形表格3.x Created by wangfan on 2020-05-12 https://gitee.com/whvse/treetable-lay */
 
layui.define(['laytpl', 'form', 'util'], function (exports) {
    var $ = layui.jquery;
    var laytpl = layui.laytpl;
    var form = layui.form;
    var util = layui.util;
    var device = layui.device();
    var MOD_NAME = 'treeTable';  // 模块名
    var _instances = {};  // 记录所有实例
 
    /* 表格默认参数 */
    var defaultOption = {
        elem: undefined,                                 // 容器
        cols: undefined,                                 // 列参数
        url: undefined,                                  // url模式请求
        method: undefined,                               // url模式请求方式
        where: undefined,                                // url模式请求条件
        contentType: undefined,                          // url模式请求类型
        headers: undefined,                              // url模式请求headers
        parseData: undefined,                            // url模式处理请求数据
        request: {pidName: 'pid'},                       // url模式请求字段自定义
        toolbar: undefined,                              // 表头工具栏
        defaultToolbar: undefined,                       // 表头工具栏右侧按钮
        width: undefined,                                // 容器宽度
        height: undefined,                               // 容器高度
        cellMinWidth: 90,                                // 单元格最小宽度
        done: undefined,                                 // 数据处理完回调
        data: undefined,                                 // 直接赋值数据
        title: undefined,                                // 定义table大标题,文件导出会用到
        skin: undefined,                                 // 表格风格
        even: undefined,                                 // 是否开启隔行变色
        size: undefined,                                 // 表格尺寸
        text: {
            none: '无数据'                               // 空数据提示
        },
        reqData: undefined,                              // 自定义加载数据方法
        useAdmin: false,                                  // 是否使用admin.ajax
        tree: {
            idName: 'id',                                // id的字段名
            pidName: 'pid',                              // pid的字段名
            childName: 'children',                       // children的字段名
            haveChildName: 'haveChild',                  // 是否有children标识的字段名
            openName: 'open',                            // 是否默认展开的字段名
            iconIndex: 0,                                // 图标列的索引
            arrowType: undefined,                        // 折叠箭头类型
            onlyIconControl: undefined,                  // 仅点击图标控制展开折叠
            getIcon: function (d) {                      // 自定义图标
                var haveChild = d[this.haveChildName];
                if (haveChild !== undefined) haveChild = haveChild === true || haveChild === 'true';
                else if (d[this.childName]) haveChild = d[this.childName].length > 0;
                if (haveChild) return '';
                else return '';
            }
        }
    };
    /* 列默认参数 */
    var colDefaultOption = {
        field: undefined,     // 字段名
        title: undefined,     // 标题
        width: undefined,     // 宽度
        minWidth: undefined,  // 最小宽度
        type: 'normal',       // 列类型
        fixed: undefined,     // 固定列
        hide: undefined,      // 是否初始隐藏列
        unresize: undefined,  // 禁用拖拽列宽
        style: undefined,     // 单元格样式
        align: undefined,     // 对齐方式
        colspan: undefined,   // 单元格所占的列数
        rowspan: undefined,   // 单元格所占的行数
        templet: undefined,   // 自定义模板
        toolbar: undefined,   // 工具列
        'class': undefined,   // 单元格class
        singleLine: undefined // 是否一行显示
    };
 
    /** TreeTable类构造方法 */
    var TreeTable = function (options) {
        _instances[options.elem.substring(1)] = this;
        this.reload(options);
    };
 
    /** 参数设置 */
    TreeTable.prototype.initOptions = function (opt) {
        var that = this;
 
        // 处理特殊列
        function initCol(item) {
            if (!item.INIT_OK) item = $.extend({INIT_OK: true}, colDefaultOption, item);
            // 特殊列处理
            if (item.type === 'space') {  // 空列
                if (!item.width) item.width = 15;
                item.minWidth = item.width;
            } else if (item.type === 'numbers') {  // 序号列
                if (!item.width) item.width = 40;
                item.minWidth = item.width;
                if (!item.singleLine) item.singleLine = false;
                if (!item.unresize) item.unresize = true;
                if (!item.align) item.align = 'center';
            } else if (item.type === 'checkbox' || item.type === 'radio') {  // 复/单选框列
                if (!item.width) item.width = 48;
                item.minWidth = item.width;
                if (!item.singleLine) item.singleLine = false;
                if (!item.unresize) item.unresize = true;
                if (!item.align) item.align = 'center';
            }
            if (item.toolbar) item.type = 'tool';
            return item;
        }
 
        // 初始化列参数
        if ('Array' !== isClass(opt.cols[0])) opt.cols = [opt.cols];
 
        // 恢复cols参数初始状态
        for (var m = 0; m < opt.cols.length; m++) {
            for (var n = 0; n < opt.cols[m].length; n++) {
                opt.cols[m][n].INIT_OK = undefined;
                opt.cols[m][n].key = undefined;
                opt.cols[m][n].colGroup = undefined;
                opt.cols[m][n].HAS_PARENT = undefined;
                opt.cols[m][n].parentKey = undefined;
                opt.cols[m][n].PARENT_COL_INDEX = undefined;
            }
        }
 
        // cols参数处理
        var colArrays = [], colIndex = 0;
        for (var i1 = 0; i1 < opt.cols.length; i1++) {
            var item1 = opt.cols[i1];
            for (var i2 = 0; i2 < item1.length; i2++) {
                var item2 = item1[i2];
                if (!item2) {
                    item1.splice(i2, 1);
                    continue;
                }
                item2 = initCol(item2);
                // 合并单元格处理
                item2.key = i1 + '-' + i2;
                var CHILD_COLS = undefined;
                if (item2.colGroup || item2.colspan > 1) {
                    item2.colGroup = true;
                    item2.type = 'group';
                    CHILD_COLS = [];
                    colIndex++;
                    var childIndex = 0;
                    for (var i22 = 0; i22 < opt.cols[i1 + 1].length; i22++) {
                        var item22 = $.extend({INIT_OK: true}, colDefaultOption, opt.cols[i1 + 1][i22]);
                        if (item22.HAS_PARENT || (childIndex > 1 && childIndex == item2.colspan)) {
                            opt.cols[i1 + 1][i22] = item22;
                            continue;
                        }
                        item22.HAS_PARENT = true;
                        item22.parentKey = i1 + '-' + i2;
                        item22.key = (i1 + 1) + '-' + i22;
                        item22.PARENT_COL_INDEX = colIndex;
                        item22 = initCol(item22);
                        CHILD_COLS.push(item22);
                        childIndex = childIndex + parseInt(item22.colspan > 1 ? item22.colspan : 1);
                        opt.cols[i1 + 1][i22] = item22;
                    }
                }
                item2.CHILD_COLS = CHILD_COLS;
                if (!item2.PARENT_COL_INDEX) colArrays.push(item2);
                opt.cols[i1][i2] = item2;
            }
        }
        this.options = $.extend(true, {}, defaultOption, opt);
        this.options.colArrays = colArrays;
 
        // url加载模式转为reqData模式
        if (this.options.url) {
            this.options.reqData = function (data, callback) {
                if (!that.options.where) that.options.where = {};
                if (data) that.options.where[that.options.request.pidName] = data[that.options.tree.idName];
                (that.options.useAdmin ? layui.admin : $).ajax({
                    url: that.options.url,
                    data: that.options.contentType && that.options.contentType.indexOf('application/json') === 0 ? JSON.stringify(that.options.where) : that.options.where,
                    headers: that.options.headers,
                    type: that.options.method,
                    dataType: 'json',
                    contentType: that.options.contentType,
                    success: function (res) {
                        if (that.options.parseData) res = that.options.parseData(res);
                        if (res.code == 0) callback(res.data);
                        else callback(res.msg || '加载失败');
                    },
                    error: function (xhr) {
                        callback(xhr.status + ' - ' + xhr.statusText);
                    }
                });
            };
        } else if (this.options.data && this.options.data.length > 0 && this.options.tree.isPidData) {  // pid形式数据转children形式
            this.options.data = tt.pidToChildren(this.options.data, this.options.tree.idName, this.options.tree.pidName, this.options.tree.childName);
        }
 
        // toolbar参数处理
        if ('default' === this.options.toolbar) {
            this.options.toolbar = [
                '
', '
', ' ', '
'
, '
', ' ', '
'
, '
', ' ', '
'
, '
'
].join(''); } if (this.options.defaultToolbar === undefined) this.options.defaultToolbar = ['filter', 'exports', 'print']; // 自定义图标参数处理 if (typeof this.options.tree.getIcon === 'string') { var icon = this.options.tree.getIcon; this.options.tree.getIcon = function (d) { if (icon !== 'ew-tree-icon-style2') return icon; var haveChild = d[this.haveChildName]; if (haveChild !== undefined) haveChild = haveChild === true || haveChild === 'true'; else if (d[this.childName]) haveChild = d[this.childName].length > 0; if (haveChild) return ''; else return ''; } } }; /** 初始化表格 */ TreeTable.prototype.init = function () { var options = this.options; var $elem = $(options.elem); // 原始表格 var tbFilter = options.elem.substring(1); // 表格的filter // 第一次生成树表格dom $elem.removeAttr('lay-filter'); if ($elem.next('.ew-tree-table').length === 0) { $elem.css('display', 'none'); $elem.after([ '
, tbFilter, '" style="', options.style || '', '">', ' ', '
', '
'
, '
'
, '
', '
'
, '
', ' ', '
'
, '
', options.text.none || '', '
'
, '
'
, '
'
].join('')); } // 获取各个组件 var components = this.getComponents(); // 基础参数设置 if (options.skin) components.$table.attr('lay-skin', options.skin); if (options.size) components.$table.attr('lay-size', options.size); if (options.even) components.$table.attr('lay-even', options.even); // 头部工具栏 components.$toolbar.empty(); if (options.toolbar === false || options.toolbar === undefined) { components.$toolbar.hide(); } else { components.$toolbar.show(); if (typeof options.toolbar === 'string') { laytpl($(options.toolbar).html()).render({}, function (html) { components.$toolbar.html('
' + html + '
'
); }); } var tbRights = ['
']; for (var i = 0; i < options.defaultToolbar.length; i++) { var tbItem; if ('filter' === options.defaultToolbar[i]) { tbItem = {title: '筛选', layEvent: 'LAYTABLE_COLS', icon: 'layui-icon-cols'}; } else if ('exports' === options.defaultToolbar[i]) { tbItem = {title: '导出', layEvent: 'LAYTABLE_EXPORT', icon: 'layui-icon-export'}; } else if ('print' === options.defaultToolbar[i]) { tbItem = {title: '打印', layEvent: 'LAYTABLE_PRINT', icon: 'layui-icon-print'}; } else { tbItem = options.defaultToolbar[i]; } if (tbItem) { tbRights.push('
); tbRights.push(' title="' + tbItem.title + '"'); tbRights.push(' lay-event="' + tbItem.layEvent + '">'); tbRights.push('+ tbItem.icon + '">
'
); } } components.$toolbar.append(tbRights.join('') + '
'
); } // 固定宽度 if (options.width) { components.$view.css('width', options.width); components.$tHeadGroup.css('width', options.width); components.$tBodyGroup.css('width', options.width); } // 表格尺寸设置 var colgroupHtml = this.resize(true); // 生成thead var headHtml = '' + this.renderBodyTh() + ''; // 渲染表头及空的表主体的结构 components.$tBodyGroup.children('style').remove(); if (options.height) { // 固定表头 components.$tHead.html(colgroupHtml + headHtml); components.$tBody.html(colgroupHtml + ''); if (options.height.indexOf('full-') === 0) { // 差值高度 var h = parseFloat(options.height.substring(5)) + components.$toolbar.outerHeight() + components.$tHeadGroup.outerHeight() + 1; components.$tBodyGroup.append([ '' ].join('')); components.$tBodyGroup.data('full', h); components.$tBodyGroup.css('height', ''); } else { // 固定高度 components.$tBodyGroup.css('height', options.height); components.$tBodyGroup.data('full', ''); } components.$tHeadGroup.show(); } else { components.$tHeadGroup.hide(); var trH = {lg: 50, sm: 30, md: 38}; components.$tBodyGroup.append([ '' ].join('')); components.$tBody.html(colgroupHtml + headHtml + ''); } form.render('checkbox', tbFilter); // 渲染表头的表单元素 // 默认隐藏列修正colspan function patchHide($tr) { var parentKey = $tr.data('parent'), pCol; if (!parentKey) return; var $parent = components.$table.children('thead').children('tr').children('[data-key="' + parentKey + '"]'); var colspan = $parent.attr('colspan') - 1; $parent.attr('colspan', colspan); if (colspan === 0) $parent.addClass('layui-hide'); patchHide($parent); } components.$table.children('thead').children('tr').children('th.layui-hide').each(function () { patchHide($(this)); }); // 渲染数据 if (options.reqData) { // 异步加载 this.options.data = undefined; this.renderBodyAsync(); } else if (options.data && options.data.length > 0) { this.renderBodyData(options.data); } else { components.$loading.hide(); components.$empty.show(); } }; /** 绑定各项事件 */ TreeTable.prototype.bindEvents = function () { var that = this; var options = this.options; var components = this.getComponents(); var $allBody = components.$table.children('tbody'); /* 行事件公共返回对象 */ var member = function (ext) { // 获取行dom var $tr = $(this); if (!$tr.is('tr')) { var $temp = $tr.parent('tr'); if ($temp.length > 0) $tr = $temp; else $tr = $tr.parentsUntil('tr').last().parent(); } var data = that.getDataByTr($tr); // 行对应数据 var obj = { tr: $tr, data: data, del: function () { // 删除行 var index = $tr.data('index'); var indent = parseInt($tr.data('indent')); // 删除子级 $tr.nextAll('tr').each(function () { if (parseInt($(this).data('indent')) <= indent) return false; $(this).remove(); }); // 更新后面同辈的index var indexLength = (typeof index === 'number' ? 1 : index.split('-').length); $tr.nextAll('tr').each(function () { var $this = $(this); if (parseInt($this.data('indent')) < indent) return false; var _index = $this.data('index').toString().split('-'); _index[indexLength - 1] = parseInt(_index[indexLength - 1]) - 1; $this.data('index', _index.join('-')); }); // 删除当前行 var $pTr = $tr.prevAll('tr'); that.del(undefined, index); $tr.remove(); that.renderNumberCol(); // 渲染序号列 // 联动父级多选框 $pTr.each(function () { var tInd = parseInt($(this).data('indent')); if (tInd >= indent) return true; that.checkParentCB($(this)); indent = tInd; }); that.checkChooseAllCB(); // 联动全选框 if (options.data.length === 0) components.$empty.show(); updateFixedTbHead(components.$view); // 更新滚动条补丁 }, update: function (fields) { // 修改行 data = $.extend(true, data, fields); var indent = parseInt($tr.data('indent')); that.renderBodyTr(data, indent, undefined, $tr); // 更新界面 form.render(null, components.filter); // 渲染表单元素 that.renderNumberCol(); // 渲染序号列 // 联动父级多选框 $tr.prevAll('tr').each(function () { var tInd = parseInt($(this).data('indent')); if (tInd >= indent) return true; that.checkParentCB($(this)); indent = tInd; }); that.checkChooseAllCB(); // 联动全选框 } }; return $.extend(obj, ext); }; // 绑定折叠展开事件 $allBody.off('click.fold').on('click.fold', '.ew-tree-pack', function (e) { layui.stope(e); var $tr = $(this).parentsUntil('tr').last().parent(); if ($tr.hasClass('ew-tree-table-loading')) return; // 已是加载中 var haveChild = $tr.data('have-child'); if (haveChild !== true && haveChild !== 'true') return; // 子节点 var open = $tr.hasClass('ew-tree-table-open'); var data = that.getDataByTr($tr); if (!open && !data[options.tree.childName]) { that.renderBodyAsync(data, $tr); } else { data[options.tree.openName] = toggleRow($tr); } }); // 绑定lay-event事件 $allBody.off('click.tool').on('click.tool', '*[lay-event]', function (e) { layui.stope(e); var $this = $(this); layui.event.call(this, MOD_NAME, 'tool(' + components.filter + ')', member.call(this, { event: $this.attr('lay-event') })); }); // 绑定单选框事件 form.on('radio(' + components.radioFilter + ')', function (data) { var d = that.getDataByTr($(data.elem).parentsUntil('tr').last().parent()); that.removeAllChecked(); d.LAY_CHECKED = true; // 同时更新数据 d.LAY_INDETERMINATE = false; layui.event.call(this, MOD_NAME, 'checkbox(' + components.filter + ')', {checked: true, data: d, type: 'one'}); }); // 绑定复选框事件 form.on('checkbox(' + components.checkboxFilter + ')', function (data) { var checked = data.elem.checked; var $cb = $(data.elem); var $layCb = $cb.next('.layui-form-checkbox'); // 如果是半选状态,点击全选 if (!checked && $cb.hasClass('ew-form-indeterminate')) { checked = true; $cb.prop('checked', checked); $layCb.addClass('layui-form-checked'); $cb.removeClass('ew-form-indeterminate'); } var $tr = $cb.parentsUntil('tr').last().parent(); var d = that.getDataByTr($tr); d.LAY_CHECKED = checked; // 同时更新数据 d.LAY_INDETERMINATE = false; // 联动操作 if (d[options.tree.childName] && d[options.tree.childName].length > 0) { that.checkSubCB($tr, checked); // 联动子级 } var indent = parseInt($tr.data('indent')); $tr.prevAll('tr').each(function () { var tInd = parseInt($(this).data('indent')); if (tInd < indent) { that.checkParentCB($(this)); // 联动父级 indent = tInd; } }); that.checkChooseAllCB(); // 联动全选框 // 回调事件 layui.event.call(this, MOD_NAME, 'checkbox(' + components.filter + ')', {checked: checked, data: d, type: 'more'}); }); // 绑定全选复选框事件 form.on('checkbox(' + components.chooseAllFilter + ')', function (data) { var checked = data.elem.checked; var $cb = $(data.elem); var $layCb = $cb.next('.layui-form-checkbox'); if (!options.data || options.data.length === 0) { // 如果数据为空 $cb.prop('checked', false); $layCb.removeClass('layui-form-checked'); $cb.removeClass('ew-form-indeterminate'); return; } // 如果是半选状态,点击全选 if (!checked && $cb.hasClass('ew-form-indeterminate')) { checked = true; $cb.prop('checked', checked); $layCb.addClass('layui-form-checked'); $cb.removeClass('ew-form-indeterminate'); } layui.event.call(this, MOD_NAME, 'checkbox(' + components.filter + ')', {checked: checked, type: 'all'}); that.checkSubCB(components.$tBody.children('tbody'), checked); // 联动操作 }); // 绑定行单击事件 $allBody.off('click.row').on('click.row', 'tr', function () { layui.event.call(this, MOD_NAME, 'row(' + components.filter + ')', member.call(this, {})); }); // 绑定行双击事件 $allBody.off('dblclick.rowDouble').on('dblclick.rowDouble', 'tr', function () { layui.event.call(this, MOD_NAME, 'rowDouble(' + components.filter + ')', member.call(this, {})); }); // 绑定单元格点击事件 $allBody.off('click.cell').on('click.cell', 'td', function (e) { var $td = $(this); var type = $td.data('type'); // 判断是否是复选框、单选框列 if (type === 'checkbox' || type === 'radio') return layui.stope(e); var edit = $td.data('edit'); var field = $td.data('field'); if (edit) { // 开启了单元格编辑 layui.stope(e); if ($allBody.find('.ew-tree-table-edit').length > 0) return; var index = $td.data('index'); var indent = $td.find('.ew-tree-table-indent').length; var d = that.getDataByTr($td.parent()); if ('text' === edit || 'number' === edit) { // 文本框 var $input = $('+ edit + '" class="layui-input ew-tree-table-edit"/>'); $input[0].value = d[field]; $td.append($input); $input.focus(); $input.blur(function () { var value = $(this).val(); if (value == d[field]) return $(this).remove(); var rs = layui.event.call(this, MOD_NAME, 'edit(' + components.filter + ')', member.call(this, {value: value, field: field})); if (rs === false) { $(this).addClass('layui-form-danger'); $(this).focus(); } else { d[field] = value; // 同步更新数据 var keys = $td.data('key').split('-'); that.renderBodyTd(d, indent, index, $td, options.cols[keys[0]][keys[1]]); // 更新单元格 } }); } else { console.error('不支持的单元格编辑类型:' + edit); } } else { // 回调单元格点击事件 var rs = layui.event.call(this, MOD_NAME, 'cell(' + components.filter + ')', member.call(this, {td: $td, field: field})); if (rs === false) layui.stope(e); } }); // 绑定单元格双击事件 $allBody.off('dblclick.cellDouble').on('dblclick.cellDouble', 'td', function (e) { var $td = $(this); var type = $td.data('type'); // 判断是否是复选框、单选框列 if (type === 'checkbox' || type === 'radio') return layui.stope(e); var edit = $td.data('edit'); var field = $td.data('field'); if (edit) return layui.stope(e); // 开启了单元格编辑 // 回调单元格双击事件 var rs = layui.event.call(this, MOD_NAME, 'cellDouble(' + components.filter + ')', member.call(this, {td: $td, field: field})); if (rs === false) layui.stope(e); }); // 绑定头部工具栏事件 components.$toolbar.off('click.toolbar').on('click.toolbar', '*[lay-event]', function (e) { layui.stope(e); var $this = $(this); var event = $this.attr('lay-event'); if ('LAYTABLE_COLS' === event) that.toggleCol(); else if ('LAYTABLE_EXPORT' === event) that.exportData('show'); else if ('LAYTABLE_PRINT' === event) that.printTable(); else layui.event.call(this, MOD_NAME, 'toolbar(' + components.filter + ')', {event: event, elem: $this}); }); // 同步滚动条 components.$tBodyGroup.on('scroll', function () { var $this = $(this); components.$tHeadGroup.scrollLeft($this.scrollLeft()); }); // 导出数据 components.$toolbar.off('click.export').on('click.export', '.layui-table-tool-panel>[data-type]', function () { var type = $(this).data('type'); if ('csv' === type || 'xls' === type) that.exportData(type); }); components.$toolbar.off('click.panel').on('click.panel', '.layui-table-tool-panel', function (e) { layui.stope(e); }); // 筛选列 form.on('checkbox(' + components.colsToggleFilter + ')', function (data) { that.toggleCol(data.elem.checked, undefined, data.value); }); }; /** 获取各个组件 */ TreeTable.prototype.getComponents = function () { var $view = $(this.options.elem).next('.ew-tree-table'); // 容器 var filter = $view.attr('lay-filter'); // 容器filter var $tHeadGroup = $view.children('.ew-tree-table-head'); // 表头部分容器 var $tBodyGroup = $view.children('.ew-tree-table-box'); // 主体部分容器 return { $view: $view, filter: filter, $tHeadGroup: $tHeadGroup, $tBodyGroup: $tBodyGroup, $tHead: $tHeadGroup.children('.layui-table'), // 表头表格 $tBody: $tBodyGroup.children('.layui-table'), // 主体表格 $table: $view.find('.layui-table'), // 所有表格 $toolbar: $view.children('.ew-tree-table-tool'), // 头部工具栏 $empty: $tBodyGroup.children('.ew-tree-table-empty'), // 空视图 $loading: $tBodyGroup.children('.ew-tree-table-loading'), // 加载视图 checkboxFilter: 'ew_tb_checkbox_' + filter, // 复选框filter radioFilter: 'ew_tb_radio_' + filter, // 单选框filter chooseAllFilter: 'ew_tb_choose_all_' + filter, // 全选按钮filter colsToggleFilter: 'ew_tb_toggle_cols' + filter // 筛选列的filter }; }; /** * 遍历表头 * @param callback * @param obj */ TreeTable.prototype.eachCols = function (callback, obj) { if (!obj) obj = this.options.colArrays; for (var i = 0; i < obj.length; i++) { var item = obj[i]; callback && callback(i, item); if (item.CHILD_COLS) this.eachCols(callback, item.CHILD_COLS); } }; /** * 遍历数据 * @param callback * @param data */ TreeTable.prototype.eachData = function (callback, data) { if (!data) data = this.options.data; for (var i = 0; i < data.length; i++) { var item = data[i]; callback && callback(i, item); if (item[this.options.tree.childName]) this.eachData(callback, item[this.options.tree.childName]); } }; /** * 异步加载渲染 * @param d 父级数据 * @param $tr 父级dom */ TreeTable.prototype.renderBodyAsync = function (d, $tr) { var that = this; var options = this.options; var components = this.getComponents(); // 显示loading if ($tr) { $tr.addClass('ew-tree-table-loading'); $tr.find('.ew-tree-pack').children('.ew-tree-table-arrow').addClass('layui-anim layui-anim-rotate layui-anim-loop'); } else { components.$empty.hide(); if (options.data && options.data.length > 0) components.$loading.addClass('ew-loading-float'); components.$loading.show(); } // 请求数据 options.reqData(d, function (data) { if (typeof data !== 'string' && data && data.length > 0 && options.tree.isPidData) { data = tt.pidToChildren(data, options.tree.idName, options.tree.pidName, options.tree.childName); } that.renderBodyData(data, d, $tr); // 渲染内容 }); }; /** * 根据数据渲染body * @param data 数据集合 * @param d 父级数据 * @param $tr 父级dom */ TreeTable.prototype.renderBodyData = function (data, d, $tr) { var msg; if (typeof data === 'string') { msg = data; data = []; } var that = this; var options = this.options; var components = this.getComponents(); // 更新到数据 if (d === undefined) options.data = data; else d[options.tree.childName] = data; var indent; if ($tr) { indent = parseInt($tr.data('indent')) + 1; d[options.tree.openName] = true; } var htmlStr = this.renderBody(data, indent, d); if ($tr) { // 移除旧dom $tr.nextAll('tr').each(function () { if (parseInt($(this).data('indent')) <= (indent - 1)) return false; $(this).remove(); }); // 渲染新dom $tr.after(htmlStr).addClass('ew-tree-table-open'); } else { components.$tBody.children('tbody').html(htmlStr); } form.render(null, components.filter); // 渲染表单元素 this.renderNumberCol(); // 渲染序号列 if ($tr) { // 更新父级复选框状态 this.checkParentCB($tr); $tr.prevAll('tr').each(function () { var tInd = parseInt($(this).data('indent')); if (tInd < (indent - 1)) { that.checkParentCB($(this)); indent = tInd + 1; } }); // 移除loading $tr.removeClass('ew-tree-table-loading'); var $arrow = $tr.find('.ew-tree-pack').children('.ew-tree-table-arrow'); $arrow.removeClass('layui-anim layui-anim-rotate layui-anim-loop'); if (msg) { // 加载失败 $tr.removeClass('ew-tree-table-open'); } else if (data && data.length === 0) { // 无子集 d[options.tree.haveChildName] = false; $tr.data('have-child', false); $arrow.addClass('ew-tree-table-arrow-hide'); $arrow.next('.ew-tree-icon').after(options.tree.getIcon(d)).remove(); } } else { // 移除loading components.$loading.hide(); components.$loading.removeClass('ew-loading-float'); // 显示空视图 if (data && data.length > 0) { components.$empty.hide(); } else { components.$empty.show(); if (msg) components.$empty.text(msg); else components.$empty.html(options.text.none); } } this.checkChooseAllCB(); // 联动全选框 updateFixedTbHead(components.$view); // 滚动条补丁 options.done && options.done(data); }; /** * 递归渲染表格主体部分 * @param data 数据列表 * @param indent 缩进大小 * @param parent 父级 * @param h 父级是否隐藏 * @returns {string} */ TreeTable.prototype.renderBody = function (data, indent, parent, h) { var options = this.options; if (!indent) indent = 0; var html = ''; if (!data || data.length === 0) return html; var hide = parent ? !parent[options.tree.openName] : undefined; if (h) hide = h;//当所有父级存在隐藏时,隐藏所有子集 for (var i = 0; i < data.length; i++) { var d = data[i]; d.LAY_INDEX = (parent ? parent.LAY_INDEX + '-' : '') + i; html += this.renderBodyTr(d, indent, hide); // 递归渲染子集 html += this.renderBody(d[options.tree.childName], indent + 1, d, h); } return html; }; /** * 渲染每一行数据 * @param d 行数据 * @param indent 缩进大小 * @param hide 是否隐藏 * @param $tr * @returns {string} */ TreeTable.prototype.renderBodyTr = function (d, indent, hide, $tr) { var that = this; var options = this.options; if (!indent) indent = 0; var haveChild = d[options.tree.haveChildName]; if (haveChild === undefined) haveChild = d[options.tree.childName] && d[options.tree.childName].length > 0; if ($tr) { $tr.data('have-child', haveChild ? 'true' : 'false'); $tr.data('indent', indent); $tr.removeClass('ew-tree-table-loading'); } var html = '; var classNames = ''; if (haveChild && d[options.tree.openName]) classNames += 'ew-tree-table-open'; if (hide) classNames += 'ew-tree-tb-hide'; html += (' class="' + classNames + '"'); if (haveChild) html += (' data-have-child="' + haveChild + '"'); html += (' data-index="' + d.LAY_INDEX + '"'); html += (' data-indent="' + indent + '">'); var index = 0; this.eachCols(function (i, col) { if (col.colGroup) return; html += that.renderBodyTd(d, indent, index, $tr ? $tr.children('td').eq(index) : undefined, col); index++; }); html += ''; return html; }; /** * 渲染每一个单元格数据 * @param d 行数据 * @param indent 缩进大小 * @param index 第几列 * @param $td * @param col * @returns {string} */ TreeTable.prototype.renderBodyTd = function (d, indent, index, $td, col) { if (!col||col.colGroup) return ''; var options = this.options; var components = this.getComponents(); if (!indent) indent = 0; // 内容填充 var content = '', cell = '', icon = ''; if (col.type === 'numbers') { // 序号列 content = ''; } else if (col.type === 'checkbox') { // 复选框列 content = [ ', d.LAY_CHECKED ? ' checked="checked"' : '', ' lay-filter="', components.checkboxFilter, '"', ' lay-skin="primary" class="ew-tree-table-checkbox', d.LAY_INDETERMINATE ? ' ew-form-indeterminate' : '', '" />' ].join(''); } else if (col.type === 'radio') { // 单选框列 content = [ ', d.LAY_CHECKED ? ' checked="checked"' : '', ' lay-filter="', components.radioFilter, '"', ' name="', components.radioFilter, '"', ' class="ew-tree-table-radio" />' ].join(''); } else if (col.templet) { // 自定义模板 if (typeof col.templet === 'function') { content = col.templet(d); } else if (typeof col.templet === 'string') { laytpl($(col.templet).html()).render(d, function (html) { content = html; }); } } else if (col.toolbar) { // 操作列 if (typeof col.toolbar === 'function') { content = col.toolbar(d); } else if (typeof col.toolbar === 'string') { laytpl($(col.toolbar).html()).render(d, function (html) { content = html; }); } } else if (col.field && d[col.field] !== undefined && d[col.field] !== null) { // 普通字段 content = util.escape(d[col.field] === 0 ? '0' : d[col.field]); } // 图标列处理 if (index === options.tree.iconIndex) { // 缩进 for (var i = 0; i < indent; i++) icon += ''; icon += ''; // 加箭头 var haveChild = d[options.tree.haveChildName]; if (haveChild === undefined) haveChild = d[options.tree.childName] && d[options.tree.childName].length > 0; icon += ('+ (haveChild ? '' : ' ew-tree-table-arrow-hide')); icon += (' ' + (options.tree.arrowType || '') + '">'); // 加图标 icon += options.tree.getIcon(d); content = '' + content + ''; if (options.tree.onlyIconControl) content = icon + '' + content; else content = icon + content + ''; } cell = [ '
, col.singleLine === undefined || col.singleLine ? ' single-line' : '', '"', col.align ? ' align="' + col.align + '"' : '', '>', '
', content, '
'
, ' ', ' ', '
'
].join(''); if ($td) $td.html(cell); var html = '; if (col.field) html += (' data-field="' + col.field + '"'); if (col.edit) html += (' data-edit="' + col.edit + '"'); if (col.type) html += (' data-type="' + col.type + '"'); if (col.key) html += (' data-key="' + col.key + '"'); if (col.style) html += (' style="' + col.style + '"'); if (col['class']) html += (' class="' + col['class'] + (col.hide ? ' layui-hide' : '') + '"'); else if (col.hide) html += (' class="layui-hide"'); html += ('>' + cell + ''); return html; }; /** * 渲染表头 * @returns {string} */ TreeTable.prototype.renderBodyTh = function () { var options = this.options; var components = this.getComponents(); var html = []; $.each(options.cols, function (i1, item1) { html.push(''); $.each(item1, function (i2, item2) { html.push('); if (item2.colspan) html.push(' colspan="' + item2.colspan + '"'); if (item2.rowspan) html.push(' rowspan="' + item2.rowspan + '"'); if (item2.type) html.push(' data-type="' + item2.type + '"'); if (item2.key) html.push(' data-key="' + item2.key + '"'); if (item2.parentKey) html.push(' data-parent="' + item2.parentKey + '"'); if (item2.hide) html.push(' class="layui-hide"'); html.push('>'); html.push('
+ (item2.singleLine === undefined || item2.singleLine ? ' single-line' : '') + '"'); if (item2.thAlign || item2.align) html.push(' align="' + (item2.thAlign || item2.align) + '"'); html.push('>'); html.push('
'); // 标题 var ca = '+ components.chooseAllFilter + '" lay-skin="primary" class="ew-tree-table-checkbox"/>'; if (item2.type === 'checkbox') html.push(ca); else html.push(item2.title || ''); html.push('
'
); html.push('
'
); // 列宽拖拽 if (!item2.colGroup && !item2.unresize) html.push(''); html.push(''); }); html.push(''); }); return html.join(''); }; /** 重置表格尺寸 */ TreeTable.prototype.resize = function (returnColgroup) { // 计算表格宽度、最小宽度、百分比宽度 var options = this.options; var components = this.getComponents(); var minWidth = 1, width = 1, needSetWidth = true, mwPercent = 0; this.eachCols(function (i, item) { if (item.colGroup || item.hide) return; if (item.width) { width += (item.width + 1); if (item.minWidth) { if (item.width < item.minWidth) item.width = item.minWidth; } else if (item.width < options.cellMinWidth) item.width = options.cellMinWidth; } else needSetWidth = false; if (item.width) minWidth += (item.width + 1); else if (item.minWidth) { minWidth += (item.minWidth + 1); mwPercent += item.minWidth; } else { minWidth += (options.cellMinWidth + 1); mwPercent += options.cellMinWidth; } }); if (minWidth) { components.$tHead.css('min-width', minWidth); components.$tBody.css('min-width', minWidth); } else { components.$tHead.css('min-width', 'auto'); components.$tBody.css('min-width', 'auto'); } if (needSetWidth) { components.$tHead.css('width', width); components.$tBody.css('width', width); } else { components.$tHead.css('width', '100%'); components.$tBody.css('width', '100%'); } // 生成colgroup var colgroupHtml = []; this.eachCols(function (i, item) { if (item.colGroup || item.hide) return; colgroupHtml.push('); if (item.width) colgroupHtml.push(' width="' + item.width + '"'); else if (item.minWidth) colgroupHtml.push(' width="' + (item.minWidth / mwPercent * 100).toFixed(2) + '%"'); else colgroupHtml.push(' width="' + (options.cellMinWidth / mwPercent * 100).toFixed(2) + '%"'); if (item.type) colgroupHtml.push(' data-type="' + item.type + '"'); if (item.key) colgroupHtml.push(' data-key="' + item.key + '"'); colgroupHtml.push('/>'); }); colgroupHtml = colgroupHtml.join(''); if (returnColgroup) return '' + colgroupHtml + ''; components.$table.children('colgroup').html(colgroupHtml); }; /** 获取行对应数据 */ TreeTable.prototype.getDataByTr = function ($tr) { var data, index; if (typeof $tr !== 'string' && typeof $tr !== 'number') { if ($tr) index = $tr.data('index'); } else index = $tr; if (index === undefined) return; if (typeof index === 'number') index = [index]; else index = index.split('-'); for (var i = 0; i < index.length; i++) { if (data) data = data[this.options.tree.childName][index[i]]; else data = this.options.data[index[i]]; } return data; }; /** * 联动子级复选框状态 * @param $tr 当前tr的dom * @param checked */ TreeTable.prototype.checkSubCB = function ($tr, checked) { var that = this; var components = this.getComponents(); var indent = -1, $trList; if ($tr.is('tbody')) { $trList = $tr.children('tr'); } else { indent = parseInt($tr.data('indent')); $trList = $tr.nextAll('tr'); } $trList.each(function () { if (parseInt($(this).data('indent')) <= indent) return false; var $cb = $(this).children('td').find('input[lay-filter="' + components.checkboxFilter + '"]'); $cb.prop('checked', checked); $cb.removeClass('ew-form-indeterminate'); if (checked) $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); else $cb.next('.layui-form-checkbox').removeClass('layui-form-checked'); var d = that.getDataByTr($(this)); d.LAY_CHECKED = checked; // 同步更新数据 d.LAY_INDETERMINATE = false; }); }; /** * 联动父级复选框状态 * @param $tr 父级的dom */ TreeTable.prototype.checkParentCB = function ($tr) { var options = this.options; var components = this.getComponents(); var d = this.getDataByTr($tr); var ckNum = 0, unCkNum = 0; if (d[options.tree.childName]) { function checkNum(data) { for (var i = 0; i < data.length; i++) { if (data[i].LAY_CHECKED) ckNum++; else unCkNum++; if (data[i][options.tree.childName]) checkNum(data[i][options.tree.childName]); } } checkNum(d[options.tree.childName]); } var $cb = $tr.children('td').find('input[lay-filter="' + components.checkboxFilter + '"]'); if (ckNum > 0 && unCkNum === 0) { // 全选 $cb.prop('checked', true); $cb.removeClass('ew-form-indeterminate'); $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); d.LAY_CHECKED = true; // 同步更新数据 d.LAY_INDETERMINATE = false; } else if (ckNum === 0 && unCkNum > 0) { // 全不选 $cb.prop('checked', false); $cb.removeClass('ew-form-indeterminate'); $cb.next('.layui-form-checkbox').removeClass('layui-form-checked'); d.LAY_CHECKED = false; // 同步更新数据 d.LAY_INDETERMINATE = false; } else if (ckNum > 0 && unCkNum > 0) { // 半选 $cb.prop('checked', true); $cb.data('indeterminate', 'true'); $cb.addClass('ew-form-indeterminate'); $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); d.LAY_CHECKED = true; // 同步更新数据 d.LAY_INDETERMINATE = true; } }; /** 联动全选复选框 */ TreeTable.prototype.checkChooseAllCB = function () { var options = this.options; var components = this.getComponents(); var ckNum = 0, unCkNum = 0; function checkNum(data) { for (var i = 0; i < data.length; i++) { if (data[i].LAY_CHECKED) ckNum++; else unCkNum++; if (data[i][options.tree.childName]) checkNum(data[i][options.tree.childName]); } } checkNum(options.data); var $cb = components.$view.find('input[lay-filter="' + components.chooseAllFilter + '"]'); if (ckNum > 0 && unCkNum === 0) { // 全选 $cb.prop('checked', true); $cb.removeClass('ew-form-indeterminate'); $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); } else if ((ckNum === 0 && unCkNum > 0) || (ckNum === 0 && unCkNum === 0)) { // 全不选 $cb.prop('checked', false); $cb.removeClass('ew-form-indeterminate'); $cb.next('.layui-form-checkbox').removeClass('layui-form-checked'); } else if (ckNum > 0 && unCkNum > 0) { // 半选 $cb.prop('checked', true); $cb.addClass('ew-form-indeterminate'); $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); } }; /** 填充序号列 */ TreeTable.prototype.renderNumberCol = function () { this.getComponents().$tBody.children('tbody').children('tr').each(function (i) { $(this).children('td').find('.ew-tree-table-numbers').text(i + 1); }); }; /** 根据id获取tr的index */ TreeTable.prototype.getIndexById = function (id) { var options = this.options; function each(data, pi) { for (var i = 0; i < data.length; i++) { if (data[i][options.tree.idName] === id) return pi !== undefined ? pi + '-' + i : i; if (data[i][options.tree.childName]) { var res = each(data[i][options.tree.childName], pi !== undefined ? pi + '-' + i : i); //值不为undefined才return if (res) return res; } } } return each(options.data); }; /** 展开指定行 */ TreeTable.prototype.expand = function (id, cascade) { var components = this.getComponents(); var $tr = components.$table.children('tbody').children('tr[data-index="' + this.getIndexById(id) + '"]'); if (!$tr.hasClass('ew-tree-table-open')) $tr.children('td').find('.ew-tree-pack').trigger('click'); if (cascade === false) return; // 联动父级 var indent = parseInt($tr.data('indent')); $tr.prevAll('tr').each(function () { var tInd = parseInt($(this).data('indent')); if (tInd < indent) { if (!$(this).hasClass('ew-tree-table-open')) { $(this).children('td').find('.ew-tree-pack').trigger('click'); } indent = tInd; } }); }; /** 折叠指定行 */ TreeTable.prototype.fold = function (id) { var components = this.getComponents(); var $tr = components.$table.children('tbody').children('tr[data-index="' + this.getIndexById(id) + '"]'); if ($tr.hasClass('ew-tree-table-open')) $tr.children('td').find('.ew-tree-pack').trigger('click'); }; /** 全部展开 */ TreeTable.prototype.expandAll = function () { this.getComponents().$table.children('tbody').children('tr').each(function () { if (!$(this).hasClass('ew-tree-table-open')) $(this).children('td').find('.ew-tree-pack').trigger('click'); }); }; /** 全部折叠 */ TreeTable.prototype.foldAll = function () { this.getComponents().$table.children('tbody').children('tr').each(function () { if ($(this).hasClass('ew-tree-table-open')) $(this).children('td').find('.ew-tree-pack').trigger('click'); }); }; /** 获取当前数据 */ TreeTable.prototype.getData = function () { return this.options.data; }; /** 重载表格 */ TreeTable.prototype.reload = function (opt) { this.initOptions(this.options ? $.extend(true, this.options, opt) : opt); this.init(); // 初始化表格 this.bindEvents(); // 绑定事件 }; /** 获取当前选中行 */ TreeTable.prototype.checkStatus = function (needIndeterminate) { if (needIndeterminate === undefined) needIndeterminate = true; var list = []; this.eachData(function (i, item) { if ((needIndeterminate || !item.LAY_INDETERMINATE) && item.LAY_CHECKED) list.push($.extend({isIndeterminate: item.LAY_INDETERMINATE}, item)); }); return list; }; /** 设置复/单选框选中 */ TreeTable.prototype.setChecked = function (ids) { var that = this; var components = this.getComponents(); var $radio = components.$table.find('input[lay-filter="' + components.radioFilter + '"]'); if ($radio.length > 0) { // 开启了单选框 $radio.each(function () { var d = that.getDataByTr($(this).parentsUntil('tr').parent()); if (d && ids[ids.length - 1] == d[that.options.tree.idName]) { $(this).next('.layui-form-radio').trigger('click'); return false; } }); } else { // 开启了复选框 components.$table.find('input[lay-filter="' + components.checkboxFilter + '"]').each(function () { var $cb = $(this); var $layCb = $cb.next('.layui-form-checkbox'); var checked = $cb.prop('checked'); var indeterminate = $cb.hasClass('ew-form-indeterminate'); var d = that.getDataByTr($cb.parentsUntil('tr').parent()); for (var i = 0; i < ids.length; i++) { if (d && ids[i] == d[that.options.tree.idName]) { if (d[that.options.tree.childName] && d[that.options.tree.childName].length > 0) continue; if (!checked || indeterminate) $layCb.trigger('click'); } } }); } }; /** 移除全部选中 */ TreeTable.prototype.removeAllChecked = function () { this.checkSubCB(this.getComponents().$table.children('tbody'), false); }; /** 导出 */ TreeTable.prototype.exportData = function (type) { var components = this.getComponents(); if ('show' === type) { components.$toolbar.find('.layui-table-tool-panel').remove(); components.$toolbar.find('[lay-event="LAYTABLE_EXPORT"]').append([ '
    ', '
  • 导出到 Csv 文件
  • '
    , '
  • 导出到 Excel 文件
  • '
    , '
'
].join('')); } else { if (device.ie) return layer.msg('不支持ie导出'); if (!type) type = 'xls'; var head = [], body = []; this.eachCols(function (i, item) { if (item.type !== 'normal' || item.hide) return; head.push(item.title || ''); }); components.$tBody.children('tbody').children('tr').each(function () { var items = []; $(this).children('td').each(function () { var $this = $(this); if ($this.data('type') !== 'normal' || $this.hasClass('layui-hide')) return true; items.push($this.text().trim().replace(/,/g, ',')); }); body.push(items.join(',')); }); // 创建下载文件的a标签 var alink = document.createElement('a'); var content = encodeURIComponent(head.join(',') + '\r\n' + body.join('\r\n')); var contentType = ({csv: 'text/csv', xls: 'application/vnd.ms-excel'})[type]; alink.href = 'data:' + contentType + ';charset=utf-8,\ufeff' + content; alink.download = (this.options.title || 'table') + '.' + type; document.body.appendChild(alink); alink.click(); document.body.removeChild(alink); } }; /** 打印 */ TreeTable.prototype.printTable = function () { var components = this.getComponents(); var head = components.$tHead.children('thead').html(); if (!head) head = components.$tBody.children('thead').html(); var body = components.$tBody.children('tbody').html(); var colgroup = components.$tBody.children('colgroup').html(); var $html = $([ '',' ', colgroup,'',' ', head,'',' ', body,'','
'
].join('')); // 隐藏特殊列 $html.find('col[data-type="checkbox"],col[data-type="radio"],col[data-type="tool"]').remove(); $html.find('td[data-type="checkbox"],td[data-type="radio"],td[data-type="tool"],.layui-hide').remove(); function hideCol($temp) { var parentKey = $temp.data('parent'), pCol; if (!parentKey) return; var $parent = $html.children('thead').children('tr').children('[data-key="' + parentKey + '"]'); var colspan = parseInt($parent.attr('colspan')) - 1; $parent.attr('colspan', colspan); if (colspan === 0) $parent.remove(); hideCol($parent); } $html.find('th[data-type="checkbox"],th[data-type="radio"],th[data-type="tool"]').each(function () { hideCol($(this)); }).remove(); // 打印内容样式 var style = [ '' ].join(''); var pWindow = window.open('', '_blank'); pWindow.focus(); var pDocument = pWindow.document; pDocument.open(); pDocument.write($html[0].outerHTML + style); pDocument.close(); pWindow.print(); pWindow.close(); }; /** 筛选列 */ TreeTable.prototype.toggleCol = function (show, field, key) { var components = this.getComponents(); if (show === undefined) { components.$toolbar.find('.layui-table-tool-panel').remove(); var cols = ['
    ']; this.eachCols(function (i, item) { if (item.type !== 'normal') return; cols.push('
  • ); cols.push(' lay-filter="' + components.colsToggleFilter + '"'); cols.push(' value="' + item.key + '" title="' + util.escape(item.title || '') + '"'); cols.push((item.hide ? '' : ' checked') + '>
  • '
    ); }); components.$toolbar.find('[lay-event="LAYTABLE_COLS"]').append(cols.join('') + '
'
); form.render('checkbox', components.filter); } else { if (key) { var $td = components.$table.children('tbody').children('tr').children('[data-key="' + key + '"]'); var $th = components.$table.children('thead').children('tr').children('[data-key="' + key + '"]'); if (show) { $td.removeClass('layui-hide'); $th.removeClass('layui-hide'); } else { $td.addClass('layui-hide'); $th.addClass('layui-hide'); } // 同步更新数据 var ks = key.split('-'); var col = this.options.cols[ks[0]][ks[1]]; col.hide = !show; // 更新colspan数据 function changeParent($temp) { var parentKey = $temp.data('parent'), pCol; if (!parentKey) return; var $parent = components.$table.children('thead').children('tr').children('[data-key="' + parentKey + '"]'); var colspan = $parent.attr('colspan'); show ? colspan++ : colspan--; $parent.attr('colspan', colspan); if (colspan === 0) $parent.addClass('layui-hide'); else $parent.removeClass('layui-hide'); changeParent($parent); } changeParent($th); // 同步eachCols数据 this.eachCols(function (i, item) { if (item.key === key) item.hide = col.hide; }); this.resize(); // 更新表格尺寸 } } }; /** * 搜索数据 * @param ids 关键字或数据id集合 */ TreeTable.prototype.filterData = function (ids) { var components = this.getComponents(); components.$loading.show(); if (this.options.data.length > 0) components.$loading.addClass('ew-loading-float'); var $trList = components.$table.children('tbody').children('tr'); var indexList = []; if (typeof ids === 'string') { // 关键字 $trList.each(function () { var index = $(this).data('index'); $(this).children('td').each(function () { if ($(this).text().indexOf(ids) !== -1) { indexList.push(index); return false; } }); }); } else { for (var i = 0; i < ids.length; i++) { indexList.push(this.getIndexById(ids[i])); } } $trList.addClass('ew-tree-table-filter-hide'); for (var j = 0; j < indexList.length; j++) { var $tr = $trList.filter('[data-index="' + indexList[j] + '"]'); $tr.removeClass('ew-tree-table-filter-hide'); var indent = parseInt($tr.data('indent')); // 联动子级 $tr.nextAll('tr').each(function () { if (parseInt($(this).data('indent')) <= indent) return false; $(this).removeClass('ew-tree-table-filter-hide'); }); if ($tr.hasClass('ew-tree-table-open')) toggleRow($tr); // 联动父级 $tr.prevAll('tr').each(function () { var tInd = parseInt($(this).data('indent')); if (tInd < indent) { $(this).removeClass('ew-tree-table-filter-hide'); if (!$(this).hasClass('ew-tree-table-open')) toggleRow($(this)); indent = tInd; } }); } // 最后再检查一遍 /*$trList.not('.ew-tree-table-filter-hide').not('.ew-tree-tb-hide').each(function () { var index = $(this).data('index'), hide = true; for (var k = 0; k < indexList.length; k++) { if (indexList[k] === index) hide = false; } if (hide) $(this).addClass('ew-tree-table-filter-hide'); });*/ components.$loading.hide(); components.$loading.removeClass('ew-loading-float'); if (indexList.length === 0) components.$empty.show(); updateFixedTbHead(components.$view); // 更新滚动条补丁 }; /** 重置搜索 */ TreeTable.prototype.clearFilter = function () { var components = this.getComponents(); components.$table.children('tbody').children('tr').removeClass('ew-tree-table-filter-hide'); if (this.options.data.length > 0) components.$empty.hide(); updateFixedTbHead(components.$view); // 更新滚动条补丁 }; /** * 刷新指定父级下的节点 * @param id 父级id,空则全部刷新 * @param data 非异步模式替换的数据 */ TreeTable.prototype.refresh = function (id, data) { if (isClass(id) === 'Array') { data = id; id = undefined; } var components = this.getComponents(); var d, $tr; if (id !== undefined) { $tr = components.$table.children('tbody').children('tr[data-index="' + this.getIndexById(id) + '"]'); d = this.getDataByTr($tr); } if (data) { // 数据模式 if (data.length > 0) components.$loading.addClass('ew-loading-float'); components.$loading.show(); if (data.length > 0 && this.options.tree.isPidData) { // pid形式数据 this.renderBodyData(tt.pidToChildren(data, this.options.tree.idName, this.options.tree.pidName, this.options.tree.childName), d, $tr); } else { this.renderBodyData(data, d, $tr); } } else { // 异步模式 this.renderBodyAsync(d, $tr); } }; /** 删除数据 */ TreeTable.prototype.del = function (id, index) { if (index === undefined) index = this.getIndexById(id); var indexList = (typeof index === 'number' ? [index] : index.split('-')); var d = this.options.data; if (indexList.length > 1) { for (var i = 0; i < indexList.length - 1; i++) { d = d[parseInt(indexList[i])][this.options.tree.childName]; } } d.splice(indexList[indexList.length - 1], 1); }; /** 更新数据 */ TreeTable.prototype.update = function (id, fields) { $.extend(true, this.getDataByTr(this.getIndexById(id)), fields); }; /** 折叠/展开行 */ function toggleRow($tr) { var indent = parseInt($tr.data('indent')); var open = $tr.hasClass('ew-tree-table-open'); if (open) { // 折叠 $tr.removeClass('ew-tree-table-open'); $tr.nextAll('tr').each(function () { if (parseInt($(this).data('indent')) <= indent) return false; $(this).addClass('ew-tree-tb-hide'); }); } else { // 展开 $tr.addClass('ew-tree-table-open'); var hideInd; $tr.nextAll('tr').each(function () { var ind = parseInt($(this).data('indent')); if (ind <= indent) return false; if (hideInd !== undefined && ind > hideInd) return true; $(this).removeClass('ew-tree-tb-hide'); if (!$(this).hasClass('ew-tree-table-open')) hideInd = parseInt($(this).data('indent')); else hideInd = undefined; }); } updateFixedTbHead($tr.parentsUntil('.ew-tree-table').last().parent()); return open; } /** 固定表头滚动条补丁 */ function updateFixedTbHead($view) { var $headBox = $view.children('.ew-tree-table-head'); var $tbBox = $view.children('.ew-tree-table-box'); var sWidth = $tbBox.width() - $tbBox.prop('clientWidth'); $headBox.css('border-right', (sWidth > 0 ? sWidth : 0) + 'px solid #f2f2f2'); } // 监听窗口大小改变 $(window).resize(function () { $('.ew-tree-table').each(function () { updateFixedTbHead($(this)); var $tbBox = $(this).children('.ew-tree-table-box'); var full = $tbBox.data('full'); if (full && device.ie && device.ie < 10) { $tbBox.css('height', getPageHeight() - full); } }); }); /** 表格溢出点击展开功能 */ $(document).on('mouseenter', '.ew-tree-table-cell.single-line', function () { var $content = $(this).children('.ew-tree-table-cell-content'); if ($content.prop('scrollWidth') > $content.outerWidth()) $(this).children('.layui-table-grid-down').show(); }).on('mouseleave', '.ew-tree-table-cell.single-line', function () { $(this).children('.layui-table-grid-down').hide(); }); // 点击箭头展开 $(document).on('click', '.ew-tree-table-cell>.layui-table-grid-down', function (e) { e.stopPropagation(); hideAllTdTips(); var $cell = $(this).parent(); $cell.addClass('ew-tree-tips-open'); $cell.children('.layui-table-grid-down').hide(); var tw = $cell.parent().outerWidth() + 4; if ($cell.outerWidth() < tw) $cell.children('.ew-tree-table-cell-content').css({'width': tw, 'max-width': tw}); var $box = $cell.parents().filter('.ew-tree-table-box'); if ($box.length === 0) $box = $cell.parents().filter('.ew-tree-table-head'); if ($box.length === 0) return; if (($cell.outerWidth() + $cell.offset().left) + 20 > $box.offset().left + $box.outerWidth()) { $cell.addClass('ew-show-left'); } if (($cell.outerHeight() + $cell.offset().top + 10) > $box.offset().top + $box.outerHeight()) { $cell.addClass('ew-show-bottom'); } }); // 点击关闭按钮关闭 $(document).on('click', '.ew-tree-table-cell>.ew-tree-tips-c', function () { hideAllTdTips(); }); // 点击空白部分关闭 $(document).on('click', function () { hideAllTdTips(); $('.ew-tree-table .layui-table-tool-panel').remove(); }); $(document).on('click', '.ew-tree-table-cell.ew-tree-tips-open', function (e) { e.stopPropagation(); }); /* 关闭所有单元格溢出提示框 */ function hideAllTdTips() { $('.ew-tree-table-cell').removeClass('ew-tree-tips-open ew-show-left ew-show-bottom'); $('.ew-tree-table-cell>.ew-tree-table-cell-content').css({'width': '', 'max-width': ''}); } /** 拖拽调整列宽 */ $(document).on('mousedown', '.ew-tb-resize', function (e) { layui.stope(e); var $this = $(this); $this.attr('move', 'true'); var key = $this.parent().data('key'); $this.data('x', e.clientX); var w = $this.parent().parent().parent().parent().children('colgroup').children('col[data-key="' + key + '"]').attr('width'); if (!w || w.toString().indexOf('%') !== -1) w = $this.parent().outerWidth(); $this.data('width', w); $('body').addClass('ew-tree-table-resizing'); }).on('mousemove', function (e) { var $rs = $('.ew-tree-table .ew-tb-resize[move="true"]'); if ($rs.length === 0) return; layui.stope(e); var x = $rs.data('x'); var w = $rs.data('width'); var nw = parseFloat(w) + e.clientX - parseFloat(x); if (nw <= 0) nw = 1; // 更新实例options中的宽度 var ins = _instances[$rs.parentsUntil('.ew-tree-table').last().parent().attr('lay-filter')]; var key = $rs.parent().data('key'); var ks = key.split('-'); ins.options.cols[ks[0]][ks[1]].width = nw; ins.eachCols(function (i, item) { if (item.key === key) item.width = nw; }); ins.resize(); }).on('mouseup', function (e) { $('.ew-tree-table .ew-tb-resize[move="true"]').attr('move', 'false'); $('body').removeClass('ew-tree-table-resizing'); }).on('mouseleave', function (e) { $('.ew-tree-table .ew-tb-resize[move="true"]').attr('move', 'false'); $('body').removeClass('ew-tree-table-resizing'); }); /** 获取顶级的pId */ function getPids(data, idName, pidName) { var pids = []; for (var i = 0; i < data.length; i++) { var hasPid = false; for (var j = 0; j < data.length; j++) { if (data[i][pidName] == data[j][idName]) { hasPid = true; break; } } if (!hasPid) pids.push(data[i][pidName]); } return pids; } /** 判断pId是否相等 */ function pidEquals(pId, pIds) { if (isClass(pIds) === 'Array') { for (var i = 0; i < pIds.length; i++) if (pId == pIds[i]) return true; } return pId == pIds; } /** 获取变量类型 */ function isClass(o) { if (o === null) return 'Null'; if (o === undefined) return 'Undefined'; return Object.prototype.toString.call(o).slice(8, -1); } /** 获取浏览器高度 */ function getPageHeight() { return document.documentElement.clientHeight || document.body.clientHeight; } /** 对外提供的方法 */ var tt = { /* 渲染 */ render: function (options) { return new TreeTable(options); }, /* 重载 */ reload: function (id, opt) { _instances[id].reload(opt); }, /* 事件监听 */ on: function (events, callback) { return layui.onevent.call(this, MOD_NAME, events, callback); }, /* pid转children形式 */ pidToChildren: function (data, idName, pidName, childName, pId) { if (!childName) childName = 'children'; var newList = []; for (var i = 0; i < data.length; i++) { if (data[i][idName] == data[i][pidName]) return console.error('第' + i + '条数据的' + idName + '与' + pidName + '相同', data[i]); if (pId === undefined) pId = getPids(data, idName, pidName); if (pidEquals(data[i][pidName], pId)) { var children = this.pidToChildren(data, idName, pidName, childName, data[i][idName]); if (children.length > 0) data[i][childName] = children; newList.push(data[i]); } } return newList; } }; /** 添加样式 */ $('head').append([ '' ].join('')); exports('tableTree', tt); });

你可能感兴趣的:(UI框架,layui,javascript,前端)