Skip to content

Commit

Permalink
🚧 [#3018] Large refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
jiromaykin committed Feb 25, 2025
1 parent 586aaac commit d8b84b5
Show file tree
Hide file tree
Showing 11 changed files with 275 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</legend>
<div class="filter__list">

<div class="filter-bar__multiselect-listbox multiselect-listbox" id="selectDropdownWrapper">
<div class="filter-bar__multiselect-listbox multiselect-listbox">
<div class="multiselect-listbox__popup">
<button id="selectButton" type="button" class="button button__select selectButton" aria-haspopup="listbox" aria-expanded="false" aria-live="polite">
<span class="filter__legend-label">{{ field.label }}</span>:
Expand All @@ -30,8 +30,7 @@
</div>
</div>
</div>

</div>
</fieldset>
<hr class="divider divider--tiny">
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ function initFilterBar() {
anyChecked = true // Mark that we have at least one checkbox checked
const label = checkbox.nextElementSibling
selectedFilters.push(label.textContent.trim())
const frequencyCounter = label
.closest('.checkbox__input')
?.querySelector('.frequency-counter')

const frequencyCounter = label.querySelector('.frequency-counter')
const match = frequencyCounter.textContent.match(/\d+/)
const value = match ? parseInt(match[0]) : 0

Expand All @@ -46,96 +43,95 @@ function initFilterBar() {
}
})

document.querySelectorAll('.button__select').forEach((selectButton) => {
selectButton.innerHTML = '' // Clear the button content before appending new elements

let expandIcon = document.createElement('span')
expandIcon.classList.add('material-icons')
expandIcon.setAttribute('aria-hidden', 'true')
expandIcon.textContent = 'expand_more'

let closeIconWrapper = document.createElement('span')
closeIconWrapper.classList.add('close-icon') // Wrapper only, will get pointer-events
closeIconWrapper.setAttribute('tabindex', '0') // Adding tabindex for keyboard focus

let closeIcon = document.createElement('span')
closeIcon.classList.add('material-icons')
closeIcon.textContent = 'close'
closeIcon.setAttribute('aria-hidden', 'true') // Hiding iconfont for accessibility
closeIconWrapper.appendChild(closeIcon) // Add icon to wrapper for pointer-events

// Add text and icons based on selected filters
if (selectedFilters.length === 0) {
selectButton.textContent = 'Status '
selectButton.appendChild(expandIcon)
selectButton.classList.remove('active')
} else if (selectedFilters.length === 1) {
const ellipsisSpan = document.createElement('span')
ellipsisSpan.classList.add('ellipsis')
ellipsisSpan.textContent = selectedFilters[0]
selectButton.appendChild(ellipsisSpan)
selectButton.appendChild(closeIconWrapper) // Append wrapper
selectButton.classList.add('active')
} else {
selectButton.textContent = 'Status '
const activeFilterSpan = document.createElement('span')
activeFilterSpan.classList.add('active-filters')
activeFilterSpan.textContent = `${selectedFilters.length} actieve filters`
selectButton.appendChild(activeFilterSpan)
selectButton.appendChild(closeIconWrapper) // Append wrapper
selectButton.classList.add('active')
}
const selectButton = document.getElementById('selectButton')
selectButton.innerHTML = '' // Clear the button content before appending new elements

let expandIcon = document.createElement('span')
expandIcon.classList.add('material-icons')
expandIcon.setAttribute('aria-hidden', 'true')
expandIcon.textContent = 'expand_more'

let closeIconWrapper = document.createElement('span')
closeIconWrapper.classList.add('close-icon') // Wrapper only, will get pointer-events
closeIconWrapper.setAttribute('tabindex', '0') // Adding tabindex for keyboard focus

let closeIcon = document.createElement('span')
closeIcon.classList.add('material-icons')
closeIcon.textContent = 'close'
closeIcon.setAttribute('aria-hidden', 'true') // Hiding iconfont for accessibility
closeIconWrapper.appendChild(closeIcon) // Add icon to wrapper for pointer-events

// Add text and icons based on selected filters
if (selectedFilters.length === 0) {
selectButton.textContent = 'Status '
selectButton.appendChild(expandIcon)
selectButton.classList.remove('active')
} else if (selectedFilters.length === 1) {
const ellipsisSpan = document.createElement('span')
ellipsisSpan.classList.add('ellipsis')
ellipsisSpan.textContent = selectedFilters[0]
selectButton.appendChild(ellipsisSpan)
selectButton.appendChild(closeIconWrapper) // Append wrapper
selectButton.classList.add('active')
} else {
selectButton.textContent = 'Status '
const activeFilterSpan = document.createElement('span')
activeFilterSpan.classList.add('active-filters')
activeFilterSpan.textContent = `${selectedFilters.length} actieve filters`
selectButton.appendChild(activeFilterSpan)
selectButton.appendChild(closeIconWrapper) // Append wrapper
selectButton.classList.add('active')
}

const handleClose = function () {
checkboxes.forEach((checkbox) => {
checkbox.checked = false
})
calculateAndDisplayCheckedSum() // Recalculate and update the button and sum, even after refresh
const filterBarForm = document.querySelector('#filterBar .form')
if (filterBarForm) {
filterBarForm.submit()
}
const handleClose = function () {
checkboxes.forEach((checkbox) => {
checkbox.checked = false
})
calculateAndDisplayCheckedSum() // Recalculate and update the button and sum, even after refresh
const filterBarForm = document.querySelector('#filterBar .form')
if (filterBarForm) {
filterBarForm.submit()
}
}

closeIconWrapper.addEventListener('click', function (event) {
// Listen on wrapper
event.stopPropagation()
handleClose()
})
closeIconWrapper.addEventListener('click', function (event) {
// Listen on wrapper
event.stopPropagation()
handleClose()
})

// Add accessibility functionality for close icon-wrapper
closeIconWrapper.addEventListener('keydown', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault()
handleClose()
}
})
// Add accessibility functionality for close icon-wrapper
closeIconWrapper.addEventListener('keydown', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault()
handleClose()
}
})

