From 372bfb4175e53bfd03318de793932f291f465a44 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Fri, 14 Nov 2025 13:59:38 +0100 Subject: [PATCH] Bug 40816: DT - Update css and js files - OPAC --- .../opac-tmpl/lib/datatables/datatables.css | 239 ++- .../opac-tmpl/lib/datatables/datatables.js | 1763 +++++++++++------ .../lib/datatables/datatables.min.css | 8 +- .../lib/datatables/datatables.min.js | 22 +- 4 files changed, 1368 insertions(+), 664 deletions(-) diff --git a/koha-tmpl/opac-tmpl/lib/datatables/datatables.css b/koha-tmpl/opac-tmpl/lib/datatables/datatables.css index 0e7523c401e..5804e3c9fec 100644 --- a/koha-tmpl/opac-tmpl/lib/datatables/datatables.css +++ b/koha-tmpl/opac-tmpl/lib/datatables/datatables.css @@ -4,31 +4,32 @@ * * To rebuild or modify this file with the latest versions of the included * software please visit: - * https://datatables.net/download/#dt/dt-2.1.8/b-3.1.2/b-colvis-3.1.2/b-html5-3.1.2/b-print-3.1.2/r-3.0.3 + * https://datatables.net/download/#dt/dt-2.3.4/b-3.2.5/b-colvis-3.2.5/b-html5-3.2.5/b-print-3.2.5/r-3.0.7 * * Included libraries: - * DataTables 2.1.8, Buttons 3.1.2, Column visibility 3.1.2, HTML5 export 3.1.2, Print view 3.1.2, Responsive 3.0.3 + * DataTables 2.3.4, Buttons 3.2.5, Column visibility 3.2.5, HTML5 export 3.2.5, Print view 3.2.5, Responsive 3.0.7 */ -@charset "UTF-8"; :root { --dt-row-selected: 13, 110, 253; --dt-row-selected-text: 255, 255, 255; - --dt-row-selected-link: 9, 10, 11; + --dt-row-selected-link: 228, 228, 228; --dt-row-stripe: 0, 0, 0; --dt-row-hover: 0, 0, 0; --dt-column-ordering: 0, 0, 0; + --dt-header-align-items: center; + --dt-header-vertical-align: middle; --dt-html-background: white; } :root.dark { --dt-html-background: rgb(33, 37, 41); } -table.dataTable td.dt-control { +table.dataTable tbody td.dt-control { text-align: center; cursor: pointer; } -table.dataTable td.dt-control:before { +table.dataTable tbody td.dt-control:before { display: inline-block; box-sizing: border-box; content: ""; @@ -37,12 +38,15 @@ table.dataTable td.dt-control:before { border-bottom: 5px solid transparent; border-right: 0px solid transparent; } -table.dataTable tr.dt-hasChild td.dt-control:before { +table.dataTable tbody tr.dt-hasChild td.dt-control:before { border-top: 10px solid rgba(0, 0, 0, 0.5); border-left: 5px solid transparent; border-bottom: 0px solid transparent; border-right: 5px solid transparent; } +table.dataTable tfoot:empty { + display: none; +} html.dark table.dataTable td.dt-control:before, :root[data-bs-theme=dark] table.dataTable td.dt-control:before, @@ -90,8 +94,8 @@ table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:before { position: absolute; display: block; bottom: 50%; - content: "▲"; - content: "▲"/""; + content: "\25B2"; + content: "\25B2"/""; } table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:after, table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order:after, @@ -99,27 +103,17 @@ table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:after { position: absolute; display: block; top: 50%; - content: "▼"; - content: "▼"/""; -} -table.dataTable thead > tr > th.dt-orderable-asc, table.dataTable thead > tr > th.dt-orderable-desc, table.dataTable thead > tr > th.dt-ordering-asc, table.dataTable thead > tr > th.dt-ordering-desc, -table.dataTable thead > tr > td.dt-orderable-asc, -table.dataTable thead > tr > td.dt-orderable-desc, -table.dataTable thead > tr > td.dt-ordering-asc, -table.dataTable thead > tr > td.dt-ordering-desc { - position: relative; - padding-right: 30px; + content: "\25BC"; + content: "\25BC"/""; } table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order, table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order, table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order, table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order, table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order, table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order { - position: absolute; - right: 12px; - top: 0; - bottom: 0; + position: relative; width: 12px; + height: 20px; } table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order:after, table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order:before, table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:after, table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order:before, @@ -151,7 +145,8 @@ table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:before, table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:after { opacity: 0.6; } -table.dataTable thead > tr > th.sorting_desc_disabled span.dt-column-order:after, table.dataTable thead > tr > th.sorting_asc_disabled span.dt-column-order:before, +table.dataTable thead > tr > th.dt-orderable-none:not(.dt-ordering-asc, .dt-ordering-desc) span.dt-column-order:empty, table.dataTable thead > tr > th.sorting_desc_disabled span.dt-column-order:after, table.dataTable thead > tr > th.sorting_asc_disabled span.dt-column-order:before, +table.dataTable thead > tr > td.dt-orderable-none:not(.dt-ordering-asc, .dt-ordering-desc) span.dt-column-order:empty, table.dataTable thead > tr > td.sorting_desc_disabled span.dt-column-order:after, table.dataTable thead > tr > td.sorting_asc_disabled span.dt-column-order:before { display: none; @@ -161,6 +156,40 @@ table.dataTable thead > tr > td:active { outline: none; } +table.dataTable thead > tr > th div.dt-column-header, +table.dataTable thead > tr > th div.dt-column-footer, +table.dataTable thead > tr > td div.dt-column-header, +table.dataTable thead > tr > td div.dt-column-footer, +table.dataTable tfoot > tr > th div.dt-column-header, +table.dataTable tfoot > tr > th div.dt-column-footer, +table.dataTable tfoot > tr > td div.dt-column-header, +table.dataTable tfoot > tr > td div.dt-column-footer { + display: flex; + justify-content: space-between; + align-items: var(--dt-header-align-items); + gap: 4px; +} +table.dataTable thead > tr > th div.dt-column-header span.dt-column-title, +table.dataTable thead > tr > th div.dt-column-footer span.dt-column-title, +table.dataTable thead > tr > td div.dt-column-header span.dt-column-title, +table.dataTable thead > tr > td div.dt-column-footer span.dt-column-title, +table.dataTable tfoot > tr > th div.dt-column-header span.dt-column-title, +table.dataTable tfoot > tr > th div.dt-column-footer span.dt-column-title, +table.dataTable tfoot > tr > td div.dt-column-header span.dt-column-title, +table.dataTable tfoot > tr > td div.dt-column-footer span.dt-column-title { + flex-grow: 1; +} +table.dataTable thead > tr > th div.dt-column-header span.dt-column-title:empty, +table.dataTable thead > tr > th div.dt-column-footer span.dt-column-title:empty, +table.dataTable thead > tr > td div.dt-column-header span.dt-column-title:empty, +table.dataTable thead > tr > td div.dt-column-footer span.dt-column-title:empty, +table.dataTable tfoot > tr > th div.dt-column-header span.dt-column-title:empty, +table.dataTable tfoot > tr > th div.dt-column-footer span.dt-column-title:empty, +table.dataTable tfoot > tr > td div.dt-column-header span.dt-column-title:empty, +table.dataTable tfoot > tr > td div.dt-column-footer span.dt-column-title:empty { + display: none; +} + div.dt-scroll-body > table.dataTable > thead > tr > th, div.dt-scroll-body > table.dataTable > thead > tr > td { overflow: hidden; @@ -251,10 +280,30 @@ table.dataTable th, table.dataTable td { box-sizing: border-box; } +table.dataTable th.dt-type-numeric, table.dataTable th.dt-type-date, +table.dataTable td.dt-type-numeric, +table.dataTable td.dt-type-date { + text-align: right; +} +table.dataTable th.dt-type-numeric div.dt-column-header, +table.dataTable th.dt-type-numeric div.dt-column-footer, table.dataTable th.dt-type-date div.dt-column-header, +table.dataTable th.dt-type-date div.dt-column-footer, +table.dataTable td.dt-type-numeric div.dt-column-header, +table.dataTable td.dt-type-numeric div.dt-column-footer, +table.dataTable td.dt-type-date div.dt-column-header, +table.dataTable td.dt-type-date div.dt-column-footer { + flex-direction: row-reverse; +} table.dataTable th.dt-left, table.dataTable td.dt-left { text-align: left; } +table.dataTable th.dt-left div.dt-column-header, +table.dataTable th.dt-left div.dt-column-footer, +table.dataTable td.dt-left div.dt-column-header, +table.dataTable td.dt-left div.dt-column-footer { + flex-direction: row; +} table.dataTable th.dt-center, table.dataTable td.dt-center { text-align: center; @@ -263,10 +312,22 @@ table.dataTable th.dt-right, table.dataTable td.dt-right { text-align: right; } +table.dataTable th.dt-right div.dt-column-header, +table.dataTable th.dt-right div.dt-column-footer, +table.dataTable td.dt-right div.dt-column-header, +table.dataTable td.dt-right div.dt-column-footer { + flex-direction: row-reverse; +} table.dataTable th.dt-justify, table.dataTable td.dt-justify { text-align: justify; } +table.dataTable th.dt-justify div.dt-column-header, +table.dataTable th.dt-justify div.dt-column-footer, +table.dataTable td.dt-justify div.dt-column-header, +table.dataTable td.dt-justify div.dt-column-footer { + flex-direction: row; +} table.dataTable th.dt-nowrap, table.dataTable td.dt-nowrap { white-space: nowrap; @@ -276,16 +337,12 @@ table.dataTable td.dt-empty { text-align: center; vertical-align: top; } -table.dataTable th.dt-type-numeric, table.dataTable th.dt-type-date, -table.dataTable td.dt-type-numeric, -table.dataTable td.dt-type-date { - text-align: right; -} table.dataTable thead th, table.dataTable thead td, table.dataTable tfoot th, table.dataTable tfoot td { text-align: left; + vertical-align: var(--dt-header-vertical-align); } table.dataTable thead th.dt-head-left, table.dataTable thead td.dt-head-left, @@ -293,6 +350,16 @@ table.dataTable tfoot th.dt-head-left, table.dataTable tfoot td.dt-head-left { text-align: left; } +table.dataTable thead th.dt-head-left div.dt-column-header, +table.dataTable thead th.dt-head-left div.dt-column-footer, +table.dataTable thead td.dt-head-left div.dt-column-header, +table.dataTable thead td.dt-head-left div.dt-column-footer, +table.dataTable tfoot th.dt-head-left div.dt-column-header, +table.dataTable tfoot th.dt-head-left div.dt-column-footer, +table.dataTable tfoot td.dt-head-left div.dt-column-header, +table.dataTable tfoot td.dt-head-left div.dt-column-footer { + flex-direction: row; +} table.dataTable thead th.dt-head-center, table.dataTable thead td.dt-head-center, table.dataTable tfoot th.dt-head-center, @@ -305,12 +372,32 @@ table.dataTable tfoot th.dt-head-right, table.dataTable tfoot td.dt-head-right { text-align: right; } +table.dataTable thead th.dt-head-right div.dt-column-header, +table.dataTable thead th.dt-head-right div.dt-column-footer, +table.dataTable thead td.dt-head-right div.dt-column-header, +table.dataTable thead td.dt-head-right div.dt-column-footer, +table.dataTable tfoot th.dt-head-right div.dt-column-header, +table.dataTable tfoot th.dt-head-right div.dt-column-footer, +table.dataTable tfoot td.dt-head-right div.dt-column-header, +table.dataTable tfoot td.dt-head-right div.dt-column-footer { + flex-direction: row-reverse; +} table.dataTable thead th.dt-head-justify, table.dataTable thead td.dt-head-justify, table.dataTable tfoot th.dt-head-justify, table.dataTable tfoot td.dt-head-justify { text-align: justify; } +table.dataTable thead th.dt-head-justify div.dt-column-header, +table.dataTable thead th.dt-head-justify div.dt-column-footer, +table.dataTable thead td.dt-head-justify div.dt-column-header, +table.dataTable thead td.dt-head-justify div.dt-column-footer, +table.dataTable tfoot th.dt-head-justify div.dt-column-header, +table.dataTable tfoot th.dt-head-justify div.dt-column-footer, +table.dataTable tfoot td.dt-head-justify div.dt-column-header, +table.dataTable tfoot td.dt-head-justify div.dt-column-footer { + flex-direction: row; +} table.dataTable thead th.dt-head-nowrap, table.dataTable thead td.dt-head-nowrap, table.dataTable tfoot th.dt-head-nowrap, @@ -338,6 +425,14 @@ table.dataTable tbody td.dt-body-nowrap { white-space: nowrap; } +:root { + --dt-row-hover-alpha: 0.035; + --dt-row-stripe-alpha: 0.023; + --dt-column-ordering-alpha: 0.019; + --dt-row-selected-stripe-alpha: 0.923; + --dt-row-selected-column-ordering-alpha: 0.919; +} + /* * Table styles */ @@ -386,7 +481,7 @@ table.dataTable > tbody > tr.selected > * { color: rgb(var(--dt-row-selected-text)); } table.dataTable > tbody > tr.selected a { - color: rgb(9, 10, 11); + color: rgb(228, 228, 228); color: rgb(var(--dt-row-selected-link)); } table.dataTable > tbody > tr > th, @@ -415,15 +510,15 @@ table.dataTable.cell-border > tbody > tr:first-child > * { } table.dataTable.stripe > tbody > tr:nth-child(odd) > *, table.dataTable.display > tbody > tr:nth-child(odd) > * { box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.023); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-stripe), 0.023); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-stripe), var(--dt-row-stripe-alpha)); } table.dataTable.stripe > tbody > tr:nth-child(odd).selected > *, table.dataTable.display > tbody > tr:nth-child(odd).selected > * { box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.923); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.923); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), var(--dt-row-selected-stripe-alpha)); } table.dataTable.hover > tbody > tr:hover > *, table.dataTable.display > tbody > tr:hover > * { box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.035); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.035); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), var(--dt-row-hover-alpha)); } table.dataTable.hover > tbody > tr.selected:hover > *, table.dataTable.display > tbody > tr.selected:hover > * { box-shadow: inset 0 0 0 9999px #0d6efd !important; @@ -435,7 +530,7 @@ table.dataTable.order-column > tbody tr > .sorting_3, table.dataTable.display > table.dataTable.display > tbody tr > .sorting_2, table.dataTable.display > tbody tr > .sorting_3 { box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.019); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.019); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), var(--dt-column-ordering-alpha)); } table.dataTable.order-column > tbody tr.selected > .sorting_1, table.dataTable.order-column > tbody tr.selected > .sorting_2, @@ -443,79 +538,55 @@ table.dataTable.order-column > tbody tr.selected > .sorting_3, table.dataTable.d table.dataTable.display > tbody tr.selected > .sorting_2, table.dataTable.display > tbody tr.selected > .sorting_3 { box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.919); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.919); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), var(--dt-row-selected-column-ordering-alpha)); } table.dataTable.display > tbody > tr:nth-child(odd) > .sorting_1, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd) > .sorting_1 { box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.054); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.054); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), calc(var(--dt-row-stripe-alpha) + var(--dt-column-ordering-alpha))); } table.dataTable.display > tbody > tr:nth-child(odd) > .sorting_2, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd) > .sorting_2 { box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.047); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.047); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), calc(var(--dt-row-stripe-alpha) + var(--dt-column-ordering-alpha) - 0.007)); } table.dataTable.display > tbody > tr:nth-child(odd) > .sorting_3, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd) > .sorting_3 { box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.039); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.039); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), calc(var(--dt-row-stripe-alpha) + var(--dt-column-ordering-alpha) - 0.015)); } table.dataTable.display > tbody > tr:nth-child(odd).selected > .sorting_1, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd).selected > .sorting_1 { box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.954); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.954); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), calc(var(--dt-row-selected-stripe-alpha) + var(--dt-column-ordering-alpha))); } table.dataTable.display > tbody > tr:nth-child(odd).selected > .sorting_2, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd).selected > .sorting_2 { box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.947); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.947); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), calc(var(--dt-row-selected-stripe-alpha) + var(--dt-column-ordering-alpha) - 0.007)); } table.dataTable.display > tbody > tr:nth-child(odd).selected > .sorting_3, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd).selected > .sorting_3 { box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.939); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.939); -} -table.dataTable.display > tbody > tr.even > .sorting_1, table.dataTable.order-column.stripe > tbody > tr.even > .sorting_1 { - box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.019); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.019); -} -table.dataTable.display > tbody > tr.even > .sorting_2, table.dataTable.order-column.stripe > tbody > tr.even > .sorting_2 { - box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.011); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.011); -} -table.dataTable.display > tbody > tr.even > .sorting_3, table.dataTable.order-column.stripe > tbody > tr.even > .sorting_3 { - box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.003); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.003); -} -table.dataTable.display > tbody > tr.even.selected > .sorting_1, table.dataTable.order-column.stripe > tbody > tr.even.selected > .sorting_1 { - box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.919); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.919); -} -table.dataTable.display > tbody > tr.even.selected > .sorting_2, table.dataTable.order-column.stripe > tbody > tr.even.selected > .sorting_2 { - box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.911); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.911); -} -table.dataTable.display > tbody > tr.even.selected > .sorting_3, table.dataTable.order-column.stripe > tbody > tr.even.selected > .sorting_3 { - box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.903); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.903); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), calc(var(--dt-row-selected-stripe-alpha) + var(--dt-column-ordering-alpha) - 0.015)); } table.dataTable.display tbody tr:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1 { box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.082); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.082); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), calc(var(--dt-row-stripe-alpha) + var(--dt-column-ordering-alpha) + var(--dt-row-hover-alpha))); } table.dataTable.display tbody tr:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2 { box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.074); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.074); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), calc(var(--dt-row-stripe-alpha) + var(--dt-column-ordering-alpha) + var(--dt-row-hover-alpha) - 0.007)); } table.dataTable.display tbody tr:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3 { box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.062); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.062); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), calc(var(--dt-row-stripe-alpha) + var(--dt-column-ordering-alpha) + var(--dt-row-hover-alpha) - 0.015)); } table.dataTable.display tbody tr:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 { box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.982); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.982); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), calc(var(--dt-row-selected-stripe-alpha) + var(--dt-column-ordering-alpha))); } table.dataTable.display tbody tr:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 { box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.974); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.974); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), calc(var(--dt-row-selected-stripe-alpha) + var(--dt-column-ordering-alpha) + var(--dt-row-hover-alpha) - 0.007)); } table.dataTable.display tbody tr:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 { box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.962); - box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.962); + box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), calc(var(--dt-row-selected-stripe-alpha) + var(--dt-column-ordering-alpha) + var(--dt-row-hover-alpha) - 0.015)); } table.dataTable.compact thead th, table.dataTable.compact thead td, @@ -914,7 +985,7 @@ div.dt-button-collection .dt-button-active:after { margin-top: -10px; right: 1em; display: inline-block; - content: "✓"; + content: "\2713"; color: inherit; } div.dt-button-collection .dt-button-active.dt-button-split { @@ -932,7 +1003,7 @@ div.dt-button-collection .dt-button-active.dt-button-split > *:first-child:after margin-top: -10px; right: 1em; display: inline-block; - content: "✓"; + content: "\2713"; color: inherit; } div.dt-button-collection .dt-button-active-a a { @@ -942,7 +1013,7 @@ div.dt-button-collection .dt-button-active-a a:after { position: absolute; right: 1em; display: inline-block; - content: "✓"; + content: "\2713"; color: inherit; } div.dt-button-collection span.dt-button-spacer { @@ -966,11 +1037,6 @@ div.dt-button-collection span.dt-button-spacer.bar { box-shadow: none !important; } } -html.dark div.dt-button-info { - background-color: var(--dt-html-background); - border: 1px solid rgba(255, 255, 255, 0.15); -} - div.dt-buttons > .dt-button, div.dt-buttons > div.dt-button-split .dt-button { position: relative; @@ -1102,8 +1168,10 @@ div.dt-button-collection .dt-button { left: 0; right: 0; width: 100%; - display: block; + display: flex; float: none; + justify-content: space-between; + align-items: center; background: none; margin: 0; padding: 0.5em 1em; @@ -1125,6 +1193,9 @@ div.dt-button-collection .dt-button:hover:not(.disabled) { background: rgba(153, 153, 153, 0.1); box-shadow: none; } +div.dt-button-collection .dt-button:focus { + outline-offset: -2px; +} div.dt-button-collection div.dt-button-split { display: flex; flex-direction: row; @@ -1192,10 +1263,6 @@ div.dt-button-collection.fixed > :last-child { } div.dt-button-collection.two-column > :last-child, div.dt-button-collection.three-column > :last-child, div.dt-button-collection.four-column > :last-child { display: block !important; - -webkit-column-gap: 8px; - -moz-column-gap: 8px; - -ms-column-gap: 8px; - -o-column-gap: 8px; column-gap: 8px; } div.dt-button-collection.two-column > :last-child > *, div.dt-button-collection.three-column > :last-child > *, div.dt-button-collection.four-column > :last-child > * { @@ -1352,6 +1419,10 @@ html.dark div.dt-button-collection { background-color: rgb(33, 37, 41); box-shadow: 3px 4px 10px 1px rgba(0, 0, 0, 0.8); } +html.dark div.dt-button-info { + background-color: var(--dt-html-background); + border: 1px solid rgba(255, 255, 255, 0.15); +} table.dataTable.dtr-inline.collapsed > tbody > tr > td.child, diff --git a/koha-tmpl/opac-tmpl/lib/datatables/datatables.js b/koha-tmpl/opac-tmpl/lib/datatables/datatables.js index fd92886f833..03b7613ac22 100644 --- a/koha-tmpl/opac-tmpl/lib/datatables/datatables.js +++ b/koha-tmpl/opac-tmpl/lib/datatables/datatables.js @@ -4,34 +4,16 @@ * * To rebuild or modify this file with the latest versions of the included * software please visit: - * https://datatables.net/download/#dt/dt-2.1.8/b-3.1.2/b-colvis-3.1.2/b-html5-3.1.2/b-print-3.1.2/r-3.0.3 + * https://datatables.net/download/#dt/dt-2.3.4/b-3.2.5/b-colvis-3.2.5/b-html5-3.2.5/b-print-3.2.5/r-3.0.7 * * Included libraries: - * DataTables 2.1.8, Buttons 3.1.2, Column visibility 3.1.2, HTML5 export 3.1.2, Print view 3.1.2, Responsive 3.0.3 + * DataTables 2.3.4, Buttons 3.2.5, Column visibility 3.2.5, HTML5 export 3.2.5, Print view 3.2.5, Responsive 3.0.7 */ -/*! DataTables 2.1.8 +/*! DataTables 2.3.4 * © SpryMedia Ltd - datatables.net/license */ -/** - * @summary DataTables - * @description Paginate, search and order HTML tables - * @version 2.1.8 - * @author SpryMedia Ltd - * @contact www.datatables.net - * @copyright SpryMedia Ltd. - * - * This source file is free software, available under the following license: - * MIT license - https://datatables.net/license - * - * This source file is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. - * - * For details please refer to: https://www.datatables.net - */ - (function( factory ) { "use strict"; @@ -119,15 +101,19 @@ var defaults = DataTable.defaults; var $this = $(this); - - /* Sanity check */ + // Sanity check if ( this.nodeName.toLowerCase() != 'table' ) { _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 ); return; } - $(this).trigger( 'options.dt', oInit ); + // Special case for options + if (oInit.on && oInit.on.options) { + _fnListener($this, 'options', oInit.on.options); + } + + $this.trigger( 'options.dt', oInit ); /* Backwards compatibility for the defaults */ _fnCompatOpts( defaults ); @@ -138,7 +124,7 @@ _fnCamelToHungarian( defaults.column, defaults.column, true ); /* Setting up the initialisation object */ - _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true ); + _fnCamelToHungarian( defaults, $.extend( oInit, _fnEscapeObject($this.data()) ), true ); @@ -192,6 +178,9 @@ this.id = sId; } + // Replacing an existing colgroup with our own. Not ideal, but a merge could take a lot of code + $this.children('colgroup').remove(); + /* Create the settings object for this table and set some of the default parameters */ var oSettings = $.extend( true, {}, DataTable.models.oSettings, { "sDestroyWidth": $this[0].style.width, @@ -266,6 +255,9 @@ "caption", "layout", "orderDescReverse", + "orderIndicators", + "orderHandler", + "titleRow", "typeDetect", [ "iCookieDuration", "iStateDuration" ], // backwards compat [ "oSearch", "oPreviousSearch" ], @@ -294,6 +286,13 @@ oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId ); + // Add event listeners + if (oInit.on) { + Object.keys(oInit.on).forEach(function (key) { + _fnListener($this, key, oInit.on[key]); + }); + } + /* Browser support detection */ _fnBrowserDetect( oSettings ); @@ -354,7 +353,7 @@ /* HTML5 attribute detection - build an mData object automatically if the * attributes are found */ - var rowOne = $this.children('tbody').find('tr').eq(0); + var rowOne = $this.children('tbody').find('tr:first-child').eq(0); if ( rowOne.length ) { var a = function ( cell, name ) { @@ -441,7 +440,6 @@ thead = $('').appendTo($this); } oSettings.nTHead = thead[0]; - $('tr', thead).addClass(oClasses.thead.row); var tbody = $this.children('tbody'); if ( tbody.length === 0 ) { @@ -456,7 +454,6 @@ tfoot = $('').appendTo($this); } oSettings.nTFoot = tfoot[0]; - $('tr', tfoot).addClass(oClasses.tfoot.row); // Copy the data index array oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); @@ -514,6 +511,13 @@ * @namespace */ DataTable.ext = _ext = { + /** + * DataTables build type (expanded by the download builder) + * + * @type string + */ + builder: "dt/dt-2.3.4/b-3.2.5/b-colvis-3.2.5/b-html5-3.2.5/b-print-3.2.5/r-3.0.7", + /** * Buttons. For use with the Buttons extension for DataTables. This is * defined here so other extensions can define buttons regardless of load @@ -526,20 +530,20 @@ /** - * Element class names + * ColumnControl buttons and content * * @type object - * @default {} */ - classes: {}, + ccContent: {}, /** - * DataTables build type (expanded by the download builder) + * Element class names * - * @type string + * @type object + * @default {} */ - builder: "dt/dt-2.1.8/b-3.1.2/b-colvis-3.1.2/b-html5-3.1.2/b-print-3.1.2/r-3.0.3", + classes: {}, /** @@ -553,6 +557,11 @@ */ errMode: "alert", + /** HTML entity escaping */ + escape: { + /** When reading data-* attributes for initialisation options */ + attributes: false + }, /** * Legacy so v1 plug-ins don't throw js errors on load @@ -737,7 +746,7 @@ * * The extension options for ordering of data available here is complimentary * to the default type based ordering that DataTables typically uses. It - * allows much greater control over the the data that is being used to + * allows much greater control over the data that is being used to * order a column, but is necessarily therefore more complex. * * This type of ordering is useful if you want to do ordering based on data @@ -896,7 +905,7 @@ * `{type}-asc` and `{type}-desc` together. It is generally recommended * that only `{type}-pre` is used, as this provides the optimal * implementation in terms of speed, although the others are provided - * for compatibility with existing Javascript sort functions. + * for compatibility with existing JavaScript sort functions. * * `{type}-pre`: Functions defined take a single parameter: * @@ -906,7 +915,7 @@ * * * `{*}` Data to be sorted upon * - * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort + * `{type}-asc` and `{type}-desc`: Functions are typical JavaScript sort * functions, taking two parameters: * * 1. `{*}` Data to compare to the second parameter @@ -1130,7 +1139,7 @@ }; // Convert from a formatted number with characters other than `.` as the - // decimal place, to a Javascript number + // decimal place, to a JavaScript number var _numToDecimal = function ( num, decimalPoint ) { // Cache created regular expressions for speed as this function is called often if ( ! _re_dic[ decimalPoint ] ) { @@ -1196,19 +1205,19 @@ var _pluck = function ( a, prop, prop2 ) { var out = []; - var i=0, ien=a.length; + var i=0, iLen=a.length; // Could have the test in the loop for slightly smaller code, but speed // is essential here if ( prop2 !== undefined ) { - for ( ; i') .html( columns[i][titleProp] || '' ) .appendTo( row ); @@ -3254,9 +3291,11 @@ if (side === 'header') { settings.aoHeader = detected; + $('tr', target).addClass(classes.thead.row); } else { settings.aoFooter = detected; + $('tr', target).addClass(classes.tfoot.row); } // Every cell needs to be passed through the renderer @@ -3274,7 +3313,7 @@ * @param {*} settings DataTables settings * @param {*} source Source layout array * @param {*} incColumns What columns should be included - * @returns Layout array + * @returns Layout array in column index order */ function _fnHeaderLayout( settings, source, incColumns ) { @@ -3558,7 +3597,9 @@ _fnDraw( settings ); - settings._drawHold = false; + settings.api.one('draw', function () { + settings._drawHold = false; + }); } @@ -3570,10 +3611,9 @@ var zero = oLang.sZeroRecords; var dataSrc = _fnDataSource( settings ); - if ( - (settings.iDraw < 1 && dataSrc === 'ssp') || - (settings.iDraw <= 1 && dataSrc === 'ajax') - ) { + // Make use of the fact that settings.json is only set once the initial data has + // been loaded. Show loading when that isn't the case + if ((dataSrc === 'ssp' || dataSrc === 'ajax') && ! settings.json) { zero = oLang.sLoadingRecords; } else if ( oLang.sEmptyTable && settings.fnRecordsTotal() === 0 ) @@ -3583,7 +3623,7 @@ return $( '' ) .append( $('', { - 'colSpan': _fnVisbleColumns( settings ), + 'colSpan': _fnVisibleColumns( settings ), 'class': settings.oClasses.empty.row } ).html( zero ) )[0]; } @@ -3767,7 +3807,7 @@ var line = row[ item ].contents; - for ( var i=0, ien=line.length ; i') .addClass('dt-column-order') .appendTo(cell); } + + // We need to wrap the elements in the header in another element to use flexbox + // layout for those elements + var headerFooter = isHeader ? 'header' : 'footer'; + + if ( $('span.dt-column-' + headerFooter, cell).length === 0) { + $('
') + .addClass('dt-column-' + headerFooter) + .append(cell.childNodes) + .appendTo(cell); + } } // If there is col / rowspan, copy the information into the layout grid @@ -4107,24 +4173,21 @@ * DataTables - may be augmented by developer callbacks * @param {function} fn Callback function to run when data is obtained */ - function _fnBuildAjax( oSettings, data, fn ) - { + function _fnBuildAjax(oSettings, data, fn) { var ajaxData; var ajax = oSettings.ajax; var instance = oSettings.oInstance; - var callback = function ( json ) { - var status = oSettings.jqXHR - ? oSettings.jqXHR.status - : null; + var callback = function (json) { + var status = oSettings.jqXHR ? oSettings.jqXHR.status : null; - if ( json === null || (typeof status === 'number' && status == 204 ) ) { + if (json === null || (typeof status === 'number' && status == 204)) { json = {}; - _fnAjaxDataSrc( oSettings, json, [] ); + _fnAjaxDataSrc(oSettings, json, []); } var error = json.error || json.sError; - if ( error ) { - _fnLog( oSettings, 0, error ); + if (error) { + _fnLog(oSettings, 0, error); } // Microsoft often wrap JSON as a string in another JSON object @@ -4132,30 +4195,27 @@ if (json.d && typeof json.d === 'string') { try { json = JSON.parse(json.d); - } - catch (e) { + } catch (e) { // noop } } oSettings.json = json; - _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR], true ); - fn( json ); + _fnCallbackFire(oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR], true); + fn(json); }; - if ( $.isPlainObject( ajax ) && ajax.data ) - { + if ($.isPlainObject(ajax) && ajax.data) { ajaxData = ajax.data; - var newData = typeof ajaxData === 'function' ? - ajaxData( data, oSettings ) : // fn can manipulate data or return - ajaxData; // an object object or array to merge + var newData = + typeof ajaxData === 'function' + ? ajaxData(data, oSettings) // fn can manipulate data or return + : ajaxData; // an object or array to merge // If the function returned something, use that alone - data = typeof ajaxData === 'function' && newData ? - newData : - $.extend( true, data, newData ); + data = typeof ajaxData === 'function' && newData ? newData : $.extend(true, data, newData); // Remove the data property as we've resolved it already and don't want // jQuery to do it again (it is restored at the end of the function) @@ -4163,87 +4223,88 @@ } var baseAjax = { - "url": typeof ajax === 'string' ? - ajax : - '', - "data": data, - "success": callback, - "dataType": "json", - "cache": false, - "type": oSettings.sServerMethod, - "error": function (xhr, error) { - var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR], true ); - - if ( ret.indexOf(true) === -1 ) { - if ( error == "parsererror" ) { - _fnLog( oSettings, 0, 'Invalid JSON response', 1 ); + url: typeof ajax === 'string' ? ajax : '', + data: data, + success: callback, + dataType: 'json', + cache: false, + type: oSettings.sServerMethod, + error: function (xhr, error) { + var ret = _fnCallbackFire( + oSettings, + null, + 'xhr', + [oSettings, null, oSettings.jqXHR], + true + ); + + if (ret.indexOf(true) === -1) { + if (error == 'parsererror') { + _fnLog(oSettings, 0, 'Invalid JSON response', 1); } - else if ( xhr.readyState === 4 ) { - _fnLog( oSettings, 0, 'Ajax error', 7 ); + else if (xhr.readyState === 4) { + _fnLog(oSettings, 0, 'Ajax error', 7); } } - _fnProcessingDisplay( oSettings, false ); + _fnProcessingDisplay(oSettings, false); } }; // If `ajax` option is an object, extend and override our default base - if ( $.isPlainObject( ajax ) ) { - $.extend( baseAjax, ajax ) + if ($.isPlainObject(ajax)) { + $.extend(baseAjax, ajax); } // Store the data submitted for the API oSettings.oAjaxData = data; // Allow plug-ins and external processes to modify the data - _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data, baseAjax], true ); + _fnCallbackFire(oSettings, null, 'preXhr', [oSettings, data, baseAjax], true); - if ( typeof ajax === 'function' ) - { + // Custom Ajax option to submit the parameters as a JSON string + if (baseAjax.submitAs === 'json' && typeof data === 'object') { + baseAjax.data = JSON.stringify(data); + } + + if (typeof ajax === 'function') { // Is a function - let the caller define what needs to be done - oSettings.jqXHR = ajax.call( instance, data, callback, oSettings ); + oSettings.jqXHR = ajax.call(instance, data, callback, oSettings); } else if (ajax.url === '') { // No url, so don't load any data. Just apply an empty data array // to the object for the callback. var empty = {}; - DataTable.util.set(ajax.dataSrc)(empty, []); + _fnAjaxDataSrc(oSettings, empty, []); callback(empty); } else { // Object to extend the base settings - oSettings.jqXHR = $.ajax( baseAjax ); + oSettings.jqXHR = $.ajax(baseAjax); } // Restore for next time around - if ( ajaxData ) { + if (ajaxData) { ajax.data = ajaxData; } } - /** * Update the table using an Ajax call * @param {object} settings dataTables settings object * @returns {boolean} Block the table drawing or not * @memberof DataTable#oApi */ - function _fnAjaxUpdate( settings ) - { + function _fnAjaxUpdate(settings) { settings.iDraw++; - _fnProcessingDisplay( settings, true ); + _fnProcessingDisplay(settings, true); - _fnBuildAjax( - settings, - _fnAjaxParameters( settings ), - function(json) { - _fnAjaxUpdateDraw( settings, json ); - } - ); + _fnBuildAjax(settings, _fnAjaxParameters(settings), function (json) { + _fnAjaxUpdateDraw(settings, json); + }); } - /** * Build up the parameters in an object needed for a server-side processing * request. @@ -4251,22 +4312,18 @@ * @returns {bool} block the table drawing or not * @memberof DataTable#oApi */ - function _fnAjaxParameters( settings ) - { - var - columns = settings.aoColumns, + function _fnAjaxParameters(settings) { + var columns = settings.aoColumns, features = settings.oFeatures, preSearch = settings.oPreviousSearch, preColSearch = settings.aoPreSearchCols, - colData = function ( idx, prop ) { - return typeof columns[idx][prop] === 'function' ? - 'function' : - columns[idx][prop]; + colData = function (idx, prop) { + return typeof columns[idx][prop] === 'function' ? 'function' : columns[idx][prop]; }; return { draw: settings.iDraw, - columns: columns.map( function ( column, i ) { + columns: columns.map(function (column, i) { return { data: colData(i, 'mData'), name: column.sName, @@ -4275,40 +4332,43 @@ search: { value: preColSearch[i].search, regex: preColSearch[i].regex, - fixed: Object.keys(column.searchFixed).map( function(name) { - return { - name: name, - term: column.searchFixed[name].toString() - } - }) + fixed: Object.keys(column.searchFixed) + .map(function (name) { + return { + name: name, + term: typeof column.searchFixed[name] !== 'function' + ? column.searchFixed[name].toString() + : 'function' + }; + }) } }; - } ), - order: _fnSortFlatten( settings ).map( function ( val ) { + }), + order: _fnSortFlatten(settings).map(function (val) { return { column: val.col, dir: val.dir, name: colData(val.col, 'sName') }; - } ), + }), start: settings._iDisplayStart, - length: features.bPaginate ? - settings._iDisplayLength : - -1, + length: features.bPaginate ? settings._iDisplayLength : -1, search: { value: preSearch.search, regex: preSearch.regex, - fixed: Object.keys(settings.searchFixed).map( function(name) { - return { - name: name, - term: settings.searchFixed[name].toString() - } - }) + fixed: Object.keys(settings.searchFixed) + .map(function (name) { + return { + name: name, + term: typeof settings.searchFixed[name] !== 'function' + ? settings.searchFixed[name].toString() + : 'function' + }; + }) } }; } - /** * Data the data from the server (nuking the old) and redraw the table * @param {object} oSettings dataTables settings object @@ -4320,42 +4380,40 @@ * @param {string} [json.sColumns] Column ordering (sName, comma separated) * @memberof DataTable#oApi */ - function _fnAjaxUpdateDraw ( settings, json ) - { + function _fnAjaxUpdateDraw(settings, json) { var data = _fnAjaxDataSrc(settings, json); var draw = _fnAjaxDataSrcParam(settings, 'draw', json); var recordsTotal = _fnAjaxDataSrcParam(settings, 'recordsTotal', json); var recordsFiltered = _fnAjaxDataSrcParam(settings, 'recordsFiltered', json); - if ( draw !== undefined ) { + if (draw !== undefined) { // Protect against out of sequence returns - if ( draw*1 < settings.iDraw ) { + if (draw * 1 < settings.iDraw) { return; } settings.iDraw = draw * 1; } // No data in returned object, so rather than an array, we show an empty table - if ( ! data ) { + if (!data) { data = []; } - _fnClearTable( settings ); - settings._iRecordsTotal = parseInt(recordsTotal, 10); + _fnClearTable(settings); + settings._iRecordsTotal = parseInt(recordsTotal, 10); settings._iRecordsDisplay = parseInt(recordsFiltered, 10); - for ( var i=0, ien=data.length ; i col is set to and correct if needed @@ -5273,6 +5327,10 @@ if (colWidth !== colSizes[i].width) { colEl.style.width = colSizes[i].width + 'px'; + + if (scroll.sX) { + colEl.style.minWidth = colSizes[i].width + 'px'; + } } } } @@ -5307,7 +5365,7 @@ } // 4. Clean up - // Figure out if there are scrollbar present - if so then we need a the header and footer to + // Figure out if there are scrollbar present - if so then we need the header and footer to // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar) var isScrolling = Math.floor(table.height()) > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll"; var paddingSide = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' ); @@ -5365,6 +5423,14 @@ i, column, columnIdx; var styleWidth = table.style.width; + var containerWidth = _fnWrapperWidth(settings); + + // Don't re-run for the same width as the last time + if (containerWidth === settings.containerWidth) { + return false; + } + + settings.containerWidth = containerWidth; // If there is no width applied as a CSS style or as an attribute, we assume that // the width is intended to be 100%, which is usually is in CSS, but it is very @@ -5397,7 +5463,7 @@ .removeAttr( 'id' ); // Clean up the table body - tmpTable.append('') + tmpTable.append('') var tr = $('').appendTo( tmpTable.find('tbody') ); // Clone the table header and footer - we can't use the header / footer @@ -5422,6 +5488,8 @@ // browser will collapse it. If this width is smaller than the // width the column requires, then it will have no effect if ( scrollX ) { + this.style.minWidth = width; + $( this ).append( $('
').css( { width: width, margin: 0, @@ -5490,15 +5558,15 @@ // If there is no width attribute or style, then allow the table to // collapse - if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) { - tmpTable.width( tableContainer.clientWidth ); + if ( tmpTable.outerWidth() < tableContainer.clientWidth && tableWidthAttr ) { + tmpTable.outerWidth( tableContainer.clientWidth ); } } else if ( scrollY ) { - tmpTable.width( tableContainer.clientWidth ); + tmpTable.outerWidth( tableContainer.clientWidth ); } else if ( tableWidthAttr ) { - tmpTable.width( tableWidthAttr ); + tmpTable.outerWidth( tableWidthAttr ); } // Get the width of each column in the constructed table @@ -5531,20 +5599,64 @@ } if ( (tableWidthAttr || scrollX) && ! settings._reszEvt ) { - var bindResize = function () { - $(window).on('resize.DT-'+settings.sInstance, DataTable.util.throttle( function () { - if (! settings.bDestroying) { - _fnAdjustColumnSizing( settings ); + var resize = DataTable.util.throttle( function () { + var newWidth = _fnWrapperWidth(settings); + + // Don't do it if destroying or the container width is 0 + if (! settings.bDestroying && newWidth !== 0) { + _fnAdjustColumnSizing( settings ); + } + } ); + + // For browsers that support it (~2020 onwards for wide support) we can watch for the + // container changing width. + if (window.ResizeObserver) { + // This is a tricky beast - if the element is visible when `.observe()` is called, + // then the callback is immediately run. Which we don't want. If the element isn't + // visible, then it isn't run, but we want it to run when it is then made visible. + // This flag allows the above to be satisfied. + var first = $(settings.nTableWrapper).is(':visible'); + + // Use an empty div to attach the observer so it isn't impacted by height changes + var resizer = $('
') + .css({ + width: '100%', + height: 0 + }) + .addClass('dt-autosize') + .appendTo(settings.nTableWrapper); + + settings.resizeObserver = new ResizeObserver(function (e) { + if (first) { + first = false; } - } ) ); - }; + else { + resize(); + } + }); - bindResize(); + settings.resizeObserver.observe(resizer[0]); + } + else { + // For old browsers, the best we can do is listen for a window resize + $(window).on('resize.DT-'+settings.sInstance, resize); + } settings._reszEvt = true; } } + /** + * Get the width of the DataTables wrapper element + * + * @param {*} settings DataTables settings object + * @returns Width + */ + function _fnWrapperWidth(settings) { + return $(settings.nTableWrapper).is(':visible') + ? $(settings.nTableWrapper).width() + : 0; + } /** * Get the maximum strlen for each data column @@ -5560,7 +5672,7 @@ if (! column.maxLenString) { var s, max='', maxLen = -1; - for ( var i=0, ien=settings.aiDisplayMaster.length ; i= columns.length ? - [ 0, col[1] ] : - col - ); + var set = [ col[0], col[1] ]; + + // A column name was stored and should be used for restore + if (typeof col[0] === 'string') { + // Find the name from the current list of column names + var idx = currentNames.indexOf(col[0]); + + if (idx < 0) { + // If the column was not found ignore it and continue + return; + } + + set[0] = idx; + } + else if (set[0] >= columns.length) { + // If the column index is out of bounds ignore it and continue + return; + } + + settings.aaSorting.push(set); } ); } @@ -6292,30 +6440,66 @@ // Columns if ( s.columns ) { - for ( i=0, ien=s.columns.length ; i= 0) { + set.push(s.columns[idx]); + } + else { + // No matching column name in the state's columns, so this might be a new + // column and thus can't have a state already. + set.push({}); + } } else { - columns[i].bVisible = col.visible; + // If no name, but other columns did have a name, then there is no knowing + // where this one came from originally so it can't be restored. + set.push({}); } } + } + + // If the number of columns to restore is different from current, then all bets are off. + if (set.length === columns.length) { + for ( i=0, iLen=set.length ; i 1 && // prevent infinite - $(host).height() >= ($(buttonEls[0]).outerHeight() * 2) - 10 - ) { - _pagingDraw(settings, host, $.extend({}, opts, { buttons: opts.buttons - 2 })); + if (buttonEls.length) { + var outerHeight = $(buttonEls[0]).outerHeight(); + + if ( + opts.buttons > 1 && // prevent infinite + outerHeight > 0 && // will be 0 if hidden + $(host).height() >= (outerHeight * 2) - 10 + ) { + _pagingDraw(settings, host, $.extend({}, opts, { buttons: opts.buttons - 2 })); + } } } @@ -13336,7 +13795,6 @@ switch ( button ) { case 'ellipsis': o.display = '…'; - o.disabled = true; break; case 'first': @@ -13523,7 +13981,7 @@ // Save text node content for macro updating var textNodes = []; - Array.from(div.find('label')[0].childNodes).forEach(function (el) { + Array.prototype.slice.call(div.find('label')[0].childNodes).forEach(function (el) { if (el.nodeType === Node.TEXT_NODE) { textNodes.push({ el: el, @@ -13541,18 +13999,22 @@ // Next, the select itself, along with the options var select = $('