200 lines
7.5 KiB
JavaScript
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();
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|