class Footer { classes = { footer: 'js-footer', footerAccordionTrigger: 'js-footerAccordionTrigger', footerAccordionContent: 'js-footerAccordionContent', footerAccordionItem: 'js-footerAccordionItem', footerAccordionContentWrapper: 'js-footerAccordionContentWrapper' }; nodes = { footer: null, footerAccordionTrigger: null, footerAccordionContent: null, footerAccordionItems: null }; constructor() { // Cache DOM nodes this.nodes.footer = document.querySelector(`.${this.classes.footer}`); this.nodes.footerAccordionTrigger = this.nodes.footer.querySelectorAll(`.${this.classes.footerAccordionTrigger}`); this.nodes.footerAccordionContent = this.nodes.footer.querySelectorAll(`.${this.classes.footerAccordionContent}`); this.nodes.footerAccordionItems = this.nodes.footer.querySelectorAll(`.${this.classes.footerAccordionItem}`); this.handleResize = this.handleResize.bind(this); // Handle initial window size this.handleResize(); // Add resize event listener to handle window resize window.addEventListener('resize', this.handleResize, { passive: true }); } /** * Add all relevant event listeners to footer accordion triggers * @returns void */ addEventListeners() { if (this.nodes.footer) { this.openFooterAccordion = this.openFooterAccordion.bind(this); this.nodes.footer.addEventListener('click', this.openFooterAccordion); } } /** * Handle footer accordion opening/closing * @param {Event} event - The click event */ openFooterAccordion(event) { const footerAccordionTrigger = event.target; if (window.innerWidth >= 1024 || !footerAccordionTrigger || !footerAccordionTrigger.matches(`.${this.classes.footerAccordionTrigger}`)) { return; } const footerAccordionItem = footerAccordionTrigger.closest(`.${this.classes.footerAccordionItem}`); const footerAccordionContent = footerAccordionItem.querySelector(`.${this.classes.footerAccordionContent}`); const isActive = footerAccordionItem.classList.toggle('is--active'); // Set aria-expanded based on visibility footerAccordionTrigger.setAttribute('aria-expanded', isActive); // Set tabindex for links based on visibility const links = footerAccordionContent.querySelectorAll('a'); links.forEach(link => { link.setAttribute('tabindex', isActive ? '0' : '-1'); }); } calculateAccordionContentHeight() { this.nodes.footerAccordionItems.forEach(footerAccordionItem => { const footerAccordionContent = footerAccordionItem.querySelector(`.${this.classes.footerAccordionContent}`); const footerAccordionContentWrapper = footerAccordionItem.querySelector(`.${this.classes.footerAccordionContentWrapper}`); footerAccordionContentWrapper.style.setProperty('--accordion-item-height', footerAccordionContent.scrollHeight + 'px'); }); } /** * Handle window resize to add/remove event listeners and set tabindex * @returns void */ handleResize() { this.removeEventListeners(); if (window.innerWidth < 1024) { this.addEventListeners(); this.nodes.footerAccordionContent.forEach(content => { const links = content.querySelectorAll('a'); links.forEach(link => { link.setAttribute('tabindex', '-1'); }); }); this.calculateAccordionContentHeight(); } else { // Ensure footerAccordionTriggers are focusable when window width is greater than 1024px this.nodes.footerAccordionTrigger.forEach(trigger => { trigger.setAttribute('aria-expanded', 'true'); trigger.setAttribute('tabindex', '-1'); // Set tabindex to 0 }); this.nodes.footerAccordionContent.forEach(content => { const links = content.querySelectorAll('a'); links.forEach(link => { link.setAttribute('tabindex', '0'); }); }); } } /** * Remove all event listeners from footer accordion triggers * @returns void */ removeEventListeners() { if (this.nodes.footer) { this.nodes.footer.removeEventListener('click', this.openFooterAccordion); } } } window.addEventListener('DOMContentLoaded', () => { new Footer(); });