/*! * ZUI: 数据表格 - v1.9.1 - 2019-05-10 * http://zui.sexy * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2019 cnezsoft.com; Licensed MIT */ /* ======================================================================== * ZUI: datatable.js * http://zui.sexy * ======================================================================== * Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT * ======================================================================== */ (function($) { 'use strict'; var name = 'zui.datatable'; var store = $.zui.store; /** * Datatable class * * @param object element DOM element or jquery element * @param object options Datatable options */ var DataTable = function(element, options) { this.name = name; this.$ = $(element); this.isTable = (this.$[0].tagName === 'TABLE'); this.firstShow = true; if(this.isTable) { this.$table = this.$; this.id = 'datatable-' + (this.$.attr('id') || $.zui.uuid()); } else { this.$datatable = this.$.addClass('datatable'); if(this.$.attr('id')) { this.id = this.$.attr('id'); } else { this.id = 'datatable-' + $.zui.uuid(); this.$.attr('id', this.id); } } this.getOptions(options); this.load(); this.callEvent('ready'); }; // default options DataTable.DEFAULTS = { // Check options checkable: false, // added check icon to the head of rows checkByClickRow: true, // change check status by click anywhere on a row checkedClass: 'active', // apply CSS class to an checked row checkboxName: null, selectable: true, // Sort options sortable: false, // enable sorter // storage storage: true, // enable storage // fixed header of columns fixedHeader: false, // fixed header fixedHeaderOffset: 0, // set top offset of header when fixed fixedLeftWidth: '30%', // set left width after first render fixedRightWidth: '30%', // set right width after first render flexHeadDrag: true, // scroll flexarea by drag header scrollPos: 'in', // scroll bar position: 'out' | 'in' // hover effection rowHover: true, // apply hover effection to row colHover: true, // apply hover effection to head hoverClass: 'hover', colHoverClass: 'col-hover', // Fix cell height fixCellHeight: true, // Merge rows mergeRows: false, // Merge rows // custom columns size // customizable: false, // enable customizable minColWidth: 20, // min width of columns minFixedLeftWidth: 200, // min left width minFixedRightWidth: 200, // min right width minFlexAreaWidth: 200 // min flexarea width }; // Get options DataTable.prototype.getOptions = function(options) { var $e = this.$; options = $.extend({}, DataTable.DEFAULTS, this.$.data(), options); options.tableClass = options.tableClass || ''; options.tableClass = ' ' + options.tableClass + ' table-datatable'; $.each(['bordered', 'condensed', 'striped', 'condensed', 'fixed'], function(idx, cls) { cls = 'table-' + cls; if($e.hasClass(cls)) options.tableClass += ' ' + cls; }); if($e.hasClass('table-hover') || options.rowHover) { options.tableClass += ' table-hover'; } if(!options.checkable || !$.fn.selectable) options.selectable = false; this.options = options; }; // Load data form options or table dom DataTable.prototype.load = function(data) { var options = this.options, cols; if($.isFunction(data)) { data = data(this.data, this); data.keepSort = true; } else if($.isPlainObject(data)) { this.data = data; } else if(typeof data === 'string') { var $table = $(data); if($table.length) { this.$table = $table.first(); this.$table.data(name, this); this.isTable = true; } data = null; } else { data = options.data; } if(!data) { if(this.isTable) { data = { cols: [], rows: [] }; cols = data.cols; var rows = data.rows, i, $th, $tr, $td, row, $t = this.$table, colSpan; $t.children('thead').children('tr:first').children('th').each(function() { $th = $(this); cols.push($.extend({ text: $th.html(), flex: false || $th.hasClass('flex-col'), width: 'auto', cssClass: $th.attr('class'), css: $th.attr('style'), type: 'string', ignore: $th.hasClass('ignore'), sort: !$th.hasClass('sort-disabled'), mergeRows: $th.attr('merge-rows'), title: $th.attr('title') }, $th.data())); }); $t.children('tbody').children('tr').each(function() { $tr = $(this); row = $.extend({ data: [], checked: false, cssClass: $tr.attr('class'), css: $tr.attr('style'), id: $tr.attr('id') }, $tr.data()); $tr.children('td').each(function() { $td = $(this); colSpan = $td.attr('colspan') || 1; row.data.push($.extend({ cssClass: $td.attr('class'), css: $td.attr('style'), text: $td.html(), colSpan: colSpan, title: $td.attr('title') }, $td.data())); if(colSpan > 1) { for(i = 1; i < colSpan; i++) { row.data.push({ empty: true }); } } }); rows.push(row); }); var $tfoot = $t.children('tfoot'); if($tfoot.length) { data.footer = $('
').append($tfoot); } } else { throw new Error('No data avaliable!'); } } data.flexStart = -1; data.flexEnd = -1; cols = data.cols; data.colsLength = cols.length; for(var i = 0; i < data.colsLength; ++i) { var col = cols[i]; if(col.flex) { if(data.flexStart < 0) { data.flexStart = i; } data.flexEnd = i; } } if(data.flexStart === 0 && data.flexEnd === data.colsLength) { data.flexStart = -1; data.flexEnd = -1; } data.flexArea = data.flexStart >= 0; data.fixedRight = data.flexEnd >= 0 && data.flexEnd < (data.colsLength - 1); data.fixedLeft = data.flexStart > 0; if(data.flexStart < 0 && data.flexEnd < 0) { data.fixedLeft = true; data.flexStart = data.colsLength; data.flexEnd = data.colsLength; } this.data = data; this.callEvent('afterLoad', { data: data }); this.render(); }; // Render datatable DataTable.prototype.render = function() { var that = this; var $datatable = that.$datatable || (that.isTable ? $('
') : that.$datatable), options = that.options, data = that.data, cols = that.data.cols, rows = that.data.rows; var checkable = options.checkable, $left, i, $right, $flex, dataRowSpan = '
', dataHeadSpan = '
'; $datatable.children('.datatable-head, .datatable-rows, .scroll-wrapper').remove(); // Set css class to datatable by options $datatable.toggleClass('sortable', options.sortable); // $datatable.toggleClass('customizable', options.customizable); // Head var $head = $('
'), $tr, $th, col; $left = $(''); $right = $(''); $flex = $(''); for(i = 0; i < cols.length; i++) { col = cols[i]; $tr = i < data.flexStart ? $left : ((i >= data.flexStart && i <= data.flexEnd) ? $flex : $right); if(i === 0 && checkable) { $tr.append(''); } if(col.ignore) continue; $th = $(''); // set sort class $th.toggleClass('sort-down', col.sort === 'down') .toggleClass('sort-up', col.sort === 'up') .toggleClass('sort-disabled', col.sort === false); $th.addClass(col.cssClass) .addClass(col.colClass) .html(col.text) .attr({ 'data-index': i, 'data-type': col.type, style: col.css, title: col.title, }).css('width', col.width); $tr.append($th); } var $headSpan; if(data.fixedLeft) { $headSpan = $(dataHeadSpan); $headSpan.addClass('fixed-left') // .find('.datatable-wrapper') // .append('
') .find('table') .addClass(options.tableClass) .find('thead').append($left); $head.append($headSpan); } if(data.flexArea) { $headSpan = $(dataHeadSpan); $headSpan.addClass('flexarea') .find('.datatable-wrapper') .append('
') .find('table') .addClass(options.tableClass) .find('thead').append($flex); $head.append($headSpan); } if(data.fixedRight) { $headSpan = $(dataHeadSpan); $headSpan.addClass('fixed-right') // .find('.datatable-wrapper') // .append('
') .find('table') .addClass(options.tableClass) .find('thead').append($right); $head.append($headSpan); } $datatable.append($head); // Rows var $rows = $('
'); var $leftRow, $flexRow, $rightRow, // $tr, $td, $cTd, row, rowLen = rows.length, rowCol, rowColLen; $left = $(''); $right = $(''); $flex = $(''); for(var r = 0; r < rowLen; ++r) { row = rows[r]; // format row if(typeof row.id === 'undefined') { row.id = r; } row.index = r; $leftRow = $(''); $leftRow.addClass(row.cssClass) .toggleClass(options.checkedClass, !!row.checked) .attr({ 'data-index': r, 'data-id': row.id }); $flexRow = $leftRow.clone().addClass('datatable-row-flex'); $rightRow = $leftRow.clone().addClass('datatable-row-right'); $leftRow.addClass('datatable-row-left'); rowColLen = row.data.length; for(i = 0; i < rowColLen; ++i) { rowCol = row.data[i]; if(i > 0 && rowCol.empty) { continue; } $tr = i < data.flexStart ? $leftRow : ((i >= data.flexStart && i <= data.flexEnd) ? $flexRow : $rightRow); if(i === 0 && checkable) { $cTd = $(''); if(options.checkboxName) { $cTd.append(''); } $tr.append($cTd); } if(cols[i].ignore) continue; // format row column if(!$.isPlainObject(rowCol)) { rowCol = { text: rowCol, row: r, index: i }; } else { rowCol.row = r; rowCol.index = i; } row.data[i] = rowCol; $td = $(''); $td.html(rowCol.text) .addClass(rowCol.cssClass) .addClass(cols[i].colClass) .attr('colspan', rowCol.colSpan) .attr({ 'data-row': r, 'data-index': i, 'data-flex': false, 'data-type': cols[i].type, style: rowCol.css, title: rowCol.title || '' }).css('width', cols[i].width); $tr.append($td); } $left.append($leftRow); $flex.append($flexRow); $right.append($rightRow); } var $rowSpan; if(data.fixedLeft) { $rowSpan = $(dataRowSpan); $rowSpan.addClass('fixed-left') .find('table') .addClass(options.tableClass) .append($left); $rows.append($rowSpan); } if(data.flexArea) { $rowSpan = $(dataRowSpan); $rowSpan.addClass('flexarea') .find('.datatable-wrapper') .append('
') .find('table') .addClass(options.tableClass) .append($flex); $rows.append($rowSpan); } if(data.fixedRight) { $rowSpan = $(dataRowSpan); $rowSpan.addClass('fixed-right') .find('table') .addClass(options.tableClass) .append($right); $rows.append($rowSpan); } $datatable.append($rows); if(data.flexArea) { $datatable.append('
'); } var $oldFooter = $datatable.children('.datatable-footer').detach(); if(data.footer) { $datatable.append($('