import "datatables.net"; import "datatables.net-bs"; // Initialize state holders. FleetCart.dataTable = { routes: {}, selected: {} }; export default class { constructor(selector, options, callback) { this.selector = selector; this.element = $(selector); if (FleetCart.dataTable.selected[selector] === undefined) { FleetCart.dataTable.selected[selector] = []; } this.initiateDataTable(options, callback); this.addErrorHandler(); this.registerTableProcessingPlugin(); } initiateDataTable(options, callback) { let sortColumn = this.element.find("th[data-sort]"); this.element.dataTable( _.merge( { serverSide: true, processing: true, ajax: this.route("table", { table: true }), stateSave: true, sort: true, info: true, filter: true, lengthChange: true, paginate: true, autoWidth: false, pageLength: 20, lengthMenu: [10, 20, 50, 100, 200], order: [ sortColumn.index() !== -1 ? sortColumn.index() : 1, sortColumn.data("sort") || "desc", ], initComplete: () => { if (this.hasRoute("destroy")) { let deleteButton = this.addTableActions(); deleteButton.on("click", () => this.deleteRows()); this.selectAllRowsEventListener(); } if (this.hasRoute("show") || this.hasRoute("edit")) { this.onRowClick(this.redirectToRowPage); } if (callback !== undefined) { callback.call(this); } }, rowCallback: (row, data) => { if (this.hasRoute("show") || this.hasRoute("edit")) { this.makeRowClickable(row, data.id); } }, drawCallback: () => { this.element.find(".select-all").prop("checked", false); setTimeout(() => { this.selectRowEventListener(); this.checkSelectedCheckboxes( this.constructor.getSelectedIds(this.selector) ); }); }, stateSaveParams(settings, data) { delete data.search; }, }, options ) ); } addTableActions() { let button = ` `; return $(button).appendTo( this.element .closest(".dataTables_wrapper") .find(".dataTables_length") ); } deleteRows() { let checked = this.element.find(".select-row:checked"); if (checked.length === 0) { return; } let confirmationModal = $("#confirmation-modal"); let deleted = []; confirmationModal .modal("show") .find("form") .on("submit", (e) => { e.preventDefault(); confirmationModal.modal("hide"); let table = this.element.DataTable(); table.processing(true); let ids = this.constructor.getRowIds(checked); // Don't make ajax request if an id was previously deleted. if ( deleted.length !== 0 && _.difference(deleted, ids).length === 0 ) { return; } $.ajax({ type: "DELETE", url: this.route("destroy", { ids: ids.join() }), success: () => { deleted = _.flatten(deleted.concat(ids)); this.constructor.setSelectedIds(this.selector, []); this.constructor.reload(this.element); }, error: (xhr) => { error(xhr.responseJSON.message); deleted = _.flatten(deleted.concat(ids)); this.constructor.setSelectedIds(this.selector, []); this.constructor.reload(this.element); }, }); }); } makeRowClickable(row, id) { let key = this.hasRoute("show") ? "show" : "edit"; let url = this.route(key, { id }); $(row).addClass("clickable-row").data("href", url); } onRowClick(handler) { let row = "tbody tr.clickable-row td"; if (this.element.find(".select-all").length !== 0) { row += ":not(:first-child)"; } this.element.on("click", row, handler); } redirectToRowPage(e) { window.open( $(e.currentTarget).parent().data("href"), e.ctrlKey ? "_blank" : "_self" ); } selectAllRowsEventListener() { this.element.find(".select-all").on("change", (e) => { this.element .find(".select-row") .prop("checked", e.currentTarget.checked); }); } selectRowEventListener() { this.element.find(".select-row").on("change", (e) => { if (e.currentTarget.checked) { this.appendToSelected(e.currentTarget.value); } else { this.removeFromSelected(e.currentTarget.value); } }); } appendToSelected(id) { id = parseInt(id); if (!FleetCart.dataTable.selected[this.selector].includes(id)) { FleetCart.dataTable.selected[this.selector].push(id); } } removeFromSelected(id) { id = parseInt(id); FleetCart.dataTable.selected[this.selector].remove(id); } checkSelectedCheckboxes(selectedIds) { let rows = this.element.find(".select-row"); let checkableRows = rows.toArray().filter((row) => { return selectedIds.includes(parseInt(row.value)); }); $(checkableRows).prop("checked", true); } route(name, params) { let router = FleetCart.dataTable.routes[this.selector][name]; if (typeof router === "string") { router = { name: router, params }; } router.params = _.merge(params, router.params); return window.route(router.name, router.params); } hasRoute(name) { return FleetCart.dataTable.routes[this.selector][name] !== undefined; } static setRoutes(selector, routes) { FleetCart.dataTable.routes[selector] = routes; } static setSelectedIds(selector, selected) { FleetCart.dataTable.selected[selector] = selected; } static getSelectedIds(selector) { return FleetCart.dataTable.selected[selector]; } static reload(selector, callback, resetPaging = false) { $(selector).DataTable().ajax.reload(callback, resetPaging); } static getRowIds(rows) { return rows.toArray().reduce((ids, row) => { return ids.concat(row.value); }, []); } static removeLengthFields() { $(".dataTables_length select").remove(); } addErrorHandler() { $.fn.dataTable.ext.errMode = (settings, helpPage, message) => { this.element.html(message); }; } // https://datatables.net/plug-ins/api/processing() registerTableProcessingPlugin() { $.fn.dataTable.Api.register("processing()", function (show) { return this.iterator("table", function (ctx) { ctx.oApi._fnProcessingDisplay(ctx, show); }); }); } }