/*! * ZUI - v1.2.0 - 2014-11-20 * http://zui.sexy * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2014 cnezsoft.com; Licensed MIT */ /* ======================================================================== * ZUI: datatable.js * http://zui.sexy * ======================================================================== * Copyright (c) 2014 cnezsoft.com; Licensed MIT * ======================================================================== */ (function($) { 'use strict'; var name = 'zui.datatable'; 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') || $.uuid()); } else { this.$datatable = this.$.addClass('datatable'); if (this.$.attr('id')) { this.id = this.$.attr('id'); } else { this.id = 'datatable-' + $.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, // Sort options sortable: false, // enable sorter // storage storage: true, // enable storage // fixed header of columns fixedHeader: true, // 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', // 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'; } this.options = options; }; // Load data form options or table dom DataTable.prototype.load = function(data) { var options = this.options, cols; 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, $th, $tr, $td, row, $t = this.$table; $t.find('thead > 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') }, $th.data())); }); $t.find('tbody > 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); row.data.push($.extend( { cssClass: $td.attr('class'), css: $td.attr('style'), text: $td.html() }, $td.data())); }); rows.push(row); }); var $tfoot = $t.find('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 }); $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(); $rightRow = $leftRow.clone(); rowColLen = row.data.length; for (i = 0; i < rowColLen; ++i) { rowCol = row.data[i]; $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 }; row.data[i] = rowCol; } $td = $(''); $td.html(rowCol.text) .addClass(rowCol.cssClass) .addClass(cols[i].colClass) .attr( { 'data-row' : r, 'data-index' : i, 'data-flex' : false, 'data-type' : cols[i].type, style : rowCol.css }); $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($('