UNPKG

nested-datatables

Version:

jQuery DataTables plugin for rendering nested DataTables in rows. Inner tables are independent of the data and layout from the outer table.

212 lines (197 loc) 6.81 kB
import TableBuilder from './TableBuilder.js'; import '../styles/style.css'; var dataTable = require('datatables'); $.DataTable = dataTable; /** * * @author Andrej Gajdos <mail@andrejgajdos.com> * * TableHierarchy class is used for building nested DataTables hierarchy * * @param {string} tableParentID Id of a DOM element where will be table hierarchy placed * @param {Array.<Object>} tableDataInJson Data in Json format which are used for building table hierarchy * @param {Object} dataTableSettings settings for DataTables object */ export default class TableHierarchy { constructor(tableParentID, tableDataInJson, dataTableSettings) { // check if wrapper element for table exist if (tableParentID !== undefined) { this.tableContainerSelector = $('#' + tableParentID); if (!this.tableContainerSelector.length) { console.error('Element with id "' + tableParentID + '" doesn\'t exist!'); } } // check if data is defined if (tableDataInJson !== undefined) { this.tableBuilder = new TableBuilder(tableParentID, tableDataInJson); } else { console.error('Data are undefined!'); } // check if DataTable settings object is defined if (dataTableSettings !== undefined) { this.dataTableSettings = dataTableSettings; } else { console.error('DataTable settings are undefined!'); } this.tables = []; // created table objects in hierarchy this.tableToShow; } /** * Initialize DataTables plugin with click listener on row by jQuery, * TableBuilder object is used for building specific table */ initializeTableHierarchy() { this.tableBuilder.buildTable(); let mainNode = this.tableContainerSelector.html( this.tableBuilder.getTable() ); // Initialize DataTables, with no sorting on the 'details' column this.tableToShow = mainNode.find('table').first(); let table = this.tableToShow.dataTable(this.dataTableSettings); mainNode.find('table').wrap("<div class='tableWrapper'/>"); this.setWidthOfCellsWithNarrows(table); this.tables.push([ mainNode .find('table') .eq(0) .attr('id'), table ]); let that = this; var tableShowEvt; var tableHideEvt; this.tableContainerSelector.on('click', 'tbody tr', function() { if ( $(this).attr('class') !== 'details' && $(this).find('.arrowContainer img').length > 0 ) { if (document.createEvent) { tableShowEvt = document.createEvent('HTMLEvents'); tableShowEvt.initEvent('onShowChildHierarchy', true, true); tableHideEvt = document.createEvent('HTMLEvents'); tableHideEvt.initEvent('onHideChildHierarchy', true, true); } else { tableShowEvt = document.createEventObject(); tableShowEvt.eventType = 'onShowChildHierarchy'; tableHideEvt = document.createEventObject(); tableHideEvt.eventType = 'onHideChildHierarchy'; } tableShowEvt.eventName = 'onShowChildHierarchy'; tableHideEvt.eventName = 'onHideChildHierarchy'; let parentTable = {}; let parentTableClass = $(this) .closest('table') .attr('id'); if ( that.tables .toString() .split(',') .indexOf(parentTableClass) % 2 === 0 ) { for (let i = 0; i < that.tables.length; i++) { if ( that.tables[i][0] === $(this) .closest('table') .attr('id') ) { parentTable = that.tables[i][1]; break; } } } if (parentTable.fnIsOpen($(this))) { /* This row is already opened - close it */ if (document.createEvent) { this.dispatchEvent(tableHideEvt); } else { this.fireEvent('on' + tableHideEvt.eventType, event); } parentTable.fnClose($(this)); $(this) .find('.arrowContainer img') .removeClass('rotate-down') .addClass('rotate-up'); } else { if ( $(this) .find('.arrowContainer img') .eq(0) ) { if (document.createEvent) { this.dispatchEvent(tableShowEvt); } else { this.fireEvent('on' + tableShowEvt.eventType, event); } $(this) .find('.arrowContainer img') .removeClass('rotate-up') .addClass('rotate-down'); that.tableBuilder .getIdParser() .setElementIdWithOccurrence($(this).attr('id')); that.tableBuilder.buildTable(); let tableAsJQueryNode = $('<div/>') .html(that.tableBuilder.getTable()) .contents(); let allTables = tableAsJQueryNode.find('table'); parentTable.fnOpen(this, tableAsJQueryNode, 'details'); $(allTables).each(function() { if ( $(this) .find('tbody') .html() !== '' ) { let newTable = $(this).dataTable(that.dataTableSettings); let tableId = $(this).attr('id'); that.setWidthOfCellsWithNarrows($(this)); // if tables contains table with tableId, replace this table, otherwise push new table if ( that.tables .toString() .split(',') .indexOf(tableId) % 2 === 0 ) { let indexOfObjectWithId = $.map(that.tables, function( obj, index ) { if (obj[0] === tableId) { return index; } })[0]; that.tables[indexOfObjectWithId] = [tableId, newTable]; } else { that.tables.push([tableId, newTable]); } } }); } } } }); } /** * Set up css class and 1% width for all cells containing arrow image * * @param {DataTable} table initialized DataTable table */ setWidthOfCellsWithNarrows(table) { if (table.find('tbody tr:first-child .arrowContainer img').length > 0) { table.find('tbody tr .arrowContainer:first-child img').each(function() { $(this) .parent() .closest('td') .css('width', '1%'); $(this) .parent() .closest('tr') .addClass('rowHover'); }); } } }