src/main/webapp/js/table.js
/**
     * Binds all tables that have the class 'data-table' to a new JQuery DataTables instance.
     */
Binds all tables that have the class 'data-table' to a new JQuery DataTables instance.
Binds all tables that have the class ' data - table ' to a new JQuery DataTables instance .
function bindTables($) {
        function createDataTable(table) {
            const defaultConfiguration = {
                language: {
                    emptyTable: 'Loading - please wait ...'
                },
                deferRender: true,
                pagingType: 'numbers', 
                order: [[1, 'asc']], 
                columnDefs: [
                    {
                        targets: 'nosort', 
                        orderable: false
                    },
                    {
                        targets: 'text-end', 
                        className: 'text-end'
                    },
                    {
                        targets: 'date', 
                        render: function (data, type, _row, _meta) {
                            if (type === 'display') {
                                if (data === 0) {
                                    return '-';
                                }
                                var dateTime = luxon.DateTime.fromMillis(data * 1000);
                                return '<span data-bs-toggle="tooltip" data-bs-placement="bottom" title="'
                                    + dateTime.toLocaleString(luxon.DateTime.DATETIME_SHORT) + '">'
                                    + dateTime.toRelative({locale: 'en'}) + '</span>';
                            }
                            else {
                                return data;
                            }
                        }
                    },
                    {
                        targets: 'percentage', 
                        className: 'text-end',
                        render: function (data, type, _row, _meta) {
                            if (isNaN(data)) {
                                return data;
                            }
                            return Number(data).toLocaleString(undefined,
                                {style: 'percent', minimumFractionDigits: 2});
                        }
                    },
                    {
                        targets: 'hidden', 
                        visible: false,
                        searchable: true,
                        orderable: false 
                    }
                ],
                columns: JSON.parse(table.attr('data-columns-definition'))
            };
            const tableConfiguration = JSON.parse(table.attr('data-table-configuration'));
            const dataTable = table.DataTable(Object.assign(defaultConfiguration, tableConfiguration));
            if (tableConfiguration.buttons) {
                dataTable
                    .buttons()
                    .container()
                    .addClass('float-none mb-3')
                    .prependTo($(dataTable.table().container()).closest('.table-responsive'));
            }
            return dataTable;
        }
        function loadTableData(table, dataTable) {
            if (!table[0].hasAttribute('isLoaded')) {
                table.attr('isLoaded', 'true');
                tableDataProxy.getTableRows(table.attr('id'), function (t) {
                    (function () {
                        const model = JSON.parse(t.responseObject());
                        dataTable.rows.add(model).draw();
                    })();
                });
            }
        }
        const allTables = $('table.data-table');
        function toggleDetailsColumnIcon(tr, from, to) {
            const svg = tr.find("use");
            const current = svg.attr("href");
            svg.attr("href", current.replace(from, to))
        }
        allTables.each(function () {
            const table = $(this);
            const id = table.attr('id');
            const dataTable = createDataTable(table);
            table.on('click', 'div.details-control', function () {
                const tr = $(this).parents('tr');
                const row = dataTable.row(tr);
                if (row.child.isShown()) {
                    row.child.hide();
                    tr.removeClass('shown');
                    toggleDetailsColumnIcon(tr, "minus-circle", "plus-circle");
                }
                else {
                    row.child($(this).data('description')).show();
                    tr.addClass('shown');
                    toggleDetailsColumnIcon(tr, "plus-circle", "minus-circle");
                }
            });
            table.on('draw.dt', function () {
                table.find('[data-bs-toggle="tooltip"]').each(function () {
                    const tooltip = new bootstrap5.Tooltip($(this)[0]);
                    tooltip.enable();
                });
            });
            if (table.is(":visible")) {
                loadTableData(table, dataTable);
            }
            else {
                table.on('becameVisible', function () {
                    loadTableData(table, dataTable);
                });
            }
            table.on('order.dt', function () {
                const order = table.DataTable().order();
                localStorage.setItem(id + '#orderBy', order[0][0]);
                localStorage.setItem(id + '#orderDirection', order[0][1]);
            });
            const orderBy = localStorage.getItem(id + '#orderBy');
            const orderDirection = localStorage.getItem(id + '#orderDirection');
            if (orderBy && orderDirection) {
                const order = [orderBy, orderDirection];
                try {
                    dataTable.order(order).draw();
                }
                catch (ignore) { 
                    dataTable.order([[1, 'asc']]).draw();
                }
            }
            table.on('length.dt', function (e, settings, len) {
                localStorage.setItem(id + '#table-length', len);
            });
            const storedLength = localStorage.getItem(id + '#table-length');
            if ($.isNumeric(storedLength)) {
                dataTable.page.len(storedLength).draw();
            }
        });
    }
