diff --git a/static/js/utils/asyncTable.js b/static/js/utils/asyncTable.js index cbb48b2b9..09596f61e 100644 --- a/static/js/utils/asyncTable.js +++ b/static/js/utils/asyncTable.js @@ -23,11 +23,10 @@ var INPUT_DEBOUNCE = 600; var HEADER_HEIGHT = 80; - var RESET_OPTIONS = [ 'scrollTo' ]; - var TABLE_FILTER_FORM_CLASS = 'table-filter-form'; + var TABLE_FILTER_FORM_SELECTOR = '.table-filter-form'; + var TABLE_FILTER_FORM_ID_SELECTOR = '[name="form-identifier"]'; var ASYNC_TABLE_LOADING_CLASS = 'async-table--loading'; - var ASYNC_TABLE_FILTER_LOADING_CLASS = 'async-table-filter--loading'; var asyncTableUtil = function(element) { var asyncTableHeader; @@ -38,6 +37,13 @@ var pagesizeForm; var scrollTable; + var tableFilterInputs = { + search: [], + input: [], + change: [], + select: [], + } + function init() { if (!element) { throw new Error('Async Table utility cannot be setup without an element!'); @@ -124,12 +130,126 @@ } function setupTableFilter() { - // // filter - // var filterForm = element.querySelector('.' + TABLE_FILTER_FORM_CLASS); - // if (filterForm) { - // options.updateTableFrom = updateTableFrom; - // utilInstances.push(window.utils.setup('asyncTableFilter', filterForm, options)); - // } + var filterForm = element.querySelector(TABLE_FILTER_FORM_SELECTOR); + + if (filterForm) { + gatherTableFilterInputs(); + addTableFilterEventListeners(); + } + } + + function gatherTableFilterInputs() { + Array.from(element.querySelectorAll('input[type="search"]')).forEach(function(input) { + tableFilterInputs.search.push(input); + }); + + Array.from(element.querySelectorAll('input[type="text"]')).forEach(function(input) { + tableFilterInputs.input.push(input); + }); + + Array.from(element.querySelectorAll('input:not([type="text"]):not([type="search"])')).forEach(function(input) { + tableFilterInputs.change.push(input); + }); + + Array.from(element.querySelectorAll('select')).forEach(function(input) { + tableFilterInputs.select.push(input); + }); + } + + function addTableFilterEventListeners() { + tableFilterInputs.search.forEach(function(input) { + var debouncedInput = debounce(function() { + if (input.value.length === 0 || input.value.length > 2) { + updateFromTableFilter(); + } + }, 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(); + } + }, INPUT_DEBOUNCE); + input.addEventListener('input', debouncedInput); + }); + + tableFilterInputs.change.forEach(function(input) { + input.addEventListener('change', function() { + updateFromTableFilter(); + }); + }); + + tableFilterInputs.select.forEach(function(input) { + input.addEventListener('change', function() { + updateFromTableFilter(); + }); + }); + + element.addEventListener('submit', function(event) { + event.preventDefault(); + updateFromTableFilter(); + }); + } + + function updateFromTableFilter() { + var url = serializeTableFilterToURL(); + var callback = null; + + var focusedSearch = tableFilterInputs.search.reduce(function(acc, input) { + return acc || (input.matches(':focus') && input); + }, null); + // focus search input + if (focusedSearch) { + var selectionStart = focusedSearch.selectionStart; + callback = function(wrapper) { + var search = wrapper.querySelector('input[type="search"]'); + if (search) { + search.focus(); + search.selectionStart = selectionStart; + } + }; + } + updateTableFrom(url, callback); + } + + function serializeTableFilterToURL() { + var url = new URL(getLocalStorageParameter('currentTableUrl') || window.location.href); + + var formIdElement = element.querySelector(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 reset() { @@ -192,7 +312,7 @@ } // fetches new sorted element from url with params and replaces contents of current element - function updateTableFrom(url) { + function updateTableFrom(url, callback) { if (!HttpClient) { throw new Error('HttpClient not found!'); } @@ -218,6 +338,10 @@ // update table with new updateWrapperContents(data); + if (callback && typeof callback === 'function') { + callback(element); + } + element.classList.remove(ASYNC_TABLE_LOADING_CLASS); }).catch(function(err) { console.error(err);