forked from joomla/Component-Builder
374 lines
12 KiB
JavaScript
374 lines
12 KiB
JavaScript
|
(function($, w, undefined) {
|
|||
|
if (w.footable === undefined || w.foobox === null) throw new Error('Please check and make sure footable.js is included in the page and is loaded prior to this script.');
|
|||
|
var defaults = {
|
|||
|
grid: {
|
|||
|
enabled: true,
|
|||
|
data: null,
|
|||
|
template: null, //row html template, use for make a row.
|
|||
|
cols: null, //column define
|
|||
|
items: null, //data items
|
|||
|
url: null, //get data from url
|
|||
|
ajax: null, //paramater for $.ajax
|
|||
|
activeClass: 'active', //add to row selected
|
|||
|
multiSelect: false, //allow select multiple row
|
|||
|
showIndex: false, //show row index
|
|||
|
showCheckbox: false, //show checkbox for select
|
|||
|
showEmptyInfo: false, //when that is not data in table, show a info to notify user
|
|||
|
emptyInfo: '<p class="text-center text-warning">No Data</p>',
|
|||
|
pagination: {
|
|||
|
"page-size": 20,
|
|||
|
"pagination-class": "pagination pagination-centered"
|
|||
|
},
|
|||
|
indexFormatter: function(val, $td, index) {
|
|||
|
return index + 1;
|
|||
|
},
|
|||
|
checkboxFormatter: function(isTop) {
|
|||
|
return '<input type="checkbox" class="' + (isTop ? 'checkAll' : 'check') + '">';
|
|||
|
},
|
|||
|
events: {
|
|||
|
loaded: 'footable_grid_loaded',
|
|||
|
created: 'footable_grid_created',
|
|||
|
removed: 'footable_grid_removed',
|
|||
|
updated: 'footable_grid_updated'
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
function makeTh(col) {
|
|||
|
var $th = $('<th>' + col.title + '</th>');
|
|||
|
if ($.isPlainObject(col.data)) {
|
|||
|
$th.data(col.data);
|
|||
|
}
|
|||
|
if ($.isPlainObject(col.style)) {
|
|||
|
$th.css(col.style);
|
|||
|
}
|
|||
|
if (col.className) {
|
|||
|
$th.addClass(col.className);
|
|||
|
}
|
|||
|
return $th;
|
|||
|
}
|
|||
|
|
|||
|
function initThead($table, options) {
|
|||
|
var $thead = $table.find('thead');
|
|||
|
if ($thead.size() === 0) {
|
|||
|
$thead = $('<thead>').appendTo($table);
|
|||
|
}
|
|||
|
var $row = $('<tr>').appendTo($thead);
|
|||
|
for (var i = 0, len = options.cols.length; i < len; i++) {
|
|||
|
$row.append(makeTh(options.cols[i]));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function initTBody($table) {
|
|||
|
var $tbody = $table.find('tbody');
|
|||
|
if ($tbody.size() === 0) {
|
|||
|
$tbody = $('<tbody>').appendTo($table);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function initPagination($table, cols, options) {
|
|||
|
if (options) {
|
|||
|
$table.attr("data-page-size", options['page-size']);
|
|||
|
var $tfoot = $table.find('tfoot');
|
|||
|
if ($tfoot.size() === 0) {
|
|||
|
$tfoot = $('<tfoot class="hide-if-no-paging"></tfoot>').appendTo($table);
|
|||
|
}
|
|||
|
$tfoot.append('<tr><td colspan=' + cols.length + '></td></tr>');
|
|||
|
var $pagination = $("<div>").appendTo($tfoot.find("tr:last-child td"));
|
|||
|
$pagination.addClass(options['pagination-class']);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function setToggleColumn(cols) {
|
|||
|
var toggleColumn = cols[0];
|
|||
|
for (var i = 0, len = cols.length; i < len; i++) {
|
|||
|
var col = cols[i];
|
|||
|
if (col.data && (col.data.toggle === true || col.data.toggle === "true")) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
toggleColumn.data = $.extend(toggleColumn.data, {
|
|||
|
toggle: true
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
function makeEmptyInfo($table, cols, emptyInfo) {
|
|||
|
if ($table.find("tr.emptyInfo").size() === 0) {
|
|||
|
$table.find('tbody').append('<tr class="emptyInfo"><td colspan="' + cols.length + '">' + emptyInfo + '</td></tr>');
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function updateRowIndex($tbody, $newRow, detailClass, offset) {
|
|||
|
//update rows index
|
|||
|
$tbody.find('tr:not(.' + detailClass + ')').each(function() {
|
|||
|
var $row = $(this),
|
|||
|
index = $newRow.data('index'),
|
|||
|
oldIndex = parseInt($row.data('index'), 0),
|
|||
|
newIndex = oldIndex + offset;
|
|||
|
if (oldIndex >= index && this !== $newRow.get(0)) {
|
|||
|
$row.attr('data-index', newIndex).data('index', newIndex);
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
function Grid() {
|
|||
|
var grid = this;
|
|||
|
grid.name = 'Footable Grid';
|
|||
|
grid.init = function(ft) {
|
|||
|
var toggleClass = ft.options.classes.toggle;
|
|||
|
var detailClass = ft.options.classes.detail;
|
|||
|
var options = ft.options.grid;
|
|||
|
if (!options.cols) return;
|
|||
|
grid.footable = ft;
|
|||
|
var $table = $(ft.table);
|
|||
|
$table.data('grid', grid);
|
|||
|
if ($.isPlainObject(options.data)) {
|
|||
|
$table.data(options.data);
|
|||
|
}
|
|||
|
grid._items = [];
|
|||
|
setToggleColumn(options.cols);
|
|||
|
if (options.showCheckbox) {
|
|||
|
options.multiSelect = true;
|
|||
|
options.cols.unshift({
|
|||
|
title: options.checkboxFormatter(true),
|
|||
|
name: '',
|
|||
|
data: {
|
|||
|
"sort-ignore": true
|
|||
|
},
|
|||
|
formatter: options.checkboxFormatter
|
|||
|
});
|
|||
|
}
|
|||
|
if (options.showIndex) {
|
|||
|
options.cols.unshift({
|
|||
|
title: '#',
|
|||
|
name: 'index',
|
|||
|
data: {
|
|||
|
"sort-ignore": true
|
|||
|
},
|
|||
|
formatter: options.indexFormatter
|
|||
|
});
|
|||
|
}
|
|||
|
initThead($table, options);
|
|||
|
initTBody($table);
|
|||
|
initPagination($table, options.cols, options.pagination);
|
|||
|
$table.off('.grid').on({
|
|||
|
'footable_initialized.grid': function(e) {
|
|||
|
if (options.url || options.ajax) {
|
|||
|
$.ajax(options.ajax || {
|
|||
|
url: options.url
|
|||
|
}).then(function(resp) {
|
|||
|
grid.newItem(resp);
|
|||
|
ft.raise(options.events.loaded);
|
|||
|
}, function(jqXHR) {
|
|||
|
throw 'load data from ' + (options.url || options.ajax.url) + ' fail';
|
|||
|
});
|
|||
|
} else {
|
|||
|
grid.newItem(options.items || []);
|
|||
|
ft.raise(options.events.loaded);
|
|||
|
}
|
|||
|
},
|
|||
|
'footable_sorted.grid footable_grid_created.grid footable_grid_removed.grid': function(event) {
|
|||
|
if (options.showIndex && grid.getItem().length > 0) {
|
|||
|
$table.find('tbody tr:not(.' + detailClass + ')').each(function(index) {
|
|||
|
var $td = $(this).find('td:first');
|
|||
|
$td.html(options.indexFormatter(null, $td, index));
|
|||
|
});
|
|||
|
}
|
|||
|
},
|
|||
|
'footable_redrawn.grid footable_row_removed.grid': function(event) {
|
|||
|
if (grid.getItem().length === 0 && options.showEmptyInfo) {
|
|||
|
makeEmptyInfo($table, options.cols, options.emptyInfo);
|
|||
|
}
|
|||
|
}
|
|||
|
}).on({
|
|||
|
'click.grid': function(event) {
|
|||
|
if ($(event.target).closest('td').find('>.' + toggleClass).size() > 0) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
var $tr = $(event.currentTarget);
|
|||
|
if ($tr.hasClass(detailClass)) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
if (!options.multiSelect && !$tr.hasClass(options.activeClass)) {
|
|||
|
$table.find('tbody tr.' + options.activeClass).removeClass(options.activeClass);
|
|||
|
}
|
|||
|
$tr.toggleClass(options.activeClass);
|
|||
|
if (options.showCheckbox) {
|
|||
|
$tr.find('input:checkbox.check').prop('checked', function(index, val) {
|
|||
|
if (event.target === this) {
|
|||
|
return val;
|
|||
|
}
|
|||
|
return !val;
|
|||
|
});
|
|||
|
}
|
|||
|
ft.toggleDetail($tr);
|
|||
|
}
|
|||
|
}, 'tbody tr').on('click.grid', 'thead input:checkbox.checkAll', function(event) {
|
|||
|
var checked = !! event.currentTarget.checked;
|
|||
|
if (checked) {
|
|||
|
$table.find('tbody tr').addClass(options.activeClass);
|
|||
|
} else {
|
|||
|
$table.find('tbody tr').removeClass(options.activeClass);
|
|||
|
}
|
|||
|
$table.find('tbody input:checkbox.check').prop('checked', checked);
|
|||
|
});
|
|||
|
};
|
|||
|
/**
|
|||
|
* get selected rows index;
|
|||
|
*/
|
|||
|
grid.getSelected = function() {
|
|||
|
var options = grid.footable.options.grid,
|
|||
|
$selected = $(grid.footable.table).find('tbody>tr.' + options.activeClass);
|
|||
|
return $selected.map(function() {
|
|||
|
return $(this).data('index');
|
|||
|
});
|
|||
|
};
|
|||
|
/**
|
|||
|
* get row's data by index
|
|||
|
*/
|
|||
|
grid.getItem = function(index) {
|
|||
|
if (index !== undefined) {
|
|||
|
if ($.isArray(index)) {
|
|||
|
return $.map(index, function(item) {
|
|||
|
return grid._items[item];
|
|||
|
});
|
|||
|
}
|
|||
|
return grid._items[index];
|
|||
|
}
|
|||
|
return grid._items;
|
|||
|
};
|
|||
|
|
|||
|
function makeCell(col, value, index) {
|
|||
|
var $td = $('<td>');
|
|||
|
if (col.formatter) {
|
|||
|
$td.html(col.formatter(value, $td, index));
|
|||
|
} else {
|
|||
|
$td.html(value || '');
|
|||
|
}
|
|||
|
return $td;
|
|||
|
}
|
|||
|
grid._makeRow = function(item, index) {
|
|||
|
var options = grid.footable.options.grid;
|
|||
|
var $row;
|
|||
|
if ($.isFunction(options.template)) {
|
|||
|
$row = $(options.template($.extend({}, {
|
|||
|
__index: index
|
|||
|
}, item)));
|
|||
|
} else {
|
|||
|
$row = $('<tr>');
|
|||
|
for (var i = 0, len = options.cols.length; i < len; i++) {
|
|||
|
var col = options.cols[i];
|
|||
|
$row.append(makeCell(col, item[col.name] || '', index));
|
|||
|
}
|
|||
|
}
|
|||
|
$row.attr('data-index', index);
|
|||
|
return $row;
|
|||
|
};
|
|||
|
/**
|
|||
|
* create rows by js object
|
|||
|
*/
|
|||
|
grid.newItem = function(item, index, wait) {
|
|||
|
var $tbody = $(grid.footable.table).find('tbody');
|
|||
|
var detailClass = grid.footable.options.classes.detail;
|
|||
|
$tbody.find('tr.emptyInfo').remove();
|
|||
|
if ($.isArray(item)) {
|
|||
|
for (var atom;
|
|||
|
(atom = item.pop());) {
|
|||
|
grid.newItem(atom, index, true);
|
|||
|
}
|
|||
|
grid.footable.redraw();
|
|||
|
grid.footable.raise(grid.footable.options.grid.events.created, {
|
|||
|
item: item,
|
|||
|
index: index
|
|||
|
});
|
|||
|
return;
|
|||
|
}
|
|||
|
if (!$.isPlainObject(item)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
var $tr, len = grid._items.length;
|
|||
|
if (index === undefined || index < 0 || index > len) {
|
|||
|
$tr = grid._makeRow(item, len++);
|
|||
|
grid._items.push(item);
|
|||
|
$tbody.append($tr);
|
|||
|
} else {
|
|||
|
$tr = grid._makeRow(item, index);
|
|||
|
if (index === 0) {
|
|||
|
grid._items.unshift(item);
|
|||
|
$tbody.prepend($tr);
|
|||
|
} else {
|
|||
|
var $before = $tbody.find('tr[data-index=' + (index - 1) + ']');
|
|||
|
grid._items.splice(index, 0, item);
|
|||
|
if ($before.data('detail_created') === true) {
|
|||
|
$before = $before.next();
|
|||
|
}
|
|||
|
$before.after($tr);
|
|||
|
}
|
|||
|
updateRowIndex($tbody, $tr, detailClass, 1);
|
|||
|
}
|
|||
|
if (!wait) {
|
|||
|
grid.footable.redraw();
|
|||
|
grid.footable.raise(grid.footable.options.grid.events.created, {
|
|||
|
item: item,
|
|||
|
index: index
|
|||
|
});
|
|||
|
}
|
|||
|
};
|
|||
|
/**
|
|||
|
* update row by js object
|
|||
|
*/
|
|||
|
grid.setItem = function(item, index) {
|
|||
|
if (!$.isPlainObject(item)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
var $tbody = $(grid.footable.table).find('tbody'),
|
|||
|
$newTr = grid._makeRow(item, index);
|
|||
|
$.extend(grid._items[index], item);
|
|||
|
var $tr = $tbody.find('tr').eq(index);
|
|||
|
$tr.html($newTr.html());
|
|||
|
grid.footable.redraw();
|
|||
|
grid.footable.raise(grid.footable.options.grid.events.updated, {
|
|||
|
item: item,
|
|||
|
index: index
|
|||
|
});
|
|||
|
};
|
|||
|
/**
|
|||
|
* remove rows by index
|
|||
|
*/
|
|||
|
grid.removeItem = function(index) {
|
|||
|
var $tbody = $(grid.footable.table).find('tbody');
|
|||
|
var detailClass = grid.footable.options.classes.detail;
|
|||
|
var result = [];
|
|||
|
if ($.isArray(index)) {
|
|||
|
for (var i;
|
|||
|
(i = index.pop());) {
|
|||
|
result.push(grid.removeItem(i));
|
|||
|
}
|
|||
|
grid.footable.raise(grid.footable.options.grid.events.removed, {
|
|||
|
item: result,
|
|||
|
index: index
|
|||
|
});
|
|||
|
return result;
|
|||
|
}
|
|||
|
if (index === undefined) {
|
|||
|
$tbody.find('tr').each(function() {
|
|||
|
result.push(grid._items.shift());
|
|||
|
grid.footable.removeRow(this);
|
|||
|
});
|
|||
|
} else {
|
|||
|
var $tr = $tbody.find('tr[data-index=' + index + ']');
|
|||
|
result = grid._items.splice(index, 1)[0];
|
|||
|
grid.footable.removeRow($tr);
|
|||
|
//update rows index
|
|||
|
updateRowIndex($tbody, $tr, detailClass, -1);
|
|||
|
}
|
|||
|
grid.footable.raise(grid.footable.options.grid.events.removed, {
|
|||
|
item: result,
|
|||
|
index: index
|
|||
|
});
|
|||
|
return result;
|
|||
|
};
|
|||
|
}
|
|||
|
w.footable.plugins.register(Grid, defaults);
|
|||
|
})(jQuery, window);
|