/*!
* 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('