/** * */ 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 = $(''); $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 = $(''); $filterHead.toggle(that.responsiveHidden()); if (filterType === 'none') { $inputWrapper = $('
'); } if (filterType === 'text') { $inputWrapper = $('
'); var $inputField = $(''); $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 = $('
'); var $inputField1 = $(''); var $inputField2 = $(''); // 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 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: *
*
* * */ 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 = $('
');
            var $row1Left = $('
') .append('

Statement (sql query)

', $debugSql); var $debugBind = $('
');
            var $debugDuration = $('
');
            var $row1Right = $('
') .append('

Bind values (sql query)

', $debugBind) .append('

Profiler (sql query)

', $debugDuration); var $row1 = $('
').append($row1Left).append($row1Right); var $debugConfig = $('
');
            var $row2Left = $('
') .append('

Config options (onInit)

', $debugConfig); var $debugStorage = $('
').html(stateLoadedString);
            var $row2Right = $('
') .append('

State loaded (onInit)

', $debugStorage); var $row2 = $('
').append($row2Left).append($row2Right); $('
').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(); });