function bindTables ( $ ) { function createDataTable ( table ) { const defaultConfiguration = { language : { emptyTable : 'Loading - please wait ...' } , deferRender : true , pagingType : 'numbers' , order : [ [ 1 , 'asc' ] ] , columnDefs : [ { targets : 'nosort' , orderable : false } , { targets : 'text-end' , className : 'text-end' } , { targets : 'date' , render : function ( data , type , _row , _meta ) { if ( type === 'display' ) { if ( data === 0 ) { return '-' ; } var dateTime = luxon . DateTime . fromMillis ( data * 1000 ) ; return '<span data-bs-toggle="tooltip" data-bs-placement="bottom" title="' + dateTime . toLocaleString ( luxon . DateTime . DATETIME_SHORT ) + '">' + dateTime . toRelative ( { locale : 'en' } ) + '</span>' ; } else { return data ; } } } , { targets : 'percentage' , className : 'text-end' , render : function ( data , type , _row , _meta ) { if ( isNaN ( data ) ) { return data ; } return Number ( data ) . toLocaleString ( undefined , { style : 'percent' , minimumFractionDigits : 2 } ) ; } } , { targets : 'hidden' , visible : false , searchable : true , orderable : false } ] , columns : JSON . parse ( table . attr ( 'data-columns-definition' ) ) } ; const tableConfiguration = JSON . parse ( table . attr ( 'data-table-configuration' ) ) ; const dataTable = table . DataTable ( Object . assign ( defaultConfiguration , tableConfiguration ) ) ; if ( tableConfiguration . buttons ) { dataTable . buttons ( ) . container ( ) . addClass ( 'float-none mb-3' ) . prependTo ( $ ( dataTable . table ( ) . container ( ) ) . closest ( '.table-responsive' ) ) ; } return dataTable ; } function loadTableData ( table , dataTable ) { if ( ! table [ 0 ] . hasAttribute ( 'isLoaded' ) ) { table . attr ( 'isLoaded' , 'true' ) ; tableDataProxy . getTableRows ( table . attr ( 'id' ) , function ( t ) { ( function ( ) { const model = JSON . parse ( t . responseObject ( ) ) ; dataTable . rows . add ( model ) . draw ( ) ; } ) ( ) ; } ) ; } } const allTables = $ ( 'table.data-table' ) ; function toggleDetailsColumnIcon ( tr , from , to ) { const svg = tr . find ( "use" ) ; const current = svg . attr ( "href" ) ; svg . attr ( "href" , current . replace ( from , to ) ) } allTables . each ( function ( ) { const table = $ ( this ) ; const id = table . attr ( 'id' ) ; const dataTable = createDataTable ( table ) ; table . on ( 'click' , 'div.details-control' , function ( ) { const tr = $ ( this ) . parents ( 'tr' ) ; const row = dataTable . row ( tr ) ; if ( row . child . isShown ( ) ) { row . child . hide ( ) ; tr . removeClass ( 'shown' ) ; toggleDetailsColumnIcon ( tr , "minus-circle" , "plus-circle" ) ; } else { row . child ( $ ( this ) . data ( 'description' ) ) . show ( ) ; tr . addClass ( 'shown' ) ; toggleDetailsColumnIcon ( tr , "plus-circle" , "minus-circle" ) ; } } ) ; table . on ( 'draw.dt' , function ( ) { table . find ( '[data-bs-toggle="tooltip"]' ) . each ( function ( ) { const tooltip = new bootstrap5 . Tooltip ( $ ( this ) [ 0 ] ) ; tooltip . enable ( ) ; } ) ; } ) ; if ( table . is ( ":visible" ) ) { loadTableData ( table , dataTable ) ; } else { table . on ( 'becameVisible' , function ( ) { loadTableData ( table , dataTable ) ; } ) ; } table . on ( 'order.dt' , function ( ) { const order = table . DataTable ( ) . order ( ) ; localStorage . setItem ( id + '#orderBy' , order [ 0 ] [ 0 ] ) ; localStorage . setItem ( id + '#orderDirection' , order [ 0 ] [ 1 ] ) ; } ) ; const orderBy = localStorage . getItem ( id + '#orderBy' ) ; const orderDirection = localStorage . getItem ( id + '#orderDirection' ) ; if ( orderBy && orderDirection ) { const order = [ orderBy , orderDirection ] ; try { dataTable . order ( order ) . draw ( ) ; } catch ( ignore ) { dataTable . order ( [ [ 1 , 'asc' ] ] ) . draw ( ) ; } } table . on ( 'length.dt' , function ( e , settings , len ) { localStorage . setItem ( id + '#table-length' , len ) ; } ) ; const storedLength = localStorage . getItem ( id + '#table-length' ) ; if ( $ . isNumeric ( storedLength ) ) { dataTable . page . len ( storedLength ) . draw ( ) ; } } ) ; }
Binds all tables that have the class 'data-table' to a new JQuery DataTables instance.
Binds all tables that have the class ' data - table ' to a new JQuery DataTables instance .
/**
         * Creates the data table instance for the specified table element.
         */ // page number button only // default order, if not persisted yet // All columns with the '.nosort' class in the <th> // All columns with the '.text-right' class in the <th> // All columns with the '.date' class in the <th> // All columns with the '.percentage' class in the <th> // All columns with the '.hidden' class in the <th> // There is no point in allowing sort by this column if it's not visible. // overwrite/merge the default configuration with values from the provided table configuration // add the buttons to the top of the table /**
         * Loads the content for the specified table element via an Ajax call.
         */ // Add event listener for opening and closing details // Add event listener that stores the order a user selects /**
             * Restores the order of every table by reading the local storage of the browser.
             * If no order has been stored yet, the table is skipped.
             * Also saves the default length of the number of table columns.
             */ // TODO: find a way to determine the number of columns here // Store paging size