// Datatables in tabs that aren't initially shown need columns resized on show $('a[data-toggle="tab"]').on("shown.bs.tab", function(e) { $(this.getAttribute("href")) .find("table.dataTable") .each(function() { $(this) .dataTable() .fnAdjustColumnSizing(); }); }); const zStorage = (function() { const stores = {}; return { set(key, value, table) { if (!stores.hasOwnProperty(table)) { stores[table] = new idbKeyval.Store(APP_NAME, table + "_table"); } return idbKeyval.set(key, value, stores[table]); }, get(key, table) { if (!stores.hasOwnProperty(table)) { stores[table] = new idbKeyval.Store(APP_NAME, table + "_table"); } return idbKeyval.get(key, stores[table]); } }; })(); const DEBUG = false; function getTableParams(tableName, settings, callback) { const [cacheFilters, paramFilters] = settings.filters.reduce( ([c, p], cur) => (cur.cache ? [[cur, ...c], p] : [c, [cur, ...p]]), [[], []] ); Promise.all( [ zStorage.get("view", tableName), zStorage.get("size", tableName), zStorage.get("sort", tableName), zStorage.get("fields", tableName) ].concat(cacheFilters.map(f => zStorage.get(f.name + "_filter", tableName))) ).then(v => { const [view, size, sort, fields, ...savedFilters] = v; cacheFilters.forEach((f, i) => setupFilter(tableName, f, savedFilters[i])); paramFilters.forEach(f => setupFilter(tableName, f, undefined)); const visibleColumns = (fields || []).reduce( (acc, cur) => (cur.vis ? acc.concat(cur.col) : acc), [] ); const columns = fields === undefined ? settings.columns : settings.columns .map(c => { const index = fields.findIndex(f => f.col === c.data); return { ...c, visible: visibleColumns.includes(c.data), sortIndex: index === -1 ? 9999 : index }; }) .sort((a, b) => a.sortIndex - b.sortIndex); callback( columns, view || settings.view, size || settings.size, (sort || settings.sort).map(([col, dir]) => { const newCol = settings.columns.findIndex(c => c.data === col); return [newCol > -1 ? newCol : 1, dir]; }) ); }); } function setupFilter(tableName, filter, cached) { switch (filter.type) { case "checkbox": return (cached === undefined ? filter.defaults : cached).forEach(v => $(`#${tableName}_content input[value="${v}"]`).prop("checked", true) ); case "select": case "group-select": return $(`#${tableName}_content select[name="${filter.name}"]`) .val(cached === undefined ? filter.defaults : cached) .trigger("change"); // Is boolean used by any apps? case "boolean": return $(`#${tableName}_content input[name="${filter.name}"]`).prop( "checked", cached === undefined ? filter.defaults : cached ); } } function initTable(api, tableName, settings, columns, tableFilters) { initViewMode(api, tableName, settings.view); initTableSize(api, tableName, settings.size); initSortEvent(api, tableName); initSearch(api, tableName); initTableSelection(api, tableName); initColumnEvents(api, tableName, columns); initTableFilters(api, tableName, tableFilters); $(`#${tableName}_refresh`).on("click", function(e) { if ( $(`#${tableName}_content`).is(":visible") && !$(this).hasClass("zc-spin") ) { api.draw(false); } }); } function initViewMode(api, tableName, mode) { $(`#${tableName}_view_${mode}`).addClass("active"); const viewModeSelectors = `#${tableName}_view_table, #${tableName}_view_grid`; $(viewModeSelectors).on("click", function(e) { if ($(this).hasClass("active")) return; $(viewModeSelectors).toggleClass("active"); zStorage.set("view", e.currentTarget.id.split("_")[2], tableName); api .draw(false) .rows() .deselect(); }); } function getTableViewMode(tableName, fallback) { if ($(`#${tableName}_view_table`).hasClass("active")) return "table"; else if ($(`#${tableName}_view_grid`).hasClass("active")) return "grid"; else return fallback; } function initTableSize(api, tableName, size) { $("", { type: "checkbox", name: `${tableName}[table_column_vis][]`, checked: !c.hasOwnProperty("visible") || c.visible, value: i }).on("change", function(e) { index = api.colReorder.transpose(+$(this).val(), "toCurrent"); api.column(index).visible($(this).is(":checked")); resize_iframe(); saveColumns(); }), $("