/*!
* jQuery appendGrid v1.3.1
* https://appendgrid.apphb.com/
*
* Copyright 2014 Albert L.
* Dual licensed under the LGPL (http://www.gnu.org/licenses/lgpl.html)
* and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
*
* Depends:
* jQuery v1.9.1+
* jquery UI v1.10.2+
*/
(function ($) {
// The default initial options.
var _defaultInitOptions = {
// The text as table caption, set null to disable caption generation.
caption: null,
// The total number of empty rows generated when init the grid. This will be ignored if `initData` is assigned.
initRows: 3,
// An array of data to be filled after initialized the grid.
initData: null,
// Array of column options.
columns: null,
// Labels or messages used in grid.
i18n: null,
// The ID prefix of controls generated inside the grid. Table ID will be used if not defined.
idPrefix: null,
// Enable row dragging by using jQuery UI sortable on grid rows.
rowDragging: false,
// Hide the buttons at the end of rows or bottom of grid.
hideButtons: null,
// Hide the row number column.
hideRowNumColumn: false,
// The extra class names for buttons.
buttonClasses: null,
// Adding extra button(s) at the end of rows.
customRowButtons: null,
// Adding extra button(s) at the bottom of grid.
customFooterButtons: null,
// The callback function to be triggered after data loaded to grid.
dataLoaded: null,
// The callback function to be triggered after new row appended.
afterRowAppended: null,
// The callback function to be triggered after new row inserted.
afterRowInserted: null,
// The callback function to be triggered after grid row swapped.
afterRowSwapped: null,
// The callback function to be triggered before grid row remove.
beforeRowRemove: null,
// The callback function to be triggered after grid row removed.
afterRowRemoved: null
};
// Default column options.
var _defaultColumnOptions = {
// Type of column control.
type: 'text',
// Name of column.
name: null,
// Default value.
value: null,
// Display text on the header section.
display: null,
// Extra CSS setting to be added to display text.
displayCss: null,
// Extra CSS setting to be added to the control container table cell.
cellCss: null,
// Extra attributes to be added to the control.
ctrlAttr: null,
// Extra properties to be added to the control.
ctrlProp: null,
// Extra CSS to be added to the control.
ctrlCss: null,
// Extra name of class to be added to the control.
ctrlClass: null,
// The available option for building `select` type control.
ctrlOptions: null,
// Options for initalize jQuery UI widget.
uiOption: null,
// Options for initalize jQuery UI tooltip.
uiTooltip: null,
// Callback function to build custom type control.
customBuilder: null,
// Callback function to get control value.
customGetter: null,
// Callback function to set control value.
customSetter: null,
// The `OnClick` event callback of control.
onClick: null,
// The `OnChange` event callback of control.
onChange: null
};
var _systemMessages = {
noColumnInfo: 'Cannot initial grid without column information!',
elemNotTable: 'Cannot initial grid on element other than TABLE!',
notInit: '`appendGrid` does not initialized',
getValueMultiGrid: 'Cannot get values on multiple grid',
notSupportMethod: 'Method is not supported by `appendGrid`: '
};
var _defaultTextResources = {
append: 'Append Row',
removeLast: 'Remove Last Row',
insert: 'Insert Row Above',
remove: 'Remove Current Row',
moveUp: 'Move Up',
moveDown: 'Move Down',
rowDrag: 'Sort Row',
rowEmpty: 'This Grid Is Empty'
};
var _defaultButtonClasses = { append: null, removeLast: null, insert: null, remove: null, moveUp: null, moveDown: null, rowDrag: null };
var _defaultHideButtons = { append: false, removeLast: false, insert: false, remove: false, moveUp: false, moveDown: false };
var _methods = {
init: function (options) {
var target = this;
var tbWhole, tbHead, tbBody, tbFoot, tbRow, tbCell;
if (target.length > 0) {
// Check mandatory paramters included
if (!$.isArray(options.columns) || options.columns.length == 0) {
alert(_systemMessages.noColumnInfo);
return target;
}
// Check target element is table or not
tbWhole = target[0];
if (isEmpty(tbWhole.tagName) || tbWhole.tagName != 'TABLE') {
alert(_systemMessages.elemNotTable);
return target;
}
// Generate settings
var settings = $.extend({}, _defaultInitOptions, options);
// Add internal settings
$.extend(settings, {
//The UniqueIndex accumulate counter.
_uniqueIndex: 0,
// The row order array.
_rowOrder: [],
// Indicate data is loaded or not.
_isDataLoaded: false,
// Visible column count for internal calculation.
_visibleCount: 0,
// Total colSpan count after excluding `hideRowNumColumn` and not generating last column.
_finalColSpan: 0,
// Indicate to hide last column or not
_hideLastColumn: false
});
// Labels or messages used in grid.
if ($.isPlainObject(options.i18n))
settings._i18n = $.extend({}, _defaultTextResources, options.i18n);
else
settings._i18n = $.extend({}, _defaultTextResources);
// The extra class names for buttons.
if ($.isPlainObject(options.buttonClasses))
settings._buttonClasses = $.extend({}, _defaultButtonClasses, options.buttonClasses);
else
settings._buttonClasses = $.extend({}, _defaultButtonClasses);
// Make sure the `hideButtons` setting defined
if ($.isPlainObject(options.hideButtons))
settings.hideButtons = $.extend({}, _defaultHideButtons, options.hideButtons);
else
settings.hideButtons = $.extend({}, _defaultHideButtons);
// Check `idPrefix` is defined
if (isEmpty(settings.idPrefix)) {
// Check table ID defined
if (isEmpty(tbWhole.id) || tbWhole.id == '') {
// Generate an ID using current time
settings.idPrefix = 'ag' + new Date().getTime();
}
else {
settings.idPrefix = tbWhole.id;
}
}
// Create thead and tbody
tbHead = document.createElement('thead');
tbHead.className = 'ui-widget-header';
tbBody = document.createElement('tbody');
tbBody.className = 'ui-widget-content';
tbFoot = document.createElement('tfoot');
tbFoot.className = 'ui-widget-header';
// Remove existing content and append new thead and tbody
$(tbWhole).empty().addClass('appendGrid ui-widget').append(tbHead, tbBody, tbFoot);
// Handle header row
tbRow = tbHead.insertRow(-1);
if (!settings.hideRowNumColumn) {
tbCell = tbRow.insertCell(-1);
tbCell.className = 'ui-widget-header';
}
// Prepare column information and add column header
for (var z = 0; z < settings.columns.length; z++) {
// Assign default setting
var columnOpt = $.extend({}, _defaultColumnOptions, settings.columns[z]);
settings.columns[z] = columnOpt;
// Skip hidden
if (settings.columns[z].type != 'hidden') {
settings._visibleCount++;
tbCell = tbRow.insertCell(-1);
tbCell.className = 'ui-widget-header';
$(tbCell).text(settings.columns[z].display);
if (settings.columns[z].displayCss) $(tbCell).css(settings.columns[z].displayCss);
}
}
// Check to hide last column or not
if (settings.hideButtons.insert && settings.hideButtons.remove
&& settings.hideButtons.moveUp && settings.hideButtons.moveDown
&& (!$.isArray(settings.customRowButtons) || settings.customRowButtons.length == 0)) {
settings._hideLastColumn = true;
}
// Calculate the `_finalColSpan` value
settings._finalColSpan = settings._visibleCount;
if (!settings.hideRowNumColumn) settings._finalColSpan++;
if (!settings._hideLastColumn) settings._finalColSpan++;
// Generate last column header if needed
if (!settings._hideLastColumn) {
tbCell = tbRow.insertCell(-1);
tbCell.className = 'ui-widget-header';
}
// Add caption when defined
if (settings.caption) {
tbRow = tbHead.insertRow(0);
tbCell = tbRow.insertCell(-1);
tbCell.className = 'ui-state-active caption';
tbCell.colSpan = settings._finalColSpan;
$(tbCell).text(settings.caption);
}
// Handle footer row
tbRow = tbFoot.insertRow(-1);
tbCell = tbRow.insertCell(-1);
tbCell.colSpan = settings._finalColSpan;
$('').attr({
type: 'hidden',
id: settings.idPrefix + '_rowOrder',
name: settings.idPrefix + '_rowOrder'
}).appendTo(tbCell);
// Make row invisible if all buttons are hidden
if (settings.hideButtons.append && settings.hideButtons.removeLast
&& (!$.isArray(settings.customFooterButtons) || settings.customFooterButtons.length == 0)) {
tbRow.style.display = 'none';
} else {
if (!settings.hideButtons.append) {
$('').addClass('append', settings._buttonClasses.append).attr({ type: 'button', title: settings._i18n.append })
.button({ icons: { primary: 'ui-icon-plusthick' }, text: false }).click(function () {
insertRow(tbWhole, 1, null, null);
}).appendTo(tbCell);
}
if (!settings.hideButtons.removeLast) {
$('').addClass('removeLast', settings._buttonClasses.removeLast).attr({ type: 'button', title: settings._i18n.removeLast })
.button({ icons: { primary: 'ui-icon-closethick' }, text: false }).click(function () {
removeRow(tbWhole, null, this.value, false);
}).appendTo(tbCell);
}
if (settings.customFooterButtons && settings.customFooterButtons.length) {
// Add front buttons
for (var y = settings.customFooterButtons.length - 1; y >= 0; y--) {
var buttonCfg = settings.customFooterButtons[y];
if (buttonCfg && buttonCfg.uiButton && buttonCfg.click && buttonCfg.atTheFront) {
$(tbCell).prepend(makeCustomBottomButton(tbWhole, buttonCfg));
}
}
// Add end buttons
for (var y = 0; y < settings.customFooterButtons.length; y++) {
var buttonCfg = settings.customFooterButtons[y];
if (buttonCfg && buttonCfg.uiButton && buttonCfg.click && !buttonCfg.atTheFront) {
$(tbCell).append(makeCustomBottomButton(tbWhole, buttonCfg));
}
}
}
}
// Enable dragging
if (settings.rowDragging) {
$(tbBody).sortable({
axis: 'y',
containment: tbWhole,
handle: '.rowDrag',
helper: function (e, tr) {
var org = tr.children();
var helper = tr.clone();
helper.children().each(function (index) {
$(this).width(org.eq(index).width());
});
return helper;
},
update: function (event, ui) {
var uniqueIndex = ui.item[0].id.substring(ui.item[0].id.lastIndexOf('_') + 1);
var tbRowIndex = ui.item[0].rowIndex - $('tr', tbHead).length;
gridRowDragged(tbWhole, ui.originalPosition.top > ui.position.top, uniqueIndex, tbRowIndex);
}
});
}
// Save options
$(tbWhole).data('appendGrid', settings);
if ($.isArray(options.initData)) {
// Load data if initData is array
loadData(tbWhole, options.initData, true);
} else {
// Add empty rows
$(tbWhole).appendGrid('appendRow', settings.initRows);
}
// Show no rows in grid
if (settings._rowOrder.length == 0) {
var empty = $('