selectButton.setAttribute('aria-live', 'polite')
selectButton.setAttribute('aria-live', 'polite')

const frequencySumElement = document.getElementById('frequencySum')
const resultTextElement = document.getElementById('resultText')
const frequencySumElement = document.getElementById('frequencySum')
const resultTextElement = document.getElementById('resultText')

if (frequencySumElement) {
frequencySumElement.textContent = sum
}
if (frequencySumElement) {
frequencySumElement.textContent = sum
}

if (resultTextElement) {
resultTextElement.textContent = sum === 1 ? 'resultaat' : 'resultaten'
}
if (resultTextElement) {
resultTextElement.textContent = sum === 1 ? 'resultaat' : 'resultaten'
}

// Handle visibility of resetMultiSelectFilters
const resetMultiSelectFilters = document.getElementById(
'resetMultiSelectFilters'
)
if (resetMultiSelectFilters) {
if (anyChecked) {
resetMultiSelectFilters.classList.remove('hide') // Show the button
} else {
resetMultiSelectFilters.classList.add('hide') // Hide the button
}
// Handle visibility of resetMultiSelectFilters
const resetMultiSelectFilters = document.getElementById(
'resetMultiSelectFilters'
)
if (resetMultiSelectFilters) {
if (anyChecked) {
resetMultiSelectFilters.classList.remove('hide') // Show the button
} else {
resetMultiSelectFilters.classList.add('hide') // Hide the button
}
})
}
}

const initSelectBehavior = function () {
Expand Down Expand Up @@ -290,5 +286,8 @@ document.body.addEventListener('htmx:afterSwap', function () {
document.addEventListener('click', function (e) {
if (e.target && e.target.classList.contains('pagination__link')) {
scrollToTopOfWindow() // Scroll up after clicking pagination
setTimeout(function () {
initFilterBar() // Reinitialize filter bar after HTMX swap from pagination
}, 20)
}
})
31 changes: 31 additions & 0 deletions src/open_inwoner/js/components/search/filter-dropdown-submit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export class FilterDropdownSubmit {
static selector = '.filter-dropdown'

constructor(node) {
this.node = node
this.submitButton = node.querySelector('.filter-dropdown__submit')
this.checkboxes = node.querySelectorAll(
'.filter-dropdown__list input[type="checkbox"]'
)

if (!this.submitButton || !this.checkboxes.length) return

this.checkboxes.forEach((checkbox) => {
checkbox.addEventListener('change', this.updateSubmitButton.bind(this))
})
}

updateSubmitButton() {
const selectedCount = this.node.querySelectorAll(
'.filter-dropdown__list input[type="checkbox"]:checked'
).length
this.submitButton.textContent = `Apply Filters (${selectedCount})`
}
}

/**
* Initialize only dropdowns with submit buttons
*/
document
.querySelectorAll(FilterDropdownSubmit.selector)
.forEach((dropdown) => new FilterDropdownSubmit(dropdown))
59 changes: 59 additions & 0 deletions src/open_inwoner/js/components/search/filter-dropdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export class FilterDropdown {
static selector = '.filter-dropdown'

constructor(node) {
this.node = node
this.button = node.querySelector('.filter-dropdown__button')
this.menu = node.querySelector('.filter-dropdown__menu')
this.checkboxes = node.querySelectorAll(
'.filter-dropdown__list input[type="checkbox"]'
)
this.clearButton = node.querySelector('.filter-dropdown__clear')
this.filterCount = node.querySelector('.filter-count')

if (!this.button || !this.menu || !this.checkboxes.length) return

this.button.addEventListener('click', this.toggleDropdown.bind(this))
document.addEventListener('click', this.closeDropdown.bind(this))

this.checkboxes.forEach((checkbox) => {
checkbox.addEventListener('change', this.updateFilters.bind(this))
})

if (this.clearButton) {
this.clearButton.addEventListener('click', this.clearFilters.bind(this))
}
}

toggleDropdown(event) {
event.preventDefault()
this.node.classList.toggle('open')
}

closeDropdown(event) {
if (!this.node.contains(event.target)) {
this.node.classList.remove('open')
}
}

updateFilters() {
const selectedCount = this.node.querySelectorAll(
'.filter-dropdown__list input[type="checkbox"]:checked'
).length
if (this.filterCount) {
this.filterCount.textContent = `(${selectedCount})`
}
}

clearFilters() {
this.checkboxes.forEach((checkbox) => (checkbox.checked = false))
this.updateFilters()
}
}

/**
* Initialize all dropdowns
*/
document
.querySelectorAll(FilterDropdown.selector)
.forEach((dropdown) => new FilterDropdown(dropdown))
12 changes: 3 additions & 9 deletions src/open_inwoner/js/components/search/filter-options.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
const searchForm = document.getElementById('search-form')
const selectors = [
'.filter .checkbox__input',
'.resetMultiSelectFilters',
'.resetAllFilters',
'.show-controls',
]

selectors.forEach((selector) => {
document.querySelectorAll(selector).forEach((element) => {
element.addEventListener('click', () => searchForm.submit())
document.querySelectorAll('.filter .checkbox__input').forEach((checkbox) => {
checkbox.addEventListener('change', (event) => {
searchForm.submit()
})
})
2 changes: 1 addition & 1 deletion src/open_inwoner/js/components/search/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import './filter-mobile'
import './filter-dropdown'
import './filter-options'

const searchForm = document.getElementById('search-form')
Expand Down
18 changes: 4 additions & 14 deletions src/open_inwoner/scss/components/Filter/Filter.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
.filter {
display: none;
@media (min-width: 768px) {
display: block;
}
border: 0 solid transparent;
margin: 0;
padding: 0;
Expand Down Expand Up @@ -106,18 +110,4 @@
display: none;
}
}

&--mobile {
.filter {
display: none;
}
}
}

.filter-bar__backdrop .show {
.filter-bar--mobile {
.filter {
display: block;
}
}
}
Loading

0 comments on commit d8b84b5

Please sign in to comment.