Add asynchronous table pagination to v2.17.5
This commit is contained in:
1 parent
86b9609ea7
commit
ab4a40ccd8
5 files changed
+300
-52
No files matched your search
@@ -599,6 +599,7 @@
|
||||
|
||||
[data-table-search-container] > .card-header:has(> .card-tools) > .card-tools {
|
||||
margin-left: auto;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* Template animation preview controls */
|
||||
|
||||
@@ -81,7 +81,9 @@
|
||||
}
|
||||
|
||||
var currentTable = container.querySelector('[data-table-searchable]');
|
||||
var nextContainer = responseDocument.querySelector('[data-table-search-container]') || responseDocument.querySelector('.card');
|
||||
var containers = Array.prototype.slice.call(document.querySelectorAll('[data-table-search-container]'));
|
||||
var nextContainers = responseDocument.querySelectorAll('[data-table-search-container]');
|
||||
var nextContainer = nextContainers[containers.indexOf(container)];
|
||||
var nextTable = nextContainer ? nextContainer.querySelector('[data-table-searchable]') : null;
|
||||
var currentFooter = container.querySelector('.card-footer');
|
||||
var nextFooter = nextContainer ? nextContainer.querySelector('.card-footer') : null;
|
||||
@@ -104,12 +106,75 @@
|
||||
} else if (currentFooter && !nextFooter) {
|
||||
currentFooter.parentNode.removeChild(currentFooter);
|
||||
} else if (!currentFooter && nextFooter) {
|
||||
currentTable.parentNode.appendChild(nextFooter.cloneNode(true));
|
||||
container.appendChild(nextFooter.cloneNode(true));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function loadTableResults(container, nextUrl, historyMode, focusInput) {
|
||||
if (!container) {
|
||||
window.location.assign(nextUrl.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (container._cancelTableSearch) {
|
||||
container._cancelTableSearch();
|
||||
}
|
||||
var sequenceId = (container._tableRequestSequence || 0) + 1;
|
||||
container._tableRequestSequence = sequenceId;
|
||||
container.setAttribute('data-table-search-loading', 'true');
|
||||
container.setAttribute('aria-busy', 'true');
|
||||
|
||||
return fetch(nextUrl.toString(), {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'text/html, application/xhtml+xml',
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
credentials: 'same-origin',
|
||||
cache: 'no-store'
|
||||
}).then(function (response) {
|
||||
if (!response.ok || (response.redirected && new URL(response.url).pathname !== nextUrl.pathname)) {
|
||||
throw new Error('Unable to load table results.');
|
||||
}
|
||||
return response.text();
|
||||
}).then(function (text) {
|
||||
if (sequenceId !== container._tableRequestSequence) {
|
||||
return;
|
||||
}
|
||||
var responseDocument = new DOMParser().parseFromString(text || '', 'text/html');
|
||||
if (!replaceTableResults(container, responseDocument)) {
|
||||
throw new Error('Missing table results.');
|
||||
}
|
||||
if (historyMode && window.history && window.history[historyMode]) {
|
||||
window.history[historyMode](window.history.state, document.title, nextUrl.pathname + nextUrl.search + nextUrl.hash);
|
||||
}
|
||||
var input = container.querySelector('[data-table-search]');
|
||||
if (input) {
|
||||
var searchParam = input.getAttribute('data-table-search-param') || 'search';
|
||||
input.value = nextUrl.searchParams.get(searchParam) || '';
|
||||
}
|
||||
rebindTableContainer(container);
|
||||
var scroller = container.querySelector('.table-responsive');
|
||||
if (scroller) {
|
||||
scroller.scrollTop = 0;
|
||||
}
|
||||
if (focusInput) {
|
||||
focusSearchInput(input);
|
||||
}
|
||||
}).catch(function () {
|
||||
if (sequenceId === container._tableRequestSequence) {
|
||||
window.location.assign(nextUrl.toString());
|
||||
}
|
||||
}).finally(function () {
|
||||
if (sequenceId === container._tableRequestSequence) {
|
||||
container.removeAttribute('data-table-search-loading');
|
||||
container.removeAttribute('aria-busy');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initTableSearches(root) {
|
||||
var scope = root && root.querySelectorAll ? root : document;
|
||||
|
||||
@@ -123,11 +188,15 @@
|
||||
var searchParam = String(input.getAttribute('data-table-search-param') || 'search').trim() || 'search';
|
||||
var currentUrl = new URL(window.location.href);
|
||||
var pendingSearchTimer = null;
|
||||
var requestSequence = 0;
|
||||
var pendingSearchRequests = 0;
|
||||
var container = input.closest('[data-table-search-container]') || input.closest('.card') || null;
|
||||
|
||||
input.value = String(currentUrl.searchParams.get(searchParam) || '').trim();
|
||||
if (container) {
|
||||
container._cancelTableSearch = function () {
|
||||
window.clearTimeout(pendingSearchTimer);
|
||||
pendingSearchTimer = null;
|
||||
};
|
||||
}
|
||||
|
||||
var searchGroup = input.closest('.table-search-group');
|
||||
if (searchGroup) {
|
||||
@@ -160,57 +229,13 @@
|
||||
}
|
||||
nextUrl.searchParams.delete('page');
|
||||
|
||||
if (nextUrl.toString() === currentUrl.toString()) {
|
||||
return;
|
||||
}
|
||||
|
||||
requestSequence += 1;
|
||||
var sequenceId = requestSequence;
|
||||
pendingSearchRequests += 1;
|
||||
if (container) {
|
||||
container.setAttribute('data-table-search-loading', 'true');
|
||||
}
|
||||
|
||||
fetch(nextUrl.toString(), {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'text/html, application/xhtml+xml',
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
credentials: 'same-origin',
|
||||
cache: 'no-store'
|
||||
}).then(function (response) {
|
||||
if (!response.ok) {
|
||||
throw new Error('Unable to load search results.');
|
||||
}
|
||||
return response.text();
|
||||
}).then(function (text) {
|
||||
if (sequenceId !== requestSequence) {
|
||||
return;
|
||||
}
|
||||
|
||||
var responseDocument = new DOMParser().parseFromString(text || '', 'text/html');
|
||||
|
||||
if (window.history && window.history.replaceState) {
|
||||
window.history.replaceState({}, document.title, nextUrl.pathname + nextUrl.search + nextUrl.hash);
|
||||
}
|
||||
|
||||
if (replaceTableResults(container, responseDocument)) {
|
||||
currentUrl = nextUrl;
|
||||
rebindTableContainer(container || document);
|
||||
focusSearchInput(input);
|
||||
}
|
||||
}).catch(function () {
|
||||
window.location.assign(nextUrl.toString());
|
||||
}).finally(function () {
|
||||
pendingSearchRequests = Math.max(0, pendingSearchRequests - 1);
|
||||
if (container && pendingSearchRequests === 0) {
|
||||
container.removeAttribute('data-table-search-loading');
|
||||
}
|
||||
});
|
||||
loadTableResults(container, nextUrl, 'replaceState', true);
|
||||
}
|
||||
|
||||
function scheduleSearchUpdate() {
|
||||
if (container) {
|
||||
container._tableRequestSequence = (container._tableRequestSequence || 0) + 1;
|
||||
}
|
||||
if (pendingSearchTimer) {
|
||||
window.clearTimeout(pendingSearchTimer);
|
||||
}
|
||||
@@ -239,6 +264,11 @@
|
||||
}
|
||||
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('popstate', function () {
|
||||
Array.prototype.forEach.call(document.querySelectorAll('[data-table-search-container]'), function (container) {
|
||||
loadTableResults(container, new URL(window.location.href));
|
||||
});
|
||||
});
|
||||
window.addEventListener('resize', function () {
|
||||
syncTablePaginationCards(document);
|
||||
});
|
||||
@@ -247,6 +277,31 @@
|
||||
});
|
||||
}
|
||||
|
||||
if (document.addEventListener) {
|
||||
document.addEventListener('click', function (event) {
|
||||
var link = event.target.closest && event.target.closest('.pagination a.page-link');
|
||||
if (!link || event.defaultPrevented || event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey || link.hasAttribute('download') || (link.target && link.target !== '_self')) {
|
||||
return;
|
||||
}
|
||||
var container = link.closest('[data-table-search-container]');
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
if (link.closest('.disabled, .active')) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
var nextUrl = new URL(link.href, window.location.href);
|
||||
var currentUrl = new URL(window.location.href);
|
||||
if (nextUrl.origin !== currentUrl.origin || nextUrl.pathname !== currentUrl.pathname) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
loadTableResults(container, nextUrl, 'pushState');
|
||||
});
|
||||
}
|
||||
|
||||
window.loadTableResults = loadTableResults;
|
||||
window.initTableSearches = initTableSearches;
|
||||
window.replaceTableResults = replaceTableResults;
|
||||
syncTablePaginationCards(document);
|
||||
|
||||
@@ -103,6 +103,10 @@
|
||||
function refreshSortedTable(table, nextUrl, requestSequence, sequenceId) {
|
||||
var container = table ? (table.closest('[data-table-search-container]') || table.closest('.card') || null) : null;
|
||||
|
||||
if (typeof window.loadTableResults === 'function') {
|
||||
return window.loadTableResults(container, nextUrl, 'replaceState');
|
||||
}
|
||||
|
||||
fetch(nextUrl.toString(), {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
|
||||
Reference in new issue
Block a user