removed obsolete static js file for asyncTable (re-appeared by accident)
This commit is contained in:
parent
c72335c13f
commit
15660fece1
@ -1,430 +0,0 @@
|
|||||||
(function collonadeClosure() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Async Table Utility
|
|
||||||
* makes table filters, sorting and pagination behave asynchronously via AJAX calls
|
|
||||||
*
|
|
||||||
* Attribute: uw-async-table
|
|
||||||
*
|
|
||||||
* Example usage:
|
|
||||||
* (regular table)
|
|
||||||
*/
|
|
||||||
|
|
||||||
var INPUT_DEBOUNCE = 600;
|
|
||||||
var HEADER_HEIGHT = 80;
|
|
||||||
|
|
||||||
var ASYNC_TABLE_UTIL_NAME = 'asyncTable';
|
|
||||||
var ASYNC_TABLE_UTIL_SELECTOR = '[uw-async-table]';
|
|
||||||
|
|
||||||
var ASYNC_TABLE_LOCAL_STORAGE_KEY = 'ASYNC_TABLE';
|
|
||||||
var ASYNC_TABLE_SCROLLTABLE_SELECTOR = '.scrolltable';
|
|
||||||
var ASYNC_TABLE_INITIALIZED_CLASS = 'async-table--initialized';
|
|
||||||
var ASYNC_TABLE_LOADING_CLASS = 'async-table--loading';
|
|
||||||
|
|
||||||
var ASYNC_TABLE_FILTER_FORM_SELECTOR = '.table-filter-form';
|
|
||||||
var ASYNC_TABLE_FILTER_FORM_ID_SELECTOR = '[name="form-identifier"]';
|
|
||||||
|
|
||||||
|
|
||||||
var asyncTableUtil = function(element) {
|
|
||||||
var asyncTableHeader;
|
|
||||||
var asyncTableId;
|
|
||||||
|
|
||||||
var ths = [];
|
|
||||||
var pageLinks = [];
|
|
||||||
var pagesizeForm;
|
|
||||||
var scrollTable;
|
|
||||||
var cssIdPrefix = '';
|
|
||||||
|
|
||||||
var tableFilterInputs = {
|
|
||||||
search: [],
|
|
||||||
input: [],
|
|
||||||
change: [],
|
|
||||||
select: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
if (!element) {
|
|
||||||
throw new Error('Async Table utility cannot be setup without an element!');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element.classList.contains(ASYNC_TABLE_INITIALIZED_CLASS)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// param asyncTableDbHeader
|
|
||||||
if (element.dataset.asyncTableDbHeader !== undefined) {
|
|
||||||
asyncTableHeader = element.dataset.asyncTableDbHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rawTableId = element.querySelector('table').id;
|
|
||||||
cssIdPrefix = findCssIdPrefix(rawTableId);
|
|
||||||
asyncTableId = rawTableId.replace(cssIdPrefix, '');
|
|
||||||
|
|
||||||
// find scrolltable wrapper
|
|
||||||
scrollTable = element.querySelector(ASYNC_TABLE_SCROLLTABLE_SELECTOR);
|
|
||||||
if (!scrollTable) {
|
|
||||||
throw new Error('Async Table cannot be set up without a scrolltable element!');
|
|
||||||
}
|
|
||||||
|
|
||||||
setupSortableHeaders();
|
|
||||||
setupPagination();
|
|
||||||
setupPageSizeSelect();
|
|
||||||
setupTableFilter();
|
|
||||||
|
|
||||||
processLocalStorage();
|
|
||||||
|
|
||||||
// clear currentTableUrl from previous requests
|
|
||||||
setLocalStorageParameter('currentTableUrl', null);
|
|
||||||
|
|
||||||
// mark initialized
|
|
||||||
element.classList.add(ASYNC_TABLE_INITIALIZED_CLASS);
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: ASYNC_TABLE_UTIL_NAME,
|
|
||||||
element: element,
|
|
||||||
destroy: function() {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupSortableHeaders() {
|
|
||||||
ths = Array.from(scrollTable.querySelectorAll('th.sortable')).map(function(th) {
|
|
||||||
return { element: th };
|
|
||||||
});
|
|
||||||
|
|
||||||
ths.forEach(function(th) {
|
|
||||||
th.clickHandler = function(event) {
|
|
||||||
setLocalStorageParameter('horizPos', (scrollTable || {}).scrollLeft);
|
|
||||||
linkClickHandler(event);
|
|
||||||
};
|
|
||||||
th.element.addEventListener('click', th.clickHandler);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupPagination() {
|
|
||||||
var pagination = element.querySelector('#' + cssIdPrefix + asyncTableId + '-pagination');
|
|
||||||
if (pagination) {
|
|
||||||
pageLinks = Array.from(pagination.querySelectorAll('.page-link')).map(function(link) {
|
|
||||||
return { element: link };
|
|
||||||
});
|
|
||||||
|
|
||||||
pageLinks.forEach(function(link) {
|
|
||||||
link.clickHandler = function(event) {
|
|
||||||
var tableBoundingRect = scrollTable.getBoundingClientRect();
|
|
||||||
if (tableBoundingRect.top < HEADER_HEIGHT) {
|
|
||||||
var scrollTo = {
|
|
||||||
top: (scrollTable.offsetTop || 0) - HEADER_HEIGHT,
|
|
||||||
left: scrollTable.offsetLeft || 0,
|
|
||||||
behavior: 'smooth',
|
|
||||||
};
|
|
||||||
setLocalStorageParameter('scrollTo', scrollTo);
|
|
||||||
}
|
|
||||||
linkClickHandler(event);
|
|
||||||
}
|
|
||||||
link.element.addEventListener('click', link.clickHandler);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupPageSizeSelect() {
|
|
||||||
// pagesize form
|
|
||||||
pagesizeForm = element.querySelector('#' + cssIdPrefix + asyncTableId + '-pagesize-form');
|
|
||||||
|
|
||||||
if (pagesizeForm) {
|
|
||||||
var pagesizeSelect = pagesizeForm.querySelector('[name=' + asyncTableId + '-pagesize]');
|
|
||||||
pagesizeSelect.addEventListener('change', changePagesizeHandler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupTableFilter() {
|
|
||||||
var tableFilterForm = element.querySelector(ASYNC_TABLE_FILTER_FORM_SELECTOR);
|
|
||||||
|
|
||||||
if (tableFilterForm) {
|
|
||||||
gatherTableFilterInputs(tableFilterForm);
|
|
||||||
addTableFilterEventListeners(tableFilterForm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function gatherTableFilterInputs(tableFilterForm) {
|
|
||||||
Array.from(tableFilterForm.querySelectorAll('input[type="search"]')).forEach(function(input) {
|
|
||||||
tableFilterInputs.search.push(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
Array.from(tableFilterForm.querySelectorAll('input[type="text"]')).forEach(function(input) {
|
|
||||||
tableFilterInputs.input.push(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
Array.from(tableFilterForm.querySelectorAll('input:not([type="text"]):not([type="search"])')).forEach(function(input) {
|
|
||||||
tableFilterInputs.change.push(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
Array.from(tableFilterForm.querySelectorAll('select')).forEach(function(input) {
|
|
||||||
tableFilterInputs.select.push(input);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function addTableFilterEventListeners(tableFilterForm) {
|
|
||||||
tableFilterInputs.search.forEach(function(input) {
|
|
||||||
var debouncedInput = debounce(function() {
|
|
||||||
if (input.value.length === 0 || input.value.length > 2) {
|
|
||||||
updateFromTableFilter(tableFilterForm);
|
|
||||||
}
|
|
||||||
}, INPUT_DEBOUNCE);
|
|
||||||
input.addEventListener('input', debouncedInput);
|
|
||||||
});
|
|
||||||
|
|
||||||
tableFilterInputs.input.forEach(function(input) {
|
|
||||||
var debouncedInput = debounce(function() {
|
|
||||||
if (input.value.length === 0 || input.value.length > 2) {
|
|
||||||
updateFromTableFilter(tableFilterForm);
|
|
||||||
}
|
|
||||||
}, INPUT_DEBOUNCE);
|
|
||||||
input.addEventListener('input', debouncedInput);
|
|
||||||
});
|
|
||||||
|
|
||||||
tableFilterInputs.change.forEach(function(input) {
|
|
||||||
input.addEventListener('change', function() {
|
|
||||||
updateFromTableFilter(tableFilterForm);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
tableFilterInputs.select.forEach(function(input) {
|
|
||||||
input.addEventListener('change', function() {
|
|
||||||
updateFromTableFilter(tableFilterForm);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
tableFilterForm.addEventListener('submit', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
updateFromTableFilter(tableFilterForm);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateFromTableFilter(tableFilterForm) {
|
|
||||||
var url = serializeTableFilterToURL();
|
|
||||||
var callback = null;
|
|
||||||
|
|
||||||
var focusedInput = tableFilterForm.querySelector(':focus, :active');
|
|
||||||
// focus previously focused input
|
|
||||||
if (focusedInput && focusedInput.selectionStart !== null) {
|
|
||||||
var selectionStart = focusedInput.selectionStart;
|
|
||||||
// remove the following part of the id to get rid of the random
|
|
||||||
// (yet somewhat structured) prefix we got from nudging.
|
|
||||||
var prefix = findCssIdPrefix(focusedInput.id);
|
|
||||||
var focusId = focusedInput.id.replace(prefix, '');
|
|
||||||
callback = function(wrapper) {
|
|
||||||
var idPrefix = getLocalStorageParameter('cssIdPrefix');
|
|
||||||
var toBeFocused = wrapper.querySelector('#' + idPrefix + focusId);
|
|
||||||
if (toBeFocused) {
|
|
||||||
toBeFocused.focus();
|
|
||||||
toBeFocused.selectionStart = selectionStart;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
updateTableFrom(url, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function serializeTableFilterToURL() {
|
|
||||||
var url = new URL(getLocalStorageParameter('currentTableUrl') || window.location.href);
|
|
||||||
|
|
||||||
var formIdElement = element.querySelector(ASYNC_TABLE_FILTER_FORM_ID_SELECTOR);
|
|
||||||
if (!formIdElement) {
|
|
||||||
// cannot serialize the filter form without an identifier
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
url.searchParams.set('form-identifier', formIdElement.value);
|
|
||||||
url.searchParams.set('_hasdata', 'true');
|
|
||||||
url.searchParams.set(asyncTableId + '-page', '0');
|
|
||||||
|
|
||||||
tableFilterInputs.search.forEach(function(input) {
|
|
||||||
url.searchParams.set(input.name, input.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
tableFilterInputs.input.forEach(function(input) {
|
|
||||||
url.searchParams.set(input.name, input.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
tableFilterInputs.change.forEach(function(input) {
|
|
||||||
if (input.checked) {
|
|
||||||
url.searchParams.set(input.name, input.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tableFilterInputs.select.forEach(function(select) {
|
|
||||||
var options = Array.from(select.querySelectorAll('option'));
|
|
||||||
var selected = options.find(function(option) { return option.selected });
|
|
||||||
if (selected) {
|
|
||||||
url.searchParams.set(select.name, selected.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
function processLocalStorage() {
|
|
||||||
var scrollTo = getLocalStorageParameter('scrollTo');
|
|
||||||
if (scrollTo && scrollTable) {
|
|
||||||
window.scrollTo(scrollTo);
|
|
||||||
}
|
|
||||||
setLocalStorageParameter('scrollTo', null);
|
|
||||||
|
|
||||||
var horizPos = getLocalStorageParameter('horizPos');
|
|
||||||
if (horizPos && scrollTable) {
|
|
||||||
scrollTable.scrollLeft = horizPos;
|
|
||||||
}
|
|
||||||
setLocalStorageParameter('horizPos', null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeListeners() {
|
|
||||||
ths.forEach(function(th) {
|
|
||||||
th.element.removeEventListener('click', th.clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
pageLinks.forEach(function(link) {
|
|
||||||
link.element.removeEventListener('click', link.clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (pagesizeForm) {
|
|
||||||
var pagesizeSelect = pagesizeForm.querySelector('[name=' + asyncTableId + '-pagesize]')
|
|
||||||
pagesizeSelect.removeEventListener('change', changePagesizeHandler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function linkClickHandler(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var url = getClickDestination(event.target);
|
|
||||||
if (!url.match(/^http/)) {
|
|
||||||
url = window.location.origin + window.location.pathname + url;
|
|
||||||
}
|
|
||||||
updateTableFrom(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getClickDestination(el) {
|
|
||||||
if (!el.matches('a') && !el.querySelector('a')) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return el.getAttribute('href') || el.querySelector('a').getAttribute('href');
|
|
||||||
}
|
|
||||||
|
|
||||||
function changePagesizeHandler(event) {
|
|
||||||
var paginationParamKey = asyncTableId + '-pagination';
|
|
||||||
var pagesizeParamKey = asyncTableId + '-pagesize';
|
|
||||||
var pageParamKey = asyncTableId + '-page';
|
|
||||||
|
|
||||||
var paginationParamEl = pagesizeForm.querySelector('[name="' + paginationParamKey + '"]');
|
|
||||||
var url = new URL(getLocalStorageParameter('currentTableUrl') || window.location.href);
|
|
||||||
url.searchParams.set(pagesizeParamKey, event.target.value);
|
|
||||||
url.searchParams.set(pageParamKey, 0);
|
|
||||||
|
|
||||||
if (paginationParamEl) {
|
|
||||||
var encodedValue = encodeURIComponent(paginationParamEl.value);
|
|
||||||
url.searchParams.set(paginationParamKey, encodedValue);
|
|
||||||
}
|
|
||||||
updateTableFrom(url.href);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetches new sorted element from url with params and replaces contents of current element
|
|
||||||
function updateTableFrom(url, callback) {
|
|
||||||
if (!HttpClient) {
|
|
||||||
throw new Error('HttpClient not found!');
|
|
||||||
}
|
|
||||||
|
|
||||||
element.classList.add(ASYNC_TABLE_LOADING_CLASS);
|
|
||||||
|
|
||||||
var headers = {
|
|
||||||
'Accept': 'text/html',
|
|
||||||
[asyncTableHeader]: asyncTableId
|
|
||||||
};
|
|
||||||
|
|
||||||
HttpClient.get({
|
|
||||||
url: url,
|
|
||||||
headers: headers,
|
|
||||||
accept: HttpClient.ACCEPT.TEXT_HTML,
|
|
||||||
}).then(function(response) {
|
|
||||||
return HtmlHelpers.parseResponse(response);
|
|
||||||
}).then(function(response) {
|
|
||||||
setLocalStorageParameter('currentTableUrl', url.href);
|
|
||||||
// reset table
|
|
||||||
removeListeners();
|
|
||||||
element.classList.remove(ASYNC_TABLE_INITIALIZED_CLASS);
|
|
||||||
// update table with new
|
|
||||||
updateWrapperContents(response);
|
|
||||||
|
|
||||||
if (UtilRegistry) {
|
|
||||||
UtilRegistry.setupAll(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback && typeof callback === 'function') {
|
|
||||||
setLocalStorageParameter('cssIdPrefix', response.idPrefix);
|
|
||||||
callback(element);
|
|
||||||
setLocalStorageParameter('cssIdPrefix', '');
|
|
||||||
}
|
|
||||||
}).catch(function(err) {
|
|
||||||
console.error(err);
|
|
||||||
}).finally(function() {
|
|
||||||
element.classList.remove(ASYNC_TABLE_LOADING_CLASS);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateWrapperContents(response) {
|
|
||||||
var newPage = document.createElement('div');
|
|
||||||
newPage.appendChild(response.element);
|
|
||||||
var newWrapperContents = newPage.querySelector('#' + response.idPrefix + element.id);
|
|
||||||
element.innerHTML = newWrapperContents.innerHTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
return init();
|
|
||||||
};
|
|
||||||
|
|
||||||
// returns any random nudged prefix found in the given id
|
|
||||||
function findCssIdPrefix(id) {
|
|
||||||
var matcher = /r\d*?__/;
|
|
||||||
var maybePrefix = id.match(matcher);
|
|
||||||
if (maybePrefix && maybePrefix[0]) {
|
|
||||||
return maybePrefix[0]
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLocalStorageParameter(key, value) {
|
|
||||||
var currentLSState = JSON.parse(window.localStorage.getItem(ASYNC_TABLE_LOCAL_STORAGE_KEY)) || {};
|
|
||||||
if (value !== null) {
|
|
||||||
currentLSState[key] = value;
|
|
||||||
} else {
|
|
||||||
delete currentLSState[key];
|
|
||||||
}
|
|
||||||
window.localStorage.setItem(ASYNC_TABLE_LOCAL_STORAGE_KEY, JSON.stringify(currentLSState));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLocalStorageParameter(key) {
|
|
||||||
var currentLSState = JSON.parse(window.localStorage.getItem(ASYNC_TABLE_LOCAL_STORAGE_KEY)) || {};
|
|
||||||
return currentLSState[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
// debounce function, taken from Underscore.js
|
|
||||||
function debounce(func, wait, immediate) {
|
|
||||||
var timeout;
|
|
||||||
return function() {
|
|
||||||
var context = this, args = arguments;
|
|
||||||
var later = function() {
|
|
||||||
timeout = null;
|
|
||||||
if (!immediate) func.apply(context, args);
|
|
||||||
};
|
|
||||||
var callNow = immediate && !timeout;
|
|
||||||
clearTimeout(timeout);
|
|
||||||
timeout = setTimeout(later, wait);
|
|
||||||
if (callNow) func.apply(context, args);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// register async table utility
|
|
||||||
if (UtilRegistry) {
|
|
||||||
UtilRegistry.register({
|
|
||||||
name: ASYNC_TABLE_UTIL_NAME,
|
|
||||||
selector: ASYNC_TABLE_UTIL_SELECTOR,
|
|
||||||
setup: asyncTableUtil,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
Loading…
Reference in New Issue
Block a user