UNPKG

@arrow-ecs/reflex

Version:

Reflex UI library

455 lines (376 loc) 14.5 kB
const disableFilter = (toggle) => { if (toggle.classList.contains('show')) { toggle.classList.remove('show'); setTimeout(() => { toggle.classList.remove('showing'); }, 300); return true; } return false; } const toggleAllOptions = (enableAll, menu) => { const menuOptions = menu.querySelectorAll('.select-menu-option input'); for (const option of menuOptions) { option.checked = enableAll; } } const toggleFilterHandler = (toggle) => { // remove active styling on toggle if (toggle.classList.contains('active')) { toggle.classList.remove('active'); } // check if current toggle is already active, if it is then disable it // change from nextSibling to nextElementSibling due to C# rendering white space as text node // https://stackoverflow.com/questions/33080492/c-sharp-what-is-text-node-in-htmlnode let menu = (toggle.classList.contains('full-width')) ? toggle.parentNode.nextElementSibling : toggle.nextElementSibling; const isDisabled = disableFilter(menu); if (!isDisabled) { // reset all the search filters if any is active const selectMenu = document.querySelectorAll('.select-menu'); for (const menu of selectMenu) { // reset all active styling on toggle const activeToggle = menu.classList.contains('full-width') ? menu.previousElementSibling.querySelector('.select-toggle') : menu.previousElementSibling.closest('.select-toggle'); if (activeToggle) { activeToggle.classList.remove('active'); } disableFilter(menu); } // update toggle styling to indicate active toggle.classList.add('active'); // enable specific search filter to be active let menu = (toggle.classList.contains('full-width')) ? toggle.parentNode.nextElementSibling : toggle.nextElementSibling; menu.classList.add('showing'); setTimeout(() => { menu.classList.add('show'); // enable select/deselect all buttons const deselectAll = menu.querySelector('.deselect-all'); const selectAll = menu.querySelector('.select-all'); if (deselectAll) { deselectAll.addEventListener('click', () => { toggleAllOptions(false, menu); }) } if (selectAll) { selectAll.addEventListener('click', () => { toggleAllOptions(true, menu); }) } }); } } const toggleFilter = () => { const searchFilterToggle = document.querySelectorAll('.select .select-toggle'); if (!searchFilterToggle || !searchFilterToggle.length) { return false; } for (const toggle of searchFilterToggle) { toggle.addEventListener('click', () => { toggleFilterHandler(toggle); }); } } const toggleAllHandler = (menu) => { const deselectAll = menu.querySelector('.deselect-all'); const selectAll = menu.querySelector('.select-all'); if (deselectAll) { deselectAll.addEventListener('click', () => { toggleAllOptions(false, menu); }) } if (selectAll) { selectAll.addEventListener('click', () => { toggleAllOptions(true, menu); }) } } const toggleMobileFilter = () => { const searchFilterBtn = document.querySelector('.search-filter.mobile .search-filter-button'); const closeFilterBtn = document.querySelector('.search-filter.mobile .close-filter-sidebar'); const navLink = document.querySelectorAll('.search-filter.mobile .nav-link'); if (searchFilterBtn) { searchFilterBtn.addEventListener('click', () => { const filterSidebar = document.querySelector('.search-filter.mobile .filter-sidebar'); filterSidebar.classList.add('show'); const searchFilterToggle = document.querySelectorAll('.search-filter.mobile .select-menu'); if (!searchFilterToggle || !searchFilterToggle.length) { return false; } for (const toggle of searchFilterToggle) { toggleAllHandler(toggle); } }); } if (closeFilterBtn) { closeFilterBtn.addEventListener('click', () => { const filterSidebar = document.querySelector('.search-filter.mobile .filter-sidebar'); filterSidebar.classList.remove('show'); }); } // force clicking on nav to toggle menu due to desktop hover CSS causing unwanted checkbox selected when opening // nav menu on mobile if (navLink && navLink.length) { for (const link of navLink) { const parentDiv = link.closest('div'); if (parentDiv) { parentDiv.addEventListener('click', () => { const parentLi = parentDiv.closest('li'); parentLi.classList.toggle('active'); }); } } } } const removeFilterOption = (toggle) => { const selectedOption = toggle.parentNode; for (const option of selectedOption.children) { if (option.classList.contains('active')) { option.classList.remove('active'); } } } const updateFormSelect = (toggle, selection) => { const selectedToggle = toggle.querySelector('.selected-toggle'); let optionCode; if (selectedToggle && selection.hasAttribute('data-option')) { selectedToggle.textContent = selection.getAttribute('data-option'); selectedToggle.setAttribute('data-value', selectedToggle.textContent); optionCode = selection.getAttribute('data-option-code'); } if (selectedToggle && selectedToggle.hasAttribute('data-select-handler')) { const pageUrlArr = window.location.href.split('?'); const pageUrl = pageUrlArr && pageUrlArr.length ? pageUrlArr[0] : null; window.location.href = pageUrl + (optionCode ? '?location=' + optionCode : ''); } } const filterHandler = (e) => { const searchFilterToggle = e.target.closest('.select-menu'); if (!searchFilterToggle) { const activeFilterToggle = document.querySelectorAll('.select-menu.show'); if (activeFilterToggle && activeFilterToggle.length) { for (const menu of activeFilterToggle) { // reset all active styling on toggle const activeToggle = menu.classList.contains('full-width') ? menu.previousElementSibling.querySelector('.select-toggle') : menu.previousElementSibling.closest('.select-toggle'); if (activeToggle) { activeToggle.classList.remove('active'); } if (menu.classList.contains('full-width') && e.target.closest('.select-menu-option')) { return false; } disableFilter(menu); } } } else if (e.target.closest('.select-menu-option')) { if (!e.target.closest('.full-width')) { // remove active styling on toggle const toggle = searchFilterToggle.previousElementSibling; if (toggle && toggle.classList.contains('active')) { toggle.classList.remove('active'); const errorFormField = toggle.closest('.form-field.has-error'); if (errorFormField) { errorFormField.classList.remove('has-error'); } } // remove current active selection removeFilterOption(e.target.closest('.select-menu-option')); // highlight current option as selected in menu e.target.closest('.select-menu-option').classList.add('active'); // closing the menu after disableFilter(searchFilterToggle); updateFormSelect(toggle, e.target); } } } const getMenuOptions = (filter) => { const arr = []; const options = filter.querySelectorAll('.select-menu-option input'); for (const option of options) { if (option.checked === true) { const value = option.parentNode ? option.parentNode.getAttribute('data-abbr') : null; if (value) { arr.push(value); } } } return arr.length ? arr : []; } const getMenuOption = (filter, isMobile) => { let option; if (isMobile) { const radios = filter.querySelectorAll('.select-menu-option input'); for (const radio of radios) { if (radio.checked) { option = radio.closest('label'); break; } } } else { option = filter.querySelector('.select-menu-option.active label'); } return option ? option.getAttribute('data-abbr') : null; } const getDateMenuOption = (filter) => { let option = filter.querySelector('.select-menu-option input[type="hidden"]'); return option ? option.value : null; } const getFilterPayload = (isClearAll, pageSize) => { const isMobileQuery = window.matchMedia("screen and (max-width: 576px)"); const isMobile = isMobileQuery ? isMobileQuery.matches : false; const defaultPageSize = document.querySelector('[data-default]'); const pg = 1; const numberOfDisplay = pageSize || (defaultPageSize ? defaultPageSize.getAttribute('data-default') : 10); const pageUrl = window.location.href.split('?'); const searchBarInput = document.querySelector('form input[data-url]'); const pageUrlQueries = pageUrl && (pageUrl.length > 1) ? pageUrl[1].split('&') : []; let keywordQueryArr; let keywordQueryVal; for (const query of pageUrlQueries) { if (query.indexOf('keyword') > -1) { keywordQueryArr = query.split('='); keywordQueryVal = keywordQueryArr && keywordQueryArr.length ? keywordQueryArr[1] : ''; } } const keyword = searchBarInput && searchBarInput.value ? searchBarInput.value : keywordQueryVal; const filters = isMobile ? document.querySelectorAll('.search-filter.mobile .select-menu') : document.querySelectorAll('.search-filter.desktop .select-menu'); if (!filters || !filters.length) { return pageSize ? { pageUrl: pageUrl && pageUrl.length ? pageUrl[0] : null, pg: pg, numberOfDisplay: numberOfDisplay, keyword: keyword, noFilter: true } : null; } let topics = null; let deliveryTypes = null; let period = null; let locations = null; let vendors = null; let guaranteed = null; let publishedFrom = null; let categories = null; for (const filter of filters) { const select = isMobile ? filter.previousElementSibling.querySelector('.nav-link') : filter.previousElementSibling.querySelector('.selected-toggle'); const type = select.getAttribute('data-filter-type'); switch (type) { case 'topic': topics = []; topics = getMenuOptions(filter); break; case 'deliveryType': deliveryTypes = []; deliveryTypes = getMenuOptions(filter); break; case 'period': period = getMenuOption(filter, isMobile); break; case 'location': locations = []; locations = getMenuOptions(filter); break; case 'vendor': vendors = []; vendors = getMenuOptions(filter); break; case 'guaranteed': guaranteed = false; guaranteed = getMenuOption(filter, isMobile); break; case 'publishedFrom': publishedFrom = getDateMenuOption(filter); break; case 'categories': categories = []; categories = getMenuOptions(filter); break; } } return { topic: topics, deliveryType: deliveryTypes, period: period, location: locations, vendor: vendors, guaranteed: typeof guaranteed === 'boolean' ? guaranteed.toString() : guaranteed, pg: pg, numberOfDisplay: numberOfDisplay, pageUrl: pageUrl && pageUrl.length ? pageUrl[0] : null, isClear: typeof isClearAll === 'boolean' ? isClearAll.toString() : null, keyword: keyword, publishedFrom: publishedFrom, categories: categories } }; const urlQueryBuilder = (url, type, value) => { const queries = url.split('?'); const operator = queries && (queries.length > 1) ? (queries[1] ? '&' : '') : '&'; if (value) { url += operator + type + '=' + value; } return url; } const getFilterUrl = (payload) => { let url = payload.pageUrl + '?'; if (payload.noFilter) { url = urlQueryBuilder(url, 'pg', payload.pg || ''); url = urlQueryBuilder(url, 'numberOfDisplay', payload.numberOfDisplay || ''); url = urlQueryBuilder(url, 'keyword', payload.keyword || ''); } else { url = urlQueryBuilder(url, 'topicStr', payload.topic ? payload.topic.join(',') : ''); url = urlQueryBuilder(url, 'deliveryTypeStr', payload.deliveryType ? payload.deliveryType.join(',') : ''); url = urlQueryBuilder(url, 'period', payload.period || ''); url = urlQueryBuilder(url, 'locationStr', payload.location ? payload.location.join(',') : ''); url = urlQueryBuilder(url, 'vendorStr', payload.vendor ? payload.vendor.join(',') : ''); url = urlQueryBuilder(url, 'guaranteed', payload.guaranteed || ''); url = urlQueryBuilder(url, 'pg', payload.pg || ''); url = urlQueryBuilder(url, 'numberOfDisplay', payload.numberOfDisplay || ''); url = urlQueryBuilder(url, 'isClear', payload.isClear || ''); url = urlQueryBuilder(url, 'keyword', payload.keyword || ''); url = urlQueryBuilder(url, 'publishedFrom', payload.publishedFrom || ''); url = urlQueryBuilder(url, 'categories', payload.categories ? payload.categories.join(',') : ''); } return url; } const handleSearchFilterEvents = () => { const isMobileQuery = window.matchMedia("screen and (max-width: 576px)"); const isMobile = isMobileQuery ? isMobileQuery.matches : false; const applyFilters = isMobile ? document.querySelector('.search-filter.mobile [data-btn="apply-filters"]') : document.querySelector('.search-filter.desktop [data-btn="apply-filters"]'); const clearAllFilters = isMobile ? document.querySelector('.search-filter.mobile [data-btn="clear-all-filters"]') : document.querySelector('.search-filter.desktop [data-btn="clear-all-filters"]'); if (applyFilters) { applyFilters.addEventListener('click', () => { const payload = getFilterPayload(false, null); if (payload) { window.location.href = getFilterUrl(payload); } }) } if (clearAllFilters) { clearAllFilters.addEventListener('click', () => { const payload = getFilterPayload(true, null); if (payload) { window.location.href = getFilterUrl(payload); } }) } const changePageSizes = document.querySelectorAll('[data-sel="per-page"]'); if (changePageSizes && changePageSizes.length) { for (const pageSize of changePageSizes) { pageSize.addEventListener('change', (event) => { const newPageSize = +(event.target['value']); const payload = getFilterPayload(false, newPageSize); if (payload) { window.location.href = getFilterUrl(payload); } }); } } }