layui.define(['form', 'laypage'], function (exports) { var form = layui.form, Grid = { config: { render: function (view, data) { return '未配置渲染函数'; }, //渲染函数 token: '' }, createNew: function (option) { var GRIDORDER = [], RESIZE = { left: 0, top: 0 }, CONFIG = this.config; //样式 var CSS = { danger:'grid-danger' } var grid = { elem: typeof (option.elem) === 'string' ? $('#' + option.elem) : option.elem, //GridID 或 Jquery对象 view: option.view, //模板名称 //originData: option.data, data: option.data, //模板数据(json) pageData: null, //页面数据,分页后当前页数据 url: option.url, //获取数据的url(返回Json,优先使用data数据) page: option.page || 1, //页码 pageSize: option.pageSize, //每页显示条数 pageGroup: option.pageGroup == undefined ? 5 : option.pageGroup, search: option.search, //搜索按钮(submit)的lay-filter searchData: option.searchData || [], html: '', //渲染后的html flag: true, //获取数据是否成功 message: '', //错误消息 total: 0, //数据总条数 record: option.record || false, //是否显示总记录数 freeze: option.freeze, singleSelect: option.singleSelect || false, //是否单选 success: option.success, //渲染结束后执行 rowClick: option.rowClick, rowid: option.rowid, dataSuccess: option.dataSuccess //获取数据成功后触发的事件 }; grid.build = function () { fnData(fnSuccess); } function fnFreeze() { } //获取数据 function fnData(fn) { grid.loading(); if (grid.data) { var DATA = $.extend(true, {}, grid.data); //排序 if (GRIDORDER.length > 0) { DATA.rows.sort(function (a, b) { var r = 0; for (var i = GRIDORDER.length; i > 0; i--) { var x = a[GRIDORDER[i - 1].code], y = b[GRIDORDER[i - 1].code]; if (x == y) r = 0; else { r = (x > y ? 1 : -1) * (GRIDORDER[i - 1].asc == 'asc' ? 1 : -1); break; } } return r; }); } if (grid.pageSize) { grid.total = grid.data.rows.length; var pageData = $.extend(true, {}, DATA); pageData.rows = pageData.rows.slice(grid.pageSize * (grid.page - 1), grid.pageSize * grid.page); grid.pageData = pageData; } else grid.pageData = DATA; grid.flag = true; if (grid.dataSuccess) grid.dataSuccess(grid.pageData); fn(); } else if (grid.url) { var url = grid.url; if (grid.pageSize) { grid.searchData.page = grid.page; grid.searchData.pageSize = grid.pageSize; } //生成排序字符串 if (GRIDORDER.length > 0) { var orderStr = ''; $.each(GRIDORDER, function (_, order) { orderStr += order.code + ' ' + order.asc + ','; }); orderStr = orderStr.substr(0, orderStr.length - 1); grid.searchData.orderString = orderStr; } $.ajax({ url: url, data: grid.searchData, type: 'get', dataType: 'json', beforeSend: function (xhr) { if (CONFIG.token) { xhr.setRequestHeader('Authorization', 'Basic ' + CONFIG.token); } }, success: function (data) { grid.pageData = data; grid.flag = data.flag; grid.total = data.total; if (grid.dataSuccess) grid.dataSuccess(data); fn(); }, error: function (error) { grid.flag = false; fn(); } }); } else { grid.pageData = { rows: [] }; fn(); } } //事件 var events = { //行点击事件 rowClick: function () { var that = $(this); if (that.hasClass('selected')) { if (!grid.singleSelect) { that.removeClass('selected'); if (that.find('td:first :checkbox').length > 0) that.find('td:first :checkbox')[0].checked = false; } if (grid.elem.find('.grid-head').find('th,td').first().find(':checkbox').length > 0) grid.elem.find('.grid-head').find('th,td').first().find(':checkbox')[0].checked = false; } else { that.addClass('selected'); if (that.find('td:first :checkbox').length > 0) { that.find('td:first :checkbox')[0].checked = true; that.find('td:first :checkbox').on('click', function () { that[0].checked = true; }); } if (grid.singleSelect) that.siblings().removeClass('selected').each(function () { if ($(this).find('td:first :checkbox').length > 0) $(this).find('td:first :checkbox')[0].checked = false; }); } if (grid.rowClick) grid.rowClick(grid.pageData.rows[that.index()]); that.addClass('focus'); that.siblings().removeClass('focus'); } //排序 , order: function () { var that = $(this); var ord = that.find('.grid-order'); var ordCode = that.attr('order'); if (ord.hasClass('grid-order-asc')) { ord.removeClass('grid-order-asc').addClass('grid-order-desc'); $.each(GRIDORDER, function (i, item) { if (item.code == ordCode) { GRIDORDER.splice(i, 1); return false; } }); GRIDORDER.push({ code: ordCode, asc: 'desc' }); } else if (ord.hasClass('grid-order-desc')) { ord.removeClass('grid-order-desc'); $.each(GRIDORDER, function (i, item) { if (item.code == ordCode) { GRIDORDER.splice(i, 1); return false; } }); } else { ord.addClass('grid-order-asc'); $.each(GRIDORDER, function (i, item) { if (item.code == ordCode) { GRIDORDER.splice(i, 1); return false; } }); GRIDORDER.push({ code: ordCode, asc: 'asc' }); } fnData(function () { fnBody(CONFIG.render(grid.view, grid.pageData), grid.elem.find('.grid-content')); }); } //全选 , selectAll: function () { var that = $(this); var checked = that[0].checked, trs = grid.elem.find('.grid-body tbody tr'); checked ? trs.addClass('selected') : trs.removeClass('selected'); trs.each(function () { if ($(this).find('td:first :checkbox').length > 0) $(this).find('td:first :checkbox')[0].checked = checked; }); } } //渲染Grid视图 function fnSuccess() { grid.elem.html(''); var content = $('
').appendTo(grid.elem), html = CONFIG.render(grid.view, grid.pageData); fnHeader(html, content); fnBody(html, content); if (grid.success) grid.success(grid.pageData, grid.elem); setTimeout(function () { grid.resize(); }, 100); setTimeout(function () { grid.resize(); },200) $(window).resize(function () { if (grid.elem.parents('div.layui-tab-item').length > 0) { if (grid.elem.parents('div.layui-tab-item').hasClass('layui-show')) { grid.resize(); } } else grid.resize(); }); } //header 处理 function fnHeader(html, content) { var tbHead = content.find('.grid-head'); if (tbHead.length == 0) tbHead = $('
').appendTo(content); tbHead.html(html); tbHead.find('>table').nextAll().remove(); tbHead.find('thead').siblings().empty(); tbHead.find('thead th,thead td').each(function (i) { var that = $(this); /*if (typeof (that.attr('order')) != 'undefined') { that.append('').on('click', events.order); } if (i == 0 && $(this).find(':checkbox').length > 0 && !grid.singleSelect) { that.find(':checkbox').on('click', events.selectAll); }*/ that.html('
' + that.html() + '
'); if (typeof (that.attr('order')) != 'undefined') { that.on('click', events.order).find('.grid-coll').append(''); } if (i == 0 && that.find(':checkbox').length > 0 && !grid.singleSelect) { that.find(':checkbox').on('click', events.selectAll); } }); } //body处理 function fnBody(html, content) { if (!grid.flag) { content.addClass('grid-err').html('获取数据失败'); grid.closeLoading(); return; } var tbHead = content.find('.grid-head').find('table'), tbBody = content.find('.grid-body'); if (tbBody.length == 0) tbBody = $('
').appendTo(content); tbBody.html(html); tbBody.find('>table').prevAll().remove(); tbBody.find('thead th,thead td').each(function () { /*if (typeof ($(this).attr('order')) != 'undefined') $(this).append('');*/ var that = $(this); that.html('
' + that.html() + '
'); if (typeof (that.attr('order')) != 'undefined') { that.find('.grid-coll').append(''); } }); if (tbBody.find('tbody tr').length == 0) tbBody.find('tbody').append(''); var tool = tbBody.find('>.grid-tool').remove(); grid.elem.find('.grid-page').remove(); var pageDom = $('
'); var pages = Math.ceil(grid.total / grid.pageSize); if (pages > 1 || tool.length > 0) { pageDom.appendTo(content); tool.prependTo(pageDom); } if (pages > 1) { layui.laypage({ record: grid.record ? grid.total : 0, cont: pageDom.find('>div'), pages: pages, curr: grid.page, groups: grid.pageGroup, skip: true, first: 1, last: pages, prev: '<', next: '>', jump: function (obj, isFirst) { if (!isFirst) { grid.page = obj.curr; //grid.build(); fnData(function () { fnBody(CONFIG.render(grid.view, grid.pageData), grid.elem.find('.grid-content')); }); } } }); } var trs = tbBody.find('tbody tr'); if (trs.length > 0) { var checkbox = tbHead.find('th').first().find(':checkbox'); trs.on('click', events.rowClick); } tbBody.scroll(function () { RESIZE = { left: $(this).scrollLeft(), top: $(this).scrollTop() }; tbHead.css('margin-left', -RESIZE.left); }); grid.closeLoading(); grid.resize(); //verify(tbBody); } grid.loading = function () { var loading = grid.elem.find('.loading_bg,.loading'); if (loading.length == 0) loading = $('
') .appendTo(grid.elem); loading.show(); } grid.closeLoading = function () { grid.elem.find('.loading_bg,.loading').hide(); } grid.getIndex = function () { var tr = this.elem.find('.grid-body tbody tr.focus'); if (tr.length > 0) return tr.index(); else return -1; } grid.getRow = function () { var index = grid.getIndex(); if (index >= 0) return grid.pageData.rows[index]; else return null; } grid.focus = function (index) { if (index == undefined || index == -1) { grid.elem.find('.grid-body tbody tr.focus').removeClass('focus'); } else { var tr = grid.elem.find('.grid-body tbody tr:eq(' + index + ')').addClass('focus'); tr.siblings('.focus').removeClass('focus'); if (grid.singleSelect) grid.selectIndex(index); else { tr.addClass('selected'); if (tr.find('td:first :checkbox').length > 0) tr.find('td:first :checkbox')[0].checked = true; } } } grid.selectValue = function (v) { var rowid = this.rowid; if (v == undefined) { var rows = this.selectRow(); if (rows == null) return null; if (this.singleSelect) { return rows[rowid]; } else { values = []; $.each(rows, function (_, row) { values.push(row[rowid]); }); return values; } } else { if (this.singleSelect) v = [v]; this.elem.find('tbody tr.selected').each(function () { $(this).removeClass('selected'); if ($(this).find('td:first :checkbox').length > 0) $(this).find('td:first :checkbox')[0].checked = false; }); $.each(grid.pageData.rows, function (i, row) { if (v.indexOf(row[rowid]) != -1) { var tr = grid.elem.find('tbody tr:eq(' + i + ')'); tr.addClass('selected'); if (tr.find('td:first :checkbox').length > 0) tr.find('td:first :checkbox')[0].checked = true; } }); } } grid.selectRow = function () { /*if (values != undefined) { grid.elem.find('.grid-body tbody tr.selected').removeClass('selected').each(function () { if ($(this).find('td:first :checkbox').length > 0) $(this).find('td:first :checkbox')[0].checked = false; }); var keys = grid.keys.split(';'); if (Object.prototype.toString.call(values) == '[object Array]' && !grid.singleSelect) { $.each(values, function (a, value) { $.each(grid.pageData.rows, function (i, r) { var key = ''; $.each(keys, function (j, k) { key += r[k]+';'; }); if (value + ';' == key) { var tr = grid.elem.find('.grid-body tbody tr:eq(' + i + ')'); tr.addClass('selected'); if (tr.find('td:first :checkbox').length > 0) tr.find('td:first :checkbox')[0].checked = true; return false; } }); }); } else { $.each(grid.pageData.rows, function (i, r) { var key = ''; $.each(keys, function (j, k) { key += r[k]+';'; }); if (values + ';' == key) { var tr = grid.elem.find('.grid-body tbody tr:eq(' + i + ')'); tr.addClass('selected'); if (tr.find('td:first :checkbox').length > 0) tr.find('td:first :checkbox')[0].checked = true; return false; } }); } } else {*/ if (!grid.singleSelect) { rows = []; this.elem.find('.grid-body tbody tr').each(function (i) { if ($(this).hasClass('selected')) rows.push(grid.pageData.rows[i]); }); return rows.length > 0 ? rows : null; } else { var tr = this.elem.find('.grid-body tbody tr.selected'); if (tr.length > 0) return grid.pageData.rows[tr.index()]; else return null; } //} } grid.selectIndex = function (index) { if (index != undefined && index >= 0) { grid.elem.find('.grid-body tbody tr.selected').removeClass('selected').each(function () { if ($(this).find('td:first :checkbox').length > 0) $(this).find('td:first :checkbox')[0].checked = false; }); if (Object.prototype.toString.call(index) == '[object Array]' && !grid.singleSelect) { $.each(index, function (i, idx) { var tr = grid.elem.find('.grid-body tbody tr:eq(' + idx + ')'); tr.addClass('selected'); if (tr.find('td:first :checkbox').length > 0) tr.find('td:first :checkbox')[0].checked = true; return false; }); } else { var tr = grid.elem.find('.grid-body tbody tr:eq(' + index + ')'); tr.addClass('selected'); if (tr.find('td:first :checkbox').length > 0) tr.find('td:first :checkbox')[0].checked = true; } } else if (index == undefined) { if (!grid.singleSelect) { rows = []; this.elem.find('.grid-body tbody tr').each(function (i) { if ($(this).hasClass('selected')) rows.push(i); }); return rows.length > 0 ? rows : null; } else { var tr = this.elem.find('.grid-body tbody tr.selected'); if (tr.length > 0) return tr.index(); else return -1; } } } //生成表格行并绑定事件 function rowsDom(rows, op) { if (Object.prototype.toString.call(rows) != '[object Array]') rows = [rows]; var html = CONFIG.render(grid.view, { rows: rows, op: op }); //var content = grid.elem.find('.grid-content'); var trs = $(html).find('tbody tr'); trs.on('click', events.rowClick); //verify(trs); return trs; } function verify(elem) { var flag = true, msg = '', errOthis; var fmVer = form.config.verify; elem.find('*[lay-verify]').each(function () { var othis = $(this), td = othis.parents('td').last(), ver = othis.attr('lay-verify').split('|'), tips='', value = othis.val(); //othis.removeClass(DANGER); $.each(ver, function (_, thisVer) { var isFn = typeof fmVer[thisVer] === 'function'; if (fmVer[thisVer] && (isFn ? tips = fmVer[thisVer](value, othis[0]) : !fmVer[thisVer][0].test(value))) { td.addClass(CSS.danger); flag = false; if (msg == '') msg = tips || fmVer[thisVer][1]; if (!errOthis) errOthis = othis; } }); $(this).on('keyup', function () { td.removeClass(CSS.danger); }); }); if (!flag) { layer.msg(msg, { icon: 5, shift: 6 }); errOthis.select(); } return flag; } grid.insert = function (rows, index) { if (Object.prototype.toString.call(rows) != '[object Array]') rows = [rows]; if (index == undefined || index < 0) { $.each(rows, function (i, row) { grid.pageData.rows.push(row); }); } else { var str = JSON.stringify(rows); str = str.substr(1, str.length - 2); if (index == 0) eval('grid.pageData.rows.unshift(' + str + ')'); else eval('grid.pageData.rows.splice(' + index + ',0,' + str + ')'); } var trs = rowsDom(rows); var tbody = grid.elem.find('.grid-body tbody'); if (index == undefined || index < 0) tbody.append(trs); else if (index == 0) tbody.prepend(trs); else { tbody.find('>tr:eq(' + index + ')').before(trs); } grid.resize(); return trs; } grid.update = function (row, index) { if (index == undefined || index < 0) { //console.log('grid error: index参数错误'); return; } grid.pageData.rows[index] = row; var tr = rowsDom(row); grid.elem.find('.grid-body tbody').find('>tr:eq(' + index + ')').replaceWith(tr); grid.resize(); //grid.selectIndex(index); grid.focus(index); return tr; } grid.delete = function (index) { if (index == undefined) { //console.log('grid error:index参数错误'); return; } else if (Object.prototype.toString.call(index) != '[object Array]') { index = [index]; } for (var i = index.length; i > 0; i--) { grid.pageData.rows.splice(index[i - 1], 1); grid.elem.find('.grid-body tbody').find('>tr:eq(' + index[i - 1] + ')').remove(); } grid.resize(); } //更新表格页脚 grid.foot = function (footData) { var html = CONFIG.render(grid.view, footData); var tfoot = $(html).find('tfoot'); grid.elem.find('.grid-body tfoot').replaceWith(tfoot); grid.resize(); } //编辑行 grid.edit = function (index) { var body = grid.elem.find('.grid-body tbody'); //if (index == undefined) // index = grid.selectIndex(); if (index == undefined || index < 0) { var rowhtml = rowsDom(grid.pageData.rows, 'edit'); body.html(rowhtml); } else { var row = grid.pageData.rows[index]; var rowhtml = rowsDom(row, 'edit'); body.find('>tr:eq(' + index + ')').replaceWith(rowhtml); grid.focus(index); } grid.resize(); } //结束编辑行 grid.endEdit = function (index) { var body = grid.elem.find('.grid-body tbody'); //if (index == undefined) // index = grid.selectIndex(); var row = null; if (index == undefined || index < 0) { if (verify(body)) { body.find('tr').each(function (i, tr) { $(tr).find('*[name]').each(function (_, item) { grid.pageData.rows[i][$(item).attr('name')] = item.value; }); }); row = grid.pageData.rows; var rowhtml = rowsDom(row); body.html(rowhtml); } } else { //erify() var tr = body.find('tr:eq(' + index + ')'); if (verify(tr)) { tr.find('*[name]').each(function (_, item) { grid.pageData.rows[index][$(item).attr('name')] = item.value; }); row = grid.pageData.rows[index]; var rowhtml = rowsDom(row); body.find('>tr:eq(' + index + ')').replaceWith(rowhtml); grid.focus(index); } } grid.resize(); return row; } grid.clear = function () { grid.data = { rows: [] }; grid.build(); } grid.setData = function (data) { grid.data = data; grid.page = 1; grid.build(); } /*New End*/ grid.resize = function () { //grid.elem.find('.grid-body thead').show(); var head = grid.elem.find('.grid-head>table'), body = grid.elem.find('.grid-body>table'); var ths = grid.elem.find('.grid-head th,.grid-head td'); var tbhs = grid.elem.find('.grid-body thead th,.grid-body thead td'); head.css('width', body.width()); tbhs.each(function (i, th) { var w = $(th).find('.grid-coll').width(); $(ths[i]).find('.grid-coll').css('width', w); }); if (grid.elem.hasClass('grid')) { var top = grid.elem.find('.grid-head').height() || 0, bottom = grid.elem.find('.grid-page').height() || 0; grid.elem.find('.grid-body').css({ top: top, bottom: bottom }); if (grid.elem.find('.grid-body table').height() < grid.elem.find('.grid-body').height()) grid.elem.find('.grid-body').css({ bottom: 'auto' }); var gridTop = 0; var prev = grid.elem.prevAll('.grid-position'); if (prev.length == 0) prev = grid.elem.prev(); if (prev.length > 0) { gridTop = prev.height() + prev.position().top + 5; grid.elem.css('top', gridTop); } } var H = grid.elem.find('.grid-body table:first thead').height() || 0; if (H > 0) grid.elem.find('.grid-body table:first').css('margin-top', -H); if (RESIZE.top != 0) grid.elem.find('.grid-body').scrollTop(RESIZE.top); if (RESIZE.left != 0) grid.elem.find('.grid-body').scrollLeft(RESIZE.left); } if (grid.search) { //绑定搜索事件 form.on('submit(' + grid.search + ')', function (data) { grid.page = 1; grid.searchData = data.field; grid.build(); }); } return grid; } }; exports('grid', Grid); layui.link(layui.cache.base + 'css/grid.css', null, 'gridcss'); });