mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-26 14:40:29 +01:00
1111 lines
38 KiB
JavaScript
1111 lines
38 KiB
JavaScript
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
var DataTableColumnFilter = (function ($) {
|
||
|
"use strict";
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
storage: {
|
||
|
/** @property {object} Assoziative Identity-Map der bereits initialisierten DataTables */
|
||
|
tables: {}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Initialize column filter feature
|
||
|
*
|
||
|
* @param {String} tableName
|
||
|
* @param {Array} settings
|
||
|
*/
|
||
|
init: function (tableName, settings) {
|
||
|
var $table = $('#' + tableName);
|
||
|
var table = $table.DataTable();
|
||
|
|
||
|
if ($table.length === 0) {
|
||
|
console.warn('DataTableColumnFilter: Table not found.', '#' + tableName);
|
||
|
return;
|
||
|
}
|
||
|
if (typeof settings !== 'object' || !Array.isArray(settings)) {
|
||
|
console.warn('DataTableColumnFilter Filter not active.', '#' + tableName);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (settings.length === 0) {
|
||
|
console.warn('DataTableColumnFilter: Filter not defined.', '#' + tableName);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
me.storage.tables[tableName] = table;
|
||
|
|
||
|
// Create filter elements
|
||
|
me.createFilterRow(tableName, settings);
|
||
|
|
||
|
// Show/hide filter cells on responsive resize
|
||
|
table.on('responsive-resize', me.onResponsiveResize);
|
||
|
|
||
|
// Move filter cells on column reorder
|
||
|
//table.on('column-reorder', me.onColumnReorder)
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} columName
|
||
|
* @param {array} filterSettings
|
||
|
*
|
||
|
* @return {object} Filter settings for given column
|
||
|
*/
|
||
|
getFilterSettingsByName: function (columName, filterSettings) {
|
||
|
return filterSettings.find(function (setting) {
|
||
|
if (setting.hasOwnProperty('name') && setting.name === columName) {
|
||
|
return setting;
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Create header row with filter elements
|
||
|
*
|
||
|
* @param {string} tableName
|
||
|
* @param {array} filterTypes Types [none|text|number_range]
|
||
|
*/
|
||
|
createFilterRow: function (tableName, filterTypes) {
|
||
|
var $table = me.storage.tables[tableName];
|
||
|
var $thead = $($table.table().header());
|
||
|
var $filterRow = $('<tr role="row" class="column-filter-row"></tr>');
|
||
|
|
||
|
$table.columns().every(function (index) {
|
||
|
var that = this;
|
||
|
var node = $(that.header());
|
||
|
var columnName = node.data('name');
|
||
|
var setting = me.getFilterSettingsByName(columnName, filterTypes);
|
||
|
if (typeof setting === 'undefined') {
|
||
|
setting = {type: 'none', name: columnName}; // Keine Filter-Einstellung vorhanden
|
||
|
}
|
||
|
|
||
|
var filterType = setting.type;
|
||
|
var $inputWrapper;
|
||
|
var searchValue = that.search();
|
||
|
var title = $(that.header()).html();
|
||
|
var $filterHead = $('<th colspan="1" rowspan="1" aria-controls="' + tableName + '"></th>');
|
||
|
$filterHead.toggle(that.responsiveHidden());
|
||
|
|
||
|
if (filterType === 'none') {
|
||
|
$inputWrapper = $('<div class="column-filter column-filter-none"></div>');
|
||
|
}
|
||
|
|
||
|
if (filterType === 'text') {
|
||
|
$inputWrapper = $('<div class="column-filter column-filter-text"></div>');
|
||
|
var $inputField = $('<input type="text" class="column-filter-input">');
|
||
|
$inputField
|
||
|
.attr('placeholder', title)
|
||
|
.val(searchValue !== '' ? searchValue : '')
|
||
|
.data('title', title)
|
||
|
.data('index', index)
|
||
|
.on('keyup', function () {
|
||
|
var $me = $(this);
|
||
|
var value = $me.val();
|
||
|
if (that.search() !== value) {
|
||
|
me.debounce(function () { that.search(value).draw(); }, 350, that);
|
||
|
}
|
||
|
});
|
||
|
$inputField.appendTo($inputWrapper);
|
||
|
}
|
||
|
|
||
|
if (filterType === 'number_range') {
|
||
|
$inputWrapper = $('<div class="column-filter column-filter-numberrange"></div>');
|
||
|
var $inputField1 = $('<input type="text" class="column-filter-input" placeholder="von">');
|
||
|
var $inputField2 = $('<input type="text" class="column-filter-input" placeholder="bis">');
|
||
|
|
||
|
// Split search value: example "number_range:42|123" or "number_range:null|null"
|
||
|
var searchParts = searchValue
|
||
|
.replace('number_range:', '')
|
||
|
.split('|', 2);
|
||
|
if (typeof searchParts[0] !== 'undefined' && searchParts[0] === 'null') {
|
||
|
searchParts[0] = '';
|
||
|
}
|
||
|
if (typeof searchParts[1] !== 'undefined' && searchParts[1] === 'null') {
|
||
|
searchParts[1] = '';
|
||
|
}
|
||
|
if (typeof searchParts[1] === 'undefined') {
|
||
|
searchParts[1] = '';
|
||
|
}
|
||
|
|
||
|
$inputField1
|
||
|
.val(searchParts[0])
|
||
|
.data('index', index);
|
||
|
$inputField2
|
||
|
.val(searchParts[1])
|
||
|
.data('index', index);
|
||
|
|
||
|
$inputField2
|
||
|
.on('keyup', function () {
|
||
|
var valueFrom = $inputField1.val();
|
||
|
var valueTo = $inputField2.val();
|
||
|
var searchValue = 'number_range:' + valueFrom + '|' + valueTo;
|
||
|
me.debounce(function () {
|
||
|
that.search(searchValue).draw();
|
||
|
}, 350, that);
|
||
|
});
|
||
|
$inputField1
|
||
|
.on('keyup', function () {
|
||
|
var valueFrom = $inputField1.val() || null;
|
||
|
var valueTo = $inputField2.val() || null;
|
||
|
var searchValue = 'number_range:' + valueFrom + '|' + valueTo;
|
||
|
me.debounce(function () {
|
||
|
that.search(searchValue).draw();
|
||
|
}, 350, that);
|
||
|
});
|
||
|
$inputField1.appendTo($inputWrapper);
|
||
|
$inputField2.appendTo($inputWrapper);
|
||
|
}
|
||
|
|
||
|
$inputWrapper.appendTo($filterHead);
|
||
|
$filterHead.appendTo($filterRow);
|
||
|
});
|
||
|
$filterRow.appendTo($thead);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Show/hide filter cells on responsive resize
|
||
|
*
|
||
|
* @see https://datatables.net/reference/event/responsive-resize
|
||
|
*
|
||
|
* @param {Event} e jQuery event object
|
||
|
* @param {object} datatable DataTable API instance for the table in question
|
||
|
* @param {Array} colVisible An array of boolean values that represent the visibility of the columns
|
||
|
*/
|
||
|
onResponsiveResize: function (e, datatable, colVisible) {
|
||
|
var $filterCells = $(datatable.header()).find('tr:nth-child(2) th');
|
||
|
$filterCells.each(function (index) {
|
||
|
$(this).toggle(colVisible[index]);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Move filter cells on column reorder
|
||
|
*
|
||
|
* @param {Event} e
|
||
|
* @param {object} settings
|
||
|
* @param {object} details
|
||
|
*/
|
||
|
onColumnReorder: function (e, settings, details) {
|
||
|
// @todo Filter-Spalten verschieben bei ColReorder
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Puffer-Funktion um Events erst nach einer bestimmten Zeit auszuführen
|
||
|
*
|
||
|
* @param {function} callback
|
||
|
* @param {number} delay
|
||
|
* @param {object|null} contextParam
|
||
|
*/
|
||
|
debounce: function (callback, delay, contextParam) {
|
||
|
var context = typeof contextParam !== 'undefined' && contextParam !== null ? contextParam : this;
|
||
|
var args = arguments;
|
||
|
|
||
|
window.clearTimeout(me.storage.debounceBuffer);
|
||
|
me.storage.debounceBuffer = window.setTimeout(function () {
|
||
|
callback.apply(context, args);
|
||
|
}, delay || 250);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
init: me.init
|
||
|
};
|
||
|
|
||
|
})(jQuery);
|
||
|
|
||
|
|
||
|
var DataTableExporter = (function ($) {
|
||
|
"use strict";
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
/**
|
||
|
* @param {Event} e
|
||
|
* @param {DataTable} dt
|
||
|
* @param {jQuery} node
|
||
|
* @param {object} buttonConfig
|
||
|
*/
|
||
|
onClickExportButton: function (e, dt, node, buttonConfig) {
|
||
|
var exportFormat = null;
|
||
|
var exportResult = null;
|
||
|
var ajaxUrl = dt.ajax.url();
|
||
|
var ajaxParams = me.cloneObject(dt.ajax.params());
|
||
|
|
||
|
var buttonName = buttonConfig.hasOwnProperty('name') ? buttonConfig.name : null;
|
||
|
switch (buttonName) {
|
||
|
case 'export-csv-all':
|
||
|
exportFormat = 'csv';
|
||
|
exportResult = 'all';
|
||
|
break;
|
||
|
case 'export-csv-page':
|
||
|
exportFormat = 'csv';
|
||
|
exportResult = 'page';
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (exportFormat === null || exportResult === null) {
|
||
|
alert('Export nicht möglich. Fehlkonfiguration');
|
||
|
throw 'Invalid export settings. Format or Result setting is empty.';
|
||
|
}
|
||
|
|
||
|
//
|
||
|
ajaxParams.draw = 1;
|
||
|
ajaxParams.export = {
|
||
|
format: exportFormat,
|
||
|
result: exportResult
|
||
|
};
|
||
|
var paramsString = $.param(ajaxParams);
|
||
|
window.location = ajaxUrl + '&' + paramsString;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {object} options
|
||
|
*/
|
||
|
prepareButtonOptions: function (options) {
|
||
|
if (options.hasOwnProperty('buttons')) {
|
||
|
options.buttons.forEach(function (button) {
|
||
|
|
||
|
if (button.hasOwnProperty('action')) {
|
||
|
if (button.action === 'export-csv-all') {
|
||
|
button.name = 'export-csv-all';
|
||
|
button.action = DataTableExporter.handleExportButtonClick;
|
||
|
}
|
||
|
if (button.action === 'export-csv-page') {
|
||
|
button.name = 'export-csv-page';
|
||
|
button.action = DataTableExporter.handleExportButtonClick;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (button.hasOwnProperty('extend') && button.extend === 'collection') {
|
||
|
me.prepareButtonOptions(button);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {object} source
|
||
|
*
|
||
|
* @return {object}
|
||
|
*/
|
||
|
cloneObject: function (source) {
|
||
|
return JSON.parse(JSON.stringify(source));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
handleExportButtonClick: me.onClickExportButton,
|
||
|
prepareButtonOptions: me.prepareButtonOptions
|
||
|
}
|
||
|
|
||
|
})(jQuery);
|
||
|
|
||
|
|
||
|
var DataTableHelper = function ($, ColumnFilter, Exporter) {
|
||
|
"use strict";
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
storage: {
|
||
|
debounceBuffer: null,
|
||
|
filterParams: {},
|
||
|
filterElements: [],
|
||
|
|
||
|
/** @property {Array} filterStorage Filter-Informationen die im LocalStorage abgelegt werden */
|
||
|
filterStorage: [],
|
||
|
|
||
|
/** @property {Object} Assoziative Identity-Map der bereits initialisierten DataTables */
|
||
|
tables: {},
|
||
|
|
||
|
/** @property {Array} tablesConfig Init-Options wegspeichern */
|
||
|
tablesConfig: {},
|
||
|
|
||
|
/** @property {Object} Assoziative Map der zusätzlichen AJAX-Parameter aus der Initialisierung */
|
||
|
ajaxParams: {}
|
||
|
},
|
||
|
|
||
|
init: function () {
|
||
|
|
||
|
// Filter vor den DataTables initialisieren
|
||
|
me.initFilter();
|
||
|
|
||
|
// DataTables autom. initialisieren; außer bei <table data-autoinit="false">
|
||
|
me.autoInitDataTables();
|
||
|
|
||
|
// Filter-Events erst nach der Initialisierung registrieren!
|
||
|
me.registerFilterEvents();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* DataTable-Filter initialisieren
|
||
|
*/
|
||
|
initFilter: function () {
|
||
|
$('input[data-datatable-filter]').each(function () {
|
||
|
var that = this;
|
||
|
var filterType = $(this).attr('type');
|
||
|
|
||
|
if (filterType === 'checkbox') {
|
||
|
me.initCheckboxFilter(that);
|
||
|
}
|
||
|
if (filterType === 'text') {
|
||
|
me.initTextFilter(that);
|
||
|
}
|
||
|
});
|
||
|
$('select[data-datatable-filter]').each(function () {
|
||
|
var that = this;
|
||
|
me.initSelectFilter(that);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Benötigte Events für Filter registrieren
|
||
|
*/
|
||
|
registerFilterEvents: function () {
|
||
|
$(document).on('change', 'select.datatable-filter', function () {
|
||
|
me.onChangeFilterValueListener(this);
|
||
|
});
|
||
|
$(document).on('change', 'input[type="checkbox"].datatable-filter', function () {
|
||
|
me.onChangeFilterValueListener(this);
|
||
|
});
|
||
|
$(document).on('keyup', 'input[type="text"].datatable-filter', function () {
|
||
|
var that = this;
|
||
|
me.debounce(function () {
|
||
|
me.onChangeFilterValueListener(that);
|
||
|
}, 100);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {HTMLElement} element
|
||
|
*/
|
||
|
onChangeFilterValueListener: function (element) {
|
||
|
var $element = $(element);
|
||
|
var filterId = $element.attr('id');
|
||
|
var filterName = $element.data('datatable-filter');
|
||
|
var targetTable = $element.data('datatable-target');
|
||
|
var filterType = null;
|
||
|
var filterValue = null;
|
||
|
|
||
|
if (typeof filterId === 'undefined' || filterId === null) {
|
||
|
console.warn('Filter element is unusable. Required property "id" is empty.', $element.get(0));
|
||
|
return;
|
||
|
}
|
||
|
if (typeof filterName === 'undefined' || filterName === null) {
|
||
|
console.warn('Filter element is unusable. Required property "data-datatable-filter" is empty.',
|
||
|
$element.get(0));
|
||
|
return;
|
||
|
}
|
||
|
if (typeof targetTable === 'undefined' || targetTable === null) {
|
||
|
console.warn('Filter element is unusable. Required property "data-datatable-target" is empty.',
|
||
|
$element.get(0));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ($element.is('select')) {
|
||
|
filterType = 'select';
|
||
|
}
|
||
|
if ($element.is('input')) {
|
||
|
filterType = $element.attr('type');
|
||
|
}
|
||
|
if (filterType === 'checkbox') {
|
||
|
filterValue = $element.prop('checked');
|
||
|
}
|
||
|
if (filterType === 'select') {
|
||
|
filterValue = $element.val();
|
||
|
}
|
||
|
if (filterType === 'text') {
|
||
|
filterValue = $element.val();
|
||
|
}
|
||
|
|
||
|
// Filter-Eigenschaften merken; für Speicherung in LocalStorage
|
||
|
me.storage.filterParams[filterName] = filterValue;
|
||
|
me.addFilterToLocalStorage(filterType, filterId, filterName, filterValue);
|
||
|
|
||
|
// DataTable-Ergenisse neu laden
|
||
|
me.reloadDataTable(targetTable);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {HTMLElement} element
|
||
|
*/
|
||
|
initCheckboxFilter: function (element) {
|
||
|
var $checkbox = $(element);
|
||
|
var filterId = $checkbox.attr('id');
|
||
|
var filterName = $checkbox.data('datatable-filter');
|
||
|
var filterValue = $checkbox.prop('checked');
|
||
|
|
||
|
if (filterId === '') {
|
||
|
console.warn('Required attribute "id" is empty.', element);
|
||
|
}
|
||
|
if (filterName === '') {
|
||
|
console.warn('Required attribute "datatable-filter" is empty.', element);
|
||
|
}
|
||
|
|
||
|
me.storage.filterParams[filterName] = filterValue;
|
||
|
me.addFilterToLocalStorage('checkbox', filterId, filterName, filterValue);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {HTMLElement} element
|
||
|
*/
|
||
|
initTextFilter: function (element) {
|
||
|
var $textInput = $(element);
|
||
|
var filterId = $textInput.attr('id');
|
||
|
var filterName = $textInput.data('datatable-filter');
|
||
|
var filterValue = $textInput.val();
|
||
|
|
||
|
if (filterId === '') {
|
||
|
console.warn('Required attribute "id" is empty.', element);
|
||
|
}
|
||
|
if (filterName === '') {
|
||
|
console.warn('Required attribute "datatable-filter" is empty.', element);
|
||
|
}
|
||
|
|
||
|
me.storage.filterParams[filterName] = filterValue;
|
||
|
me.addFilterToLocalStorage('text', filterId, filterName, filterValue);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {HTMLElement} element
|
||
|
*/
|
||
|
initSelectFilter: function (element) {
|
||
|
var $select = $(element);
|
||
|
var filterId = $select.attr('id');
|
||
|
var filterName = $select.data('datatable-filter');
|
||
|
var filterValue = $select.val();
|
||
|
|
||
|
if (filterId === '') {
|
||
|
console.warn('Required attribute "id" is empty.', element);
|
||
|
}
|
||
|
if (filterName === '') {
|
||
|
console.warn('Required attribute "datatable-filter" is empty.', element);
|
||
|
}
|
||
|
|
||
|
me.storage.filterParams[filterName] = filterValue;
|
||
|
me.addFilterToLocalStorage('select', filterId, filterName, filterValue);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* DataTable automatisch initialisieren
|
||
|
*
|
||
|
* Struktur:
|
||
|
* <div class="datatable-container">
|
||
|
* <table id="example" class="dataTable"></table>
|
||
|
* <script type="application/json"></script>
|
||
|
* </div>
|
||
|
*/
|
||
|
autoInitDataTables: function () {
|
||
|
$('.datatable-container').each(function () {
|
||
|
var $container = $(this);
|
||
|
var $table = $container.children('table').first();
|
||
|
var tableId = $table.attr('id');
|
||
|
|
||
|
// data-autoinit="false"
|
||
|
var autoInit = $table.data('autoinit');
|
||
|
if (typeof autoInit !== 'undefined' && autoInit === false) {
|
||
|
console.info('Auto init for table "' + tableId + '" disabled.');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (typeof tableId === 'undefined' || tableId === null || tableId === '') {
|
||
|
console.error('DataTable can not be initialized. Required attribute "id" is empty.', $table.get(0));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// DataTable initialisieren
|
||
|
me.initDataTable(tableId);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* DataTable initialisieren (wenn nicht autoInit)
|
||
|
*
|
||
|
* @param {string} tableName
|
||
|
*
|
||
|
* @throws
|
||
|
*/
|
||
|
initDataTable: function (tableName) {
|
||
|
if (me.isInitialized(tableName)) {
|
||
|
console.warn('Can not reinitialize DataTable #' + tableName + '. DataTable is already initialized.');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var $table = $('#' + tableName);
|
||
|
var $wrapper = $table.parent();
|
||
|
var $config = $wrapper.children('script');
|
||
|
|
||
|
try {
|
||
|
var configJson = JSON.parse($config.html());
|
||
|
if (typeof configJson !== 'object') {
|
||
|
throw 'JSON settings are invalid.';
|
||
|
}
|
||
|
|
||
|
var tableNameRequested = null;
|
||
|
if (configJson.hasOwnProperty('ajax') &&
|
||
|
configJson.ajax.hasOwnProperty('data') &&
|
||
|
configJson.ajax.data.hasOwnProperty('tablename')) {
|
||
|
tableNameRequested = configJson.ajax.data.tablename;
|
||
|
}
|
||
|
|
||
|
if (tableNameRequested !== tableName) {
|
||
|
throw 'Table names does not match.';
|
||
|
}
|
||
|
|
||
|
// Save config before modifing (for debugging only)
|
||
|
me.storage.tablesConfig[tableName] = me.cloneObject(configJson);
|
||
|
|
||
|
// Save additional ajax parameter
|
||
|
me.storage.ajaxParams[tableName] = me.cloneObject(configJson.ajax.data);
|
||
|
|
||
|
// Attach additional filter params
|
||
|
configJson.ajax.data = me.fetchFilterParams;
|
||
|
|
||
|
// Register state saving and loading callbacks
|
||
|
configJson.stateLoadParams = me.onStateLoadParams;
|
||
|
configJson.stateSaveParams = me.onStateSaveParams;
|
||
|
|
||
|
Exporter.prepareButtonOptions(configJson.buttons);
|
||
|
|
||
|
// Initialize DataTable
|
||
|
me.storage.tables[tableName] = $table.DataTable(configJson);
|
||
|
|
||
|
// Add Column filters
|
||
|
if (configJson.hasOwnProperty('columnFilter')) {
|
||
|
var colFilterSettings = configJson.columnFilter;
|
||
|
ColumnFilter.init(tableName, colFilterSettings);
|
||
|
}
|
||
|
}
|
||
|
catch (err) {
|
||
|
console.error('Can not init datatable "' + tableName + '". Error: ' + err);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* DataTable-Inhalte neu laden (per AJAX)
|
||
|
*
|
||
|
* @param {string} tableName
|
||
|
* @param {boolean} resetPaging Auf die erste Seite springen? (Default: true)
|
||
|
*/
|
||
|
refreshDataTable: function (tableName, resetPaging) {
|
||
|
if (!me.isInitialized(tableName)) {
|
||
|
console.warn('Can not refresh DataTable #' + tableName + '. DataTable is not initialized.');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
resetPaging = (typeof resetPaging === 'boolean') ? resetPaging : true;
|
||
|
me.storage.tables[tableName].ajax.reload(null, resetPaging);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* DataTable-Instanz zerstören
|
||
|
*
|
||
|
* @param {string} tableName
|
||
|
*/
|
||
|
destroyDataTable: function (tableName) {
|
||
|
if (!me.isInitialized(tableName)) {
|
||
|
console.warn('Can not destroy DataTable #' + tableName + '. DataTable is not initialized.');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
me.storage.tables[tableName].destroy();
|
||
|
|
||
|
delete me.storage.tables[tableName];
|
||
|
delete me.storage.tablesConfig[tableName];
|
||
|
},
|
||
|
|
||
|
addFilterToLocalStorage: function (filterType, elementId, filterName, filterValue) {
|
||
|
var foundInStorage = false;
|
||
|
|
||
|
// Versuche vorhandenen Eintrag zu aktualisieren
|
||
|
me.storage.filterStorage.forEach(function (storage) {
|
||
|
if (storage.elementId === elementId) {
|
||
|
storage.value = filterValue;
|
||
|
foundInStorage = true;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Eintrag fehlt > Anlegen
|
||
|
if (!foundInStorage) {
|
||
|
me.storage.filterStorage.push({
|
||
|
elementId: elementId,
|
||
|
filterType: filterType,
|
||
|
filterParam: filterName,
|
||
|
value: filterValue
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Filterwerte aus LocalStorage wiederherstellen
|
||
|
*
|
||
|
* @param {Object} settings
|
||
|
* @param {Object} data
|
||
|
*/
|
||
|
onStateLoadParams: function (settings, data) {
|
||
|
if (typeof data === 'undefined' || typeof settings === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
if (typeof settings.sTableId === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
if (typeof data.filter === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// console.log('onStateLoadParams');
|
||
|
// var newRevision = null;
|
||
|
// var lastRevision = null;
|
||
|
// if (data.hasOwnProperty('revision')) {
|
||
|
// lastRevision = data.revision;
|
||
|
// }
|
||
|
// if (settings.hasOwnProperty('oInit') && settings.oInit.hasOwnProperty('revision')) {
|
||
|
// newRevision = settings.oInit.revision;
|
||
|
// }
|
||
|
// console.log({lastRevision:lastRevision,newRevision:newRevision});
|
||
|
// if (lastRevision !== newRevision) {
|
||
|
// // alert('Einstellungen werden zurückgesetzt.');
|
||
|
// // return false;
|
||
|
// }
|
||
|
|
||
|
// Filterwerte merken
|
||
|
me.storage.filterStorage = data.filter;
|
||
|
|
||
|
// Filterwerte in HTML-Elemente schreiben
|
||
|
me.restoreFilterElements(data.filter); // @todo evtl in onStateLoaded
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Filter-Informationen im LocalStorage speichern
|
||
|
*
|
||
|
* @param {Object} settings
|
||
|
* @param {Object} data
|
||
|
*/
|
||
|
onStateSaveParams: function (settings, data) {
|
||
|
if (typeof data === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
if (typeof data.filter === 'undefined') {
|
||
|
data.filter = {};
|
||
|
}
|
||
|
|
||
|
data.filter = me.storage.filterStorage;
|
||
|
|
||
|
//var revision = null;
|
||
|
// Revision speichern, zum Zurücksetzen der Einstellungen
|
||
|
//if (settings.hasOwnProperty('oInit') && settings.oInit.hasOwnProperty('revision')) {
|
||
|
// data.revision = settings.oInit.revision;
|
||
|
//}
|
||
|
//data.revision = revision;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {Object} data
|
||
|
* @param {Object} settings DataTables.Settings object
|
||
|
*/
|
||
|
fetchFilterParams: function (data, settings) {
|
||
|
if (typeof data !== 'object' || typeof settings !== 'object') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Add additional ajax parameter from initialisation object
|
||
|
var tableName = settings.sTableId;
|
||
|
var ajaxParams = me.storage.ajaxParams[tableName];
|
||
|
Object.keys(ajaxParams).forEach(function (key) {
|
||
|
data[key] = ajaxParams[key];
|
||
|
});
|
||
|
|
||
|
// Add filter params and values to ajax data
|
||
|
if (typeof data.filter === 'undefined') {
|
||
|
data.filter = {};
|
||
|
}
|
||
|
data.filter = me.storage.filterParams;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Filter-Elemente (HTML) aus LocalStorage wiederherstellen
|
||
|
*
|
||
|
* @param {Object} data
|
||
|
*/
|
||
|
restoreFilterElements: function (data) {
|
||
|
data.forEach(function (item) {
|
||
|
var $element = $('#' + item.elementId);
|
||
|
if ($element.length !== 1) {
|
||
|
return;
|
||
|
}
|
||
|
switch (item.filterType) {
|
||
|
case 'checkbox':
|
||
|
$element.prop('checked', item.value);
|
||
|
break;
|
||
|
case 'text':
|
||
|
$element.val(item.value);
|
||
|
break;
|
||
|
case 'select':
|
||
|
$element.val(item.value);
|
||
|
break;
|
||
|
default:
|
||
|
return;
|
||
|
}
|
||
|
me.storage.filterParams[item.filterParam] = item.value;
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} tableName
|
||
|
*
|
||
|
* @return {object|null}
|
||
|
*/
|
||
|
getInitConfig: function (tableName) {
|
||
|
if (!me.storage.tablesConfig.hasOwnProperty(tableName)) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return me.storage.tablesConfig[tableName];
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* DataTable neu laden
|
||
|
*
|
||
|
* @param {string} tableName
|
||
|
*/
|
||
|
reloadDataTable: function (tableName) {
|
||
|
if (!me.isInitialized(tableName)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
me.storage.tables[tableName].draw();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} tableName
|
||
|
*
|
||
|
* @return {boolean}
|
||
|
*/
|
||
|
isInitialized: function (tableName) {
|
||
|
return me.storage.tables.hasOwnProperty(tableName) && me.storage.tables[tableName] !== null;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Puffer-Funktion um Events erst nach einer bestimmten Zeit auszuführen
|
||
|
*
|
||
|
* @param {function} callback
|
||
|
* @param {number} delay
|
||
|
*/
|
||
|
debounce: function (callback, delay) {
|
||
|
var context = this;
|
||
|
var args = arguments;
|
||
|
|
||
|
window.clearTimeout(me.storage.debounceBuffer);
|
||
|
me.storage.debounceBuffer = window.setTimeout(function () {
|
||
|
callback.apply(context, args);
|
||
|
}, delay || 250);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {object} source
|
||
|
*
|
||
|
* @return {object}
|
||
|
*/
|
||
|
cloneObject: function (source) {
|
||
|
return JSON.parse(JSON.stringify(source));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
init: me.init,
|
||
|
isInitialized: me.isInitialized,
|
||
|
initDataTable: me.initDataTable,
|
||
|
destroyDataTable: me.destroyDataTable,
|
||
|
refreshDataTable: me.refreshDataTable,
|
||
|
getInitConfig: me.getInitConfig
|
||
|
};
|
||
|
|
||
|
}(jQuery, DataTableColumnFilter, DataTableExporter);
|
||
|
|
||
|
|
||
|
var DataTableDebugger = (function ($, Helper) {
|
||
|
"use strict";
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
storage: {
|
||
|
/** @property {object} Assoziative Identity-Map der bereits initialisierten DataTables */
|
||
|
tables: {}
|
||
|
},
|
||
|
|
||
|
init: function () {
|
||
|
$(document).on('init.dt', function (e, settings) {
|
||
|
var api = new $.fn.dataTable.Api(settings);
|
||
|
var $table = $(api.table().node());
|
||
|
if ($table.hasClass('datatable-debug')) {
|
||
|
me.registerTable($table);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {jQuery} $table jQuery element
|
||
|
*/
|
||
|
registerTable: function ($table) {
|
||
|
var tableName = $table.attr('id');
|
||
|
me.storage.tables[tableName] = $table;
|
||
|
|
||
|
me.appendDebugElements($table);
|
||
|
me.registerEventListener($table);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {jQuery} $table jQuery element
|
||
|
*/
|
||
|
appendDebugElements: function ($table) {
|
||
|
var $wrapper = $table.closest('.dataTables_wrapper');
|
||
|
if ($wrapper.length === 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var api = $table.dataTable().api();
|
||
|
var stateLoadedString = JSON.stringify(api.state.loaded(), undefined, 4);
|
||
|
|
||
|
var $debugSql = $('<pre class="datatable-debug-sql">');
|
||
|
var $row1Left = $('<div class="debug-col-8">')
|
||
|
.append('<h3>Statement <small>(sql query)</small></h3>', $debugSql);
|
||
|
var $debugBind = $('<pre class="datatable-debug-bind">');
|
||
|
var $debugDuration = $('<pre class="datatable-debug-profiler">');
|
||
|
var $row1Right = $('<div class="debug-col-4">')
|
||
|
.append('<h3>Bind values <small>(sql query)</small></h3>', $debugBind)
|
||
|
.append('<h3>Profiler <small>(sql query)</small></h3>', $debugDuration);
|
||
|
var $row1 = $('<div class="debug-row">').append($row1Left).append($row1Right);
|
||
|
|
||
|
var $debugConfig = $('<pre class="datatable-debug-config">');
|
||
|
var $row2Left = $('<div class="debug-col-8">')
|
||
|
.append('<h3>Config options <small>(onInit)</small></h3>', $debugConfig);
|
||
|
var $debugStorage = $('<pre class="datatable-debug-storage">').html(stateLoadedString);
|
||
|
var $row2Right = $('<div class="debug-col-4">')
|
||
|
.append('<h3>State loaded <small>(onInit)</small></h3>', $debugStorage);
|
||
|
var $row2 = $('<div class="debug-row">').append($row2Left).append($row2Right);
|
||
|
|
||
|
$('<div class="debug-container">').append($row1, $row2).appendTo($wrapper);
|
||
|
|
||
|
var ajaxResult = api.ajax.json();
|
||
|
me.fillDebugElements($table, ajaxResult);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {jQuery} $table jQuery element
|
||
|
*/
|
||
|
registerEventListener: function ($table) {
|
||
|
$table.on('xhr.dt', function (e, settings, data) {
|
||
|
me.fillDebugElements($table, data);
|
||
|
});
|
||
|
$table.on('preXhr.dt', function (e, settings, data) {
|
||
|
me.fillDebugElements($table, data);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {jQuery} $table jQuery element
|
||
|
* @param {object} ajaxResult
|
||
|
*/
|
||
|
fillDebugElements: function ($table, ajaxResult) {
|
||
|
if (!ajaxResult.hasOwnProperty('debug')) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var $wrapper = $table.parents('.dataTables_wrapper').first();
|
||
|
var tableName = $table.attr('id');
|
||
|
var initConfigOptions = Helper.getInitConfig(tableName);
|
||
|
|
||
|
if (initConfigOptions !== null) {
|
||
|
var initConfigString = JSON.stringify(initConfigOptions, undefined, 4);
|
||
|
$wrapper.find('.datatable-debug-config').html(initConfigString);
|
||
|
}
|
||
|
if (ajaxResult.debug.hasOwnProperty('query')) {
|
||
|
$wrapper.find('.datatable-debug-sql').html(ajaxResult.debug.query.statement);
|
||
|
$wrapper.find('.datatable-debug-bind').html(ajaxResult.debug.query.bindings);
|
||
|
}
|
||
|
if (ajaxResult.debug.hasOwnProperty('profiler')) {
|
||
|
var profilerString = JSON.stringify(ajaxResult.debug.profiler, undefined, 4);
|
||
|
$wrapper.find('.datatable-debug-profiler').html(profilerString);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
init: me.init
|
||
|
};
|
||
|
|
||
|
})(jQuery, DataTableHelper);
|
||
|
|
||
|
|
||
|
var DataTableRowDetails = (function ($) {
|
||
|
"use strict";
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
storage: {
|
||
|
urls: {},
|
||
|
methods: {}
|
||
|
},
|
||
|
|
||
|
init: function () {
|
||
|
me.registerEvents();
|
||
|
},
|
||
|
|
||
|
registerEvents: function () {
|
||
|
$(document).on('init.dt', function (e, settings) {
|
||
|
var tableName = settings.sTableId;
|
||
|
var initOptions = settings.oInit;
|
||
|
if (!initOptions.hasOwnProperty('rowDetails')) {
|
||
|
return;
|
||
|
}
|
||
|
if (!initOptions.rowDetails.hasOwnProperty('ajax')) {
|
||
|
return;
|
||
|
}
|
||
|
if (!initOptions.rowDetails.ajax.hasOwnProperty('url')) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Ajax-Url pro DataTable speichern
|
||
|
me.storage.urls[tableName] = initOptions.rowDetails.ajax.url;
|
||
|
me.storage.methods[tableName] = initOptions.rowDetails.ajax.method || 'POST';
|
||
|
me.registerTableEvents(tableName);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} tableName
|
||
|
*/
|
||
|
registerTableEvents: function (tableName) {
|
||
|
var $table = $('#' + tableName);
|
||
|
if ($table.length === 0) {
|
||
|
return;
|
||
|
}
|
||
|
var ajaxMethod = me.storage.methods[tableName];
|
||
|
var ajaxUrl = me.storage.urls[tableName];
|
||
|
if (typeof ajaxUrl === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$table.on('click', '.dt-details .details', function (e) {
|
||
|
e.preventDefault();
|
||
|
var $opener = $(this);
|
||
|
var $parentRow = $opener.closest('tr');
|
||
|
var $table = $opener.closest('table.dataTable');
|
||
|
var api = $table.dataTable().api();
|
||
|
var row = api.row($parentRow);
|
||
|
var child = row.child;
|
||
|
|
||
|
if (child.isShown()) {
|
||
|
// Details ausblenden
|
||
|
row.child(false);
|
||
|
$parentRow.removeClass('parent');
|
||
|
$opener.removeClass('open');
|
||
|
|
||
|
} else {
|
||
|
// Details laden und einblenden
|
||
|
var ajaxData = $opener.data();
|
||
|
me.fetchChildRow(ajaxMethod, ajaxUrl, ajaxData).then(function (htmlContent) {
|
||
|
row.child(htmlContent, 'child').show();
|
||
|
$parentRow.addClass('parent');
|
||
|
$opener.addClass('open');
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} ajaxMethod
|
||
|
* @param {string} ajaxUrl
|
||
|
* @param {Object} ajaxParams
|
||
|
*
|
||
|
* @return {Deferred}
|
||
|
*/
|
||
|
fetchChildRow: function (ajaxMethod, ajaxUrl, ajaxParams) {
|
||
|
return $.ajax({
|
||
|
method: ajaxMethod,
|
||
|
url: ajaxUrl,
|
||
|
data: ajaxParams,
|
||
|
dataType: 'html'
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
init: me.init
|
||
|
};
|
||
|
|
||
|
})(jQuery);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Client-side formatter
|
||
|
*/
|
||
|
// var DataTableFormatter = (function ($) {
|
||
|
// "use strict";
|
||
|
//
|
||
|
// var me = {
|
||
|
//
|
||
|
// formatBytes: function (data, type, rowData, meta) {
|
||
|
// console.log('formatBytes', data, type);
|
||
|
// switch (type) {
|
||
|
// case 'display':
|
||
|
// return me.formatBytesForDisplay(data);
|
||
|
//
|
||
|
// case 'sort':
|
||
|
// return me.formatBytesForSorting(data);
|
||
|
//
|
||
|
// case 'type':
|
||
|
// return 'num';
|
||
|
//
|
||
|
// default:
|
||
|
// return data;
|
||
|
// }
|
||
|
// },
|
||
|
//
|
||
|
// /**
|
||
|
// * @param {string} value
|
||
|
// *
|
||
|
// * @return {string}
|
||
|
// */
|
||
|
// formatBytesForDisplay: function(value) {
|
||
|
// var bytes = parseInt(value);
|
||
|
// if (bytes === 0) {
|
||
|
// return '0 Bytes';
|
||
|
// }
|
||
|
//
|
||
|
// var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||
|
// var exponent = Math.floor(Math.log(bytes) / Math.log(1024));
|
||
|
// var decimalString = parseFloat((bytes / Math.pow(1024, exponent)).toFixed(1)) + '';
|
||
|
//
|
||
|
// return decimalString.replace('.', ',') + ' ' + sizes[exponent];
|
||
|
// },
|
||
|
//
|
||
|
// /**
|
||
|
// * @param {string} value
|
||
|
// *
|
||
|
// * @return {number}
|
||
|
// */
|
||
|
// formatBytesForSorting: function (value) {
|
||
|
// return parseInt(value);
|
||
|
// }
|
||
|
//
|
||
|
// };
|
||
|
//
|
||
|
// return {
|
||
|
// formatBytes: me.formatBytes
|
||
|
// };
|
||
|
//
|
||
|
// })(jQuery);
|
||
|
|
||
|
|
||
|
$(document).ready(function () {
|
||
|
DataTableHelper.init();
|
||
|
DataTableRowDetails.init();
|
||
|
DataTableDebugger.init();
|
||
|
});
|