SHX-Theme/assets/localization-form.js

200 lines
7.5 KiB
JavaScript

if (!customElements.get('localization-form')) {
customElements.define(
'localization-form',
class LocalizationForm extends HTMLElement {
constructor() {
super();
this.mql = window.matchMedia('(min-width: 750px)');
this.header = document.querySelector('.header-wrapper');
this.elements = {
input: this.querySelector('input[name="locale_code"], input[name="country_code"]'),
button: this.querySelector('button.localization-form__select'),
panel: this.querySelector('.disclosure__list-wrapper'),
search: this.querySelector('input[name="country_filter"]'),
closeButton: this.querySelector('.country-selector__close-button'),
resetButton: this.querySelector('.country-filter__reset-button'),
searchIcon: this.querySelector('.country-filter__search-icon'),
liveRegion: this.querySelector('#sr-country-search-results'),
};
this.addEventListener('keyup', this.onContainerKeyUp.bind(this));
this.addEventListener('keydown', this.onContainerKeyDown.bind(this));
this.addEventListener('focusout', this.closeSelector.bind(this));
this.elements.button.addEventListener('click', this.openSelector.bind(this));
if (this.elements.search) {
this.elements.search.addEventListener('keyup', this.filterCountries.bind(this));
this.elements.search.addEventListener('focus', this.onSearchFocus.bind(this));
this.elements.search.addEventListener('blur', this.onSearchBlur.bind(this));
this.elements.search.addEventListener('keydown', this.onSearchKeyDown.bind(this));
}
if (this.elements.closeButton) {
this.elements.closeButton.addEventListener('click', this.hidePanel.bind(this));
}
if (this.elements.resetButton) {
this.elements.resetButton.addEventListener('click', this.resetFilter.bind(this));
this.elements.resetButton.addEventListener('mousedown', (event) => event.preventDefault());
}
this.querySelectorAll('a').forEach((item) => item.addEventListener('click', this.onItemClick.bind(this)));
}
hidePanel() {
this.elements.button.setAttribute('aria-expanded', 'false');
this.elements.panel.setAttribute('hidden', true);
if (this.elements.search) {
this.elements.search.value = '';
this.filterCountries();
this.elements.search.setAttribute('aria-activedescendant', '');
}
document.body.classList.remove('overflow-hidden-mobile');
document.querySelector('.menu-drawer').classList.remove('country-selector-open');
this.header.preventHide = false;
}
onContainerKeyDown(event) {
const focusableItems = Array.from(this.querySelectorAll('a')).filter(
(item) => !item.parentElement.classList.contains('hidden')
);
let focusedItemIndex = focusableItems.findIndex((item) => item === document.activeElement);
let itemToFocus;
switch (event.code.toUpperCase()) {
case 'ARROWUP':
event.preventDefault();
itemToFocus =
focusedItemIndex > 0 ? focusableItems[focusedItemIndex - 1] : focusableItems[focusableItems.length - 1];
itemToFocus.focus();
break;
case 'ARROWDOWN':
event.preventDefault();
itemToFocus =
focusedItemIndex < focusableItems.length - 1 ? focusableItems[focusedItemIndex + 1] : focusableItems[0];
itemToFocus.focus();
break;
}
if (!this.elements.search) return;
setTimeout(() => {
focusedItemIndex = focusableItems.findIndex((item) => item === document.activeElement);
if (focusedItemIndex > -1) {
this.elements.search.setAttribute('aria-activedescendant', focusableItems[focusedItemIndex].id);
} else {
this.elements.search.setAttribute('aria-activedescendant', '');
}
});
}
onContainerKeyUp(event) {
event.preventDefault();
switch (event.code.toUpperCase()) {
case 'ESCAPE':
if (this.elements.button.getAttribute('aria-expanded') == 'false') return;
this.hidePanel();
event.stopPropagation();
this.elements.button.focus();
break;
case 'SPACE':
if (this.elements.button.getAttribute('aria-expanded') == 'true') return;
this.openSelector();
break;
}
}
onItemClick(event) {
event.preventDefault();
const form = this.querySelector('form');
this.elements.input.value = event.currentTarget.dataset.value;
if (form) form.submit();
}
openSelector() {
this.elements.button.focus();
this.elements.panel.toggleAttribute('hidden');
this.elements.button.setAttribute(
'aria-expanded',
(this.elements.button.getAttribute('aria-expanded') === 'false').toString()
);
if (!document.body.classList.contains('overflow-hidden-tablet')) {
document.body.classList.add('overflow-hidden-mobile');
}
if (this.elements.search && this.mql.matches) {
this.elements.search.focus();
}
if (this.hasAttribute('data-prevent-hide')) {
this.header.preventHide = true;
}
document.querySelector('.menu-drawer').classList.add('country-selector-open');
}
closeSelector(event) {
if (
event.target.classList.contains('country-selector__overlay') ||
!this.contains(event.target) ||
!this.contains(event.relatedTarget)
) {
this.hidePanel();
}
}
filterCountries() {
const searchValue = this.elements.search.value.toLowerCase();
const popularCountries = this.querySelector('.popular-countries');
const allCountries = this.querySelectorAll('a');
let visibleCountries = allCountries.length;
this.elements.resetButton.classList.toggle('hidden', !searchValue);
if (popularCountries) {
popularCountries.classList.toggle('hidden', searchValue);
}
allCountries.forEach((item) => {
const countryName = item.querySelector('.country').textContent.toLowerCase();
if (countryName.indexOf(searchValue) > -1) {
item.parentElement.classList.remove('hidden');
visibleCountries++;
} else {
item.parentElement.classList.add('hidden');
visibleCountries--;
}
});
if (this.elements.liveRegion) {
this.elements.liveRegion.innerHTML = window.accessibilityStrings.countrySelectorSearchCount.replace(
'[count]',
visibleCountries
);
}
this.querySelector('.country-selector').scrollTop = 0;
this.querySelector('.country-selector__list').scrollTop = 0;
}
resetFilter(event) {
event.stopPropagation();
this.elements.search.value = '';
this.filterCountries();
this.elements.search.focus();
}
onSearchFocus() {
this.elements.searchIcon.classList.add('country-filter__search-icon--hidden');
}
onSearchBlur() {
if (!this.elements.search.value) {
this.elements.searchIcon.classList.remove('country-filter__search-icon--hidden');
}
}
onSearchKeyDown(event) {
if (event.code.toUpperCase() === 'ENTER') {
event.preventDefault();
}
}
}
);
}