diff --git a/src/resources/assets/css/common.css b/src/resources/assets/css/common.css
index 9c79cc1fc8..b42d7b55b3 100644
--- a/src/resources/assets/css/common.css
+++ b/src/resources/assets/css/common.css
@@ -61,9 +61,50 @@ form .select2.select2-container {
}
/*Table - List View*/
+.dataTables_wrapper {
+ position: relative;
+ isolation: isolate;
+}
+
.dataTables_wrapper div.row .col-sm-12 {
position: relative;
}
+
+.dataTables_wrapper .table-responsive {
+ position: relative;
+}
+
+.dataTables_wrapper table.dataTable {
+ position: relative;
+ z-index: 1;
+}
+
+/* Ensure any processing indicator within or related to table wrapper covers full area */
+.dataTables_wrapper,
+div[id$="_wrapper"] {
+ position: relative !important;
+}
+
+.dataTables_wrapper > .dataTables_processing,
+.dataTables_wrapper > .dt-processing,
+.dataTables_wrapper .dataTables_processing,
+.dataTables_wrapper .dt-processing,
+div[id$="_wrapper"] > .dataTables_processing,
+div[id$="_wrapper"] > .dt-processing,
+div[id$="_wrapper"] .dataTables_processing,
+div[id$="_wrapper"] .dt-processing {
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ bottom: 60px !important;
+ width: 100% !important;
+ height: calc(100% - 60px) !important;
+ transform: none !important;
+ margin: 0 !important;
+ z-index: 1000 !important;
+ inset: unset !important;
+}
.navbar-filters {
min-height: 25px;
border-radius: 0;
@@ -629,42 +670,59 @@ table.dataTable tr th:first-child, table.dataTable tr td:first-child, table.data
padding-left: 0.6rem;
}
+/* Processing indicator - global styles */
.dataTables_processing,
.dt-processing {
+ position: absolute !important;
background: rgba(255, 255, 255, 0.8) !important;
- color: transparent !important; /* Hide any text */
border: none !important;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1) !important;
- border-radius: 5px !important;
- width: 100% !important;
- height: 100% !important;
- position: absolute !important;
- top: 0 !important;
- left: 0 !important;
- transform: none !important;
- margin: 0 !important;
+ box-shadow: none !important;
+ border-radius: 0 !important;
padding: 0 !important;
- z-index: 999 !important;
+ z-index: 1000 !important;
display: flex !important;
justify-content: center !important;
align-items: center !important;
+ overflow: hidden !important;
+ /* Aggressive text hiding */
+ font-size: 0 !important;
+ line-height: 0 !important;
+ color: transparent !important;
+ text-indent: -9999px !important;
+ white-space: nowrap !important;
+ text-shadow: none !important;
+ text-decoration: none !important;
}
+/* Hide ALL text content and children */
+.dataTables_processing *:not(img),
+.dt-processing *:not(img),
+.dataTables_processing::before,
+.dataTables_processing::after,
+.dt-processing::before,
+.dt-processing::after {
+ display: none !important;
+ visibility: hidden !important;
+ opacity: 0 !important;
+ font-size: 0 !important;
+ color: transparent !important;
+ text-indent: -9999px !important;
+}
+
+/* Show only spinner image */
.dataTables_processing img,
.dt-processing img {
display: block !important;
- width: 30px !important;
- height: 30px !important;
+ width: 40px !important;
+ height: 40px !important;
opacity: 1 !important;
visibility: visible !important;
margin: 0 auto !important;
+ position: relative !important;
+ z-index: 1001 !important;
}
-.dataTables_processing > *:not(img),
-.dt-processing > *:not(img) {
- display: none !important;
-}
-
+/* Hide when not active */
.dataTables_processing:not([style*="block"]),
.dt-processing:not([style*="block"]) {
display: none !important;
@@ -812,10 +870,6 @@ div.dt-scroll-body {
margin-bottom: 0;
}
-.dt-buttons {
- margin-bottom: 8px;
-}
-
/* Adjust table headers */
.dataTable thead th {
font-size: 0.70em;
@@ -823,7 +877,7 @@ div.dt-scroll-body {
}
/* Make export and column visibility buttons smaller */
-.dataTables_wrapper .dt-buttons .btn {
+.dt-container .dt-buttons .btn-group .btn {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
}
diff --git a/src/resources/views/crud/components/datatable/datatable_logic.blade.php b/src/resources/views/crud/components/datatable/datatable_logic.blade.php
index 314cf7a8c1..52219ef39d 100644
--- a/src/resources/views/crud/components/datatable/datatable_logic.blade.php
+++ b/src/resources/views/crud/components/datatable/datatable_logic.blade.php
@@ -305,10 +305,23 @@ functionsToRunOnDataTablesDrawEvent: [],
"colvis": "{{ trans('backpack::crud.export.column_visibility') }}"
},
},
- dom:
- "<'row hidden'<'col-sm-6'i><'col-sm-6 d-print-none'f>>" +
- "<'table-content row'<'col-sm-12'tr>>" +
- "<'table-footer row mt-2 d-print-none align-items-center '<'col-sm-12 col-md-4'l><'col-sm-0 col-md-4 text-center'B><'col-sm-12 col-md-4 'p>>",
+ layout: {
+ topStart: null,
+ topEnd: null,
+ bottomEnd: null,
+ bottomStart: null,
+ bottom: [
+ 'pageLength',
+ {
+ buttons: config.exportButtons ? window.crud.exportButtonsConfig : []
+ },
+ {
+ paging: {
+ firstLast: false,
+ }
+ }
+ ]
+ },
buttons: []
};
@@ -406,7 +419,7 @@ functionsToRunOnDataTablesDrawEvent: [],
// Configure export buttons if present
if (config.exportButtons) {
- dataTableConfig.buttons = window.crud.exportButtonsConfig;
+ dataTableConfig.layout.bottom.buttons = window.crud.exportButtonsConfig;
}
@@ -429,6 +442,33 @@ functionsToRunOnDataTablesDrawEvent: [],
};
}
+ // Add initComplete callback to fix processing indicator positioning
+ dataTableConfig.initComplete = function(settings, json) {
+ // Move processing indicator into table wrapper if it exists outside
+ const tableWrapper = document.querySelector('#' + tableId + '_wrapper');
+ const processingIndicator = document.querySelector('.dataTables_processing, .dt-processing');
+
+ if (tableWrapper && processingIndicator && !tableWrapper.contains(processingIndicator)) {
+ // Move the processing indicator into the wrapper
+ tableWrapper.appendChild(processingIndicator);
+
+ // Ensure proper positioning
+ processingIndicator.style.position = 'absolute';
+ processingIndicator.style.top = '0';
+ processingIndicator.style.left = '0';
+ processingIndicator.style.right = '0';
+ processingIndicator.style.bottom = '0';
+ processingIndicator.style.width = 'auto';
+ processingIndicator.style.height = 'auto';
+ processingIndicator.style.zIndex = '1000';
+ }
+
+ // Call any existing initComplete function
+ if (typeof window.crud.initCompleteCallback === 'function') {
+ window.crud.initCompleteCallback.call(this, settings, json);
+ }
+ };
+
// Store the dataTableConfig in the config object for future reference
config.dataTableConfig = dataTableConfig;
@@ -526,8 +566,6 @@ function setupTableUI(tableId, config) {
}
});
window.dispatchEvent(event);
- // move the bottom buttons before pagination
- $(`#bottom_buttons_${tableId}`).insertBefore($(`#${tableId}_wrapper .row:last-child`));
}
// Function to set up table event handlers
@@ -629,6 +667,55 @@ function setupTableEvents(tableId, config) {
}
}).dataTable();
+ $(`#${tableId}`).on('processing.dt', function(e, settings, processing) {
+ if (processing) {
+ setTimeout(function() {
+ const tableWrapper = document.querySelector('#' + tableId + '_wrapper');
+ const processingIndicator = document.querySelector('.dataTables_processing, .dt-processing');
+
+ if (tableWrapper && processingIndicator) {
+ if (!tableWrapper.contains(processingIndicator)) {
+ tableWrapper.appendChild(processingIndicator);
+ }
+
+ processingIndicator.style.cssText = `
+ position: absolute !important;
+ top: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ bottom: 60px !important;
+ width: 100% !important;
+ height: calc(100% - 60px) !important;
+ z-index: 1000 !important;
+ transform: none !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ display: flex !important;
+ justify-content: center !important;
+ align-items: center !important;
+ background: rgba(255, 255, 255, 0.8) !important;
+ font-size: 0 !important;
+ color: transparent !important;
+ text-indent: -9999px !important;
+ overflow: hidden !important;
+ `;
+
+ tableWrapper.style.position = 'relative';
+
+ const allChildren = processingIndicator.querySelectorAll('*:not(img)');
+ allChildren.forEach(child => {
+ child.style.cssText = 'display: none !important; visibility: hidden !important; opacity: 0 !important;';
+ });
+
+ const images = processingIndicator.querySelectorAll('img');
+ images.forEach(img => {
+ img.style.cssText = 'display: block !important; visibility: visible !important; opacity: 1 !important; width: 40px !important; height: 40px !important; margin: 0 auto !important;';
+ });
+ }
+ }, 10);
+ }
+ });
+
// when datatables-colvis (column visibility) is toggled
$(`#${tableId}`).on('column-visibility.dt', function(event) {
if (table.responsive) {
diff --git a/src/resources/views/crud/inc/export_buttons.blade.php b/src/resources/views/crud/inc/export_buttons.blade.php
index 3a44c8d770..f074b76193 100644
--- a/src/resources/views/crud/inc/export_buttons.blade.php
+++ b/src/resources/views/crud/inc/export_buttons.blade.php
@@ -55,6 +55,7 @@
{
extend: 'collection',
text: ' {{ trans('backpack::crud.export.export') }}',
+ className: 'buttons-collection dropdown-toggle',
dropup: true,
buttons: [
{
@@ -159,6 +160,7 @@
,{
extend: 'colvis',
text: ' {{ trans('backpack::crud.export.column_visibility') }}',
+ className: 'buttons-collection dropdown-toggle',
columns: function ( idx, data, node ) {
return $(node).attr('data-can-be-visible-in-table') == 'true';
},
@@ -173,14 +175,12 @@
var table = window.crud.tables[tableId];
if (!table || !table.buttons) return;
-
table.buttons().each(function(button) {
if (button.node.className.indexOf('buttons-columnVisibility') == -1 && button.node.nodeName=='BUTTON') {
- button.node.className = button.node.className + " btn-sm";
+ button.node.className = button.node.className.replace('btn-secondary', 'btn-sm');
}
});
-
- $(`#${tableId}_wrapper .dt-buttons`).appendTo($('.datatable_button_stack'));
+
$('.dt-buttons').addClass('d-xs-block')
.addClass('d-sm-inline-block')
.addClass('d-md-inline-block')