Release 1.5.13

This commit is contained in:
2026-07-26 20:26:01 +01:00
parent 4afaeaafb1
commit 815c808d73
59 changed files with 1418 additions and 3042 deletions
+4 -314
View File
@@ -164,9 +164,6 @@
if (typeof window.initTableSearches === 'function') {
window.initTableSearches(targetElement);
}
if (typeof window.initTablePaginations === 'function') {
window.initTablePaginations(targetElement);
}
}
function replaceRefreshTargetFromPage(refreshTargetSelector, sequenceId) {
@@ -201,7 +198,7 @@
currentTarget.outerHTML = nextTarget.outerHTML;
rebindRefreshTarget(document.querySelector(refreshTargetSelector));
}).catch(function (_error) {
}).catch(function () {
// Ignore refresh replacement failures and leave the existing content in place.
});
}
@@ -515,303 +512,10 @@
});
}
function initTablePaginations(root) {
var scope = root && root.querySelectorAll ? root : document;
Array.prototype.forEach.call(scope.querySelectorAll('[data-table-pagination="auto"]'), function (container) {
if (container.getAttribute('data-table-pagination-bound') === 'true') {
return;
}
var table = container.querySelector('[data-table-searchable]');
var cardHeader = container.querySelector('.card-header');
var cardBody = container.querySelector('.card-body.table-responsive') || container.querySelector('.card-body');
var footer = container.querySelector('[data-table-pagination-controls]');
var footerSummary = null;
var footerList = null;
var syncFrame = 0;
var state = {
currentPage: 1,
pageSize: 1,
totalPages: 1
};
if (!table || !cardBody || !table.tBodies.length) {
return;
}
container.setAttribute('data-table-pagination-bound', 'true');
function getRows() {
return Array.prototype.slice.call(table.querySelectorAll('tbody tr[data-table-search-row]'));
}
function isSearchMatched(row) {
return String(row.getAttribute('data-table-search-match') || 'true') !== 'false';
}
function ensureFooter() {
if (footer) {
footerSummary = footer.querySelector('[data-table-pagination-summary]');
footerList = footer.querySelector('[data-table-pagination-list]');
return footer;
}
footer = document.createElement('div');
footer.className = 'card-footer d-none';
footer.setAttribute('data-table-pagination-controls', 'true');
footer.innerHTML = '' +
'<div class="d-flex flex-wrap align-items-center justify-content-between gap-3">' +
'<div class="text-muted small" data-table-pagination-summary></div>' +
'<nav aria-label="Table pages">' +
'<ul class="pagination pagination-sm mb-0" data-table-pagination-list></ul>' +
'</nav>' +
'</div>';
cardBody.parentNode.insertBefore(footer, cardBody.nextSibling);
footerSummary = footer.querySelector('[data-table-pagination-summary]');
footerList = footer.querySelector('[data-table-pagination-list]');
return footer;
}
function setRowVisible(row, visible) {
row.hidden = !visible;
row.classList.toggle('d-none', !visible);
}
function getAvailableHeight() {
var containerRect = container.getBoundingClientRect();
var headerHeight = cardHeader ? cardHeader.getBoundingClientRect().height : 0;
var footerEstimate = footer && !footer.classList.contains('d-none') ? footer.getBoundingClientRect().height : 56;
return Math.max(0, window.innerHeight - Math.max(0, containerRect.top) - headerHeight - footerEstimate - 24);
}
function renderFooter(totalItems) {
var pageButtons = [];
ensureFooter();
if (state.totalPages <= 1 || totalItems <= 0) {
footer.classList.add('d-none');
footerSummary.textContent = '';
footerList.innerHTML = '';
return;
}
footer.classList.remove('d-none');
footerSummary.textContent = 'Showing ' + (((state.currentPage - 1) * state.pageSize) + 1) + '-' + Math.min(totalItems, state.currentPage * state.pageSize) + ' of ' + totalItems;
pageButtons.push('<li class="page-item' + (state.currentPage <= 1 ? ' disabled' : '') + '"><a class="page-link" href="#" data-table-pagination-page="' + (state.currentPage - 1) + '" aria-label="Previous page">Previous</a></li>');
for (var pageNumber = 1; pageNumber <= state.totalPages; pageNumber += 1) {
pageButtons.push('<li class="page-item' + (pageNumber === state.currentPage ? ' active' : '') + '"><a class="page-link" href="#" data-table-pagination-page="' + pageNumber + '">' + pageNumber + '</a></li>');
}
pageButtons.push('<li class="page-item' + (state.currentPage >= state.totalPages ? ' disabled' : '') + '"><a class="page-link" href="#" data-table-pagination-page="' + (state.currentPage + 1) + '" aria-label="Next page">Next</a></li>');
footerList.innerHTML = pageButtons.join('');
}
function applyPagination(resetPage) {
var rows = getRows();
var matchedRows = rows.filter(isSearchMatched);
var totalItems = matchedRows.length;
var rowHeight = 48;
var pageSize;
var startIndex;
var endIndex;
if (resetPage) {
state.currentPage = 1;
}
rows.forEach(function (row) {
if (!isSearchMatched(row)) {
setRowVisible(row, false);
}
});
if (!totalItems) {
state.pageSize = 1;
state.totalPages = 1;
state.currentPage = 1;
renderFooter(0);
return;
}
matchedRows.forEach(function (row) {
setRowVisible(row, true);
});
if (matchedRows[0]) {
rowHeight = Math.max(24, matchedRows[0].getBoundingClientRect().height || matchedRows[0].offsetHeight || 48);
}
pageSize = Math.max(1, Math.floor(getAvailableHeight() / rowHeight));
if (pageSize >= totalItems) {
state.pageSize = totalItems;
state.totalPages = 1;
state.currentPage = 1;
matchedRows.forEach(function (row) {
setRowVisible(row, true);
});
renderFooter(totalItems);
return;
}
state.pageSize = pageSize;
state.totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
state.currentPage = Math.min(Math.max(1, state.currentPage), state.totalPages);
startIndex = (state.currentPage - 1) * pageSize;
endIndex = startIndex + pageSize;
matchedRows.forEach(function (row, index) {
setRowVisible(row, index >= startIndex && index < endIndex);
});
renderFooter(totalItems);
}
function scheduleSync(options) {
if (syncFrame) {
window.cancelAnimationFrame(syncFrame);
}
syncFrame = window.requestAnimationFrame(function () {
syncFrame = 0;
applyPagination(Boolean(options && options.resetPage));
});
}
ensureFooter();
if (footer) {
footer.addEventListener('click', function (event) {
var target = event.target && event.target.closest ? event.target.closest('[data-table-pagination-page]') : null;
var pageValue;
if (!target || target.closest('.disabled')) {
return;
}
event.preventDefault();
pageValue = Math.max(1, Math.floor(Number(target.getAttribute('data-table-pagination-page')) || 1));
state.currentPage = pageValue;
scheduleSync();
});
}
window.addEventListener('resize', function () {
scheduleSync();
});
if (typeof ResizeObserver === 'function') {
try {
new ResizeObserver(function () {
scheduleSync();
}).observe(container);
} catch (_error) {
// Ignore observer setup failures and rely on window resize.
}
}
container.syncTablePagination = scheduleSync;
scheduleSync({ resetPage: true });
});
}
function initTableSearches(root) {
var scope = root && root.querySelectorAll ? root : document;
Array.prototype.forEach.call(scope.querySelectorAll('[data-table-search]'), function (input) {
if (input.getAttribute('data-table-search-bound') === 'true') {
return;
}
var container = input.closest('[data-table-search-container]') || input.closest('.card') || document;
var table = container.querySelector('[data-table-searchable]');
var emptyRow = null;
if (!table) {
return;
}
input.setAttribute('data-table-search-bound', 'true');
function getSearchableRows() {
return Array.prototype.slice.call(table.querySelectorAll('tbody tr[data-table-search-row]'));
}
function getDefaultEmptyRow() {
return table.querySelector('tbody tr[data-table-search-empty-default]');
}
function removeGeneratedEmptyRow() {
if (emptyRow && emptyRow.parentNode) {
emptyRow.parentNode.removeChild(emptyRow);
}
emptyRow = null;
}
function ensureGeneratedEmptyRow(message) {
var tbody = table.tBodies[0] || table.querySelector('tbody');
var columnCount = 1;
if (!tbody) {
return;
}
if (!emptyRow) {
emptyRow = document.createElement('tr');
emptyRow.setAttribute('data-table-search-empty-row', 'true');
var cell = document.createElement('td');
cell.className = 'empty';
cell.setAttribute('data-table-search-empty-cell', 'true');
emptyRow.appendChild(cell);
}
columnCount = table.tHead && table.tHead.rows && table.tHead.rows[0] ? table.tHead.rows[0].cells.length : (getSearchableRows()[0] ? getSearchableRows()[0].cells.length : 1);
emptyRow.firstElementChild.colSpan = Math.max(1, columnCount);
emptyRow.firstElementChild.textContent = message;
if (!emptyRow.parentNode) {
tbody.appendChild(emptyRow);
}
}
function syncSearch() {
var query = String(input.value || '').trim().toLowerCase();
var rows = getSearchableRows();
var visibleCount = 0;
var defaultEmptyRow = getDefaultEmptyRow();
removeGeneratedEmptyRow();
rows.forEach(function (row) {
var haystack = String(row.getAttribute('data-search-text') || row.textContent || '').toLowerCase();
var visible = !query || haystack.indexOf(query) !== -1;
row.setAttribute('data-table-search-match', visible ? 'true' : 'false');
row.classList.toggle('d-none', !visible);
row.hidden = !visible;
if (visible) {
visibleCount += 1;
}
});
if (defaultEmptyRow) {
defaultEmptyRow.classList.toggle('d-none', Boolean(query));
defaultEmptyRow.hidden = Boolean(query);
}
if (query && visibleCount === 0) {
ensureGeneratedEmptyRow('No results match your search.');
}
if (typeof window.syncTablePagination === 'function') {
window.syncTablePagination(container, { resetPage: true });
}
}
input.addEventListener('input', syncSearch);
syncSearch();
});
if (typeof window.initTableSearches === 'function') {
window.initTableSearches(root);
}
}
function createSlideThumbPlaceholder() {
@@ -841,10 +545,6 @@
});
}
if (window.initSortableTables) {
window.initSortableTables();
}
initConfirmForms();
initDirtyTracking();
initCancelConfirm();
@@ -854,19 +554,9 @@
initJsonTogglePanels();
initLocalDateTimes();
initTableSearches();
initTablePaginations();
attachSlideThumbFallbacks(document);
window.initJsonTogglePanels = initJsonTogglePanels;
window.initLocalDateTimes = initLocalDateTimes;
window.initTableSearches = initTableSearches;
window.initTablePaginations = initTablePaginations;
window.syncTablePagination = function (container, options) {
if (!container || !container.syncTablePagination) {
return;
}
container.syncTablePagination(options);
};
window.createSlideThumbPlaceholder = createSlideThumbPlaceholder;
window.attachSlideThumbFallbacks = attachSlideThumbFallbacks;
}());