/* ========================================================================== FAQ V2 CONTROLLER ========================================================================== */ const setupListClamps = () => { const listContainers = document.querySelectorAll('div[faq_answer_text_box_list_v2]'); listContainers.forEach(container => { const firstLi = container.querySelector('li'); if (firstLi && !firstLi.dataset.wrapped) { const originalContent = firstLi.innerHTML; firstLi.innerHTML = `${originalContent}`; firstLi.dataset.wrapped = 'true'; } }); }; class FAQController { constructor(barElement) { this.faqBar = barElement; this.container = this.faqBar.closest('.content_faq-v2') || this.faqBar.parentElement; this.plusIcon = this.container.querySelector('[plus]'); this.minusIcon = this.container.querySelector('[minus]'); this.faqContent = this.container.querySelector('[new_faq_content]'); this.textBox = this.container.querySelector('[faq_answer_text_box_v2]') || this.container.querySelector('[faq_answer_text_box_list_v2]'); this.setupSpacers(); this.isOpen = this.faqBar.getAttribute('aria-expanded') === 'true'; // Icon transitions can also be moved to CSS later if you want! if (this.plusIcon) this.plusIcon.style.transition = 'opacity 0.2s ease'; if (this.minusIcon) this.minusIcon.style.transition = 'opacity 0.2s ease'; if (this.textBox) this.textBox.style.overflow = 'hidden'; this.faqBar.addEventListener('click', () => this.toggle()); this.faqBar.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); this.toggle(); } }); this.faqBar.addEventListener("focus", () => { const rect = this.faqBar.getBoundingClientRect(); const headerOffset = 64; const viewportHeight = window.innerHeight; if (rect.top < headerOffset) { window.scrollBy({ top: rect.top - headerOffset, behavior: "smooth" }); } else if (rect.bottom > viewportHeight) { window.scrollBy({ top: rect.bottom - viewportHeight, behavior: "smooth" }); } }); this.updateDOM(true); } setupSpacers() { if (this.textBox) { const paragraphs = this.textBox.querySelectorAll('p'); paragraphs.forEach(p => { let html = p.innerHTML; html = html.replace(/(\s*)+$/gi, ""); if (html.includes('/gi, ''); } p.innerHTML = html; }); } } toggle() { this.isOpen = !this.isOpen; this.updateDOM(false); } updateDOM(isInit = false) { this.faqBar.setAttribute('aria-expanded', this.isOpen); if (this.faqContent) { this.faqContent.setAttribute('aria-hidden', !this.isOpen); } if (this.plusIcon && this.minusIcon) { this.plusIcon.style.opacity = this.isOpen ? '0' : '1'; this.minusIcon.style.opacity = this.isOpen ? '1' : '0'; } if (this.textBox) { if (isInit) { if (this.isOpen) { this.textBox.classList.add('expanded'); this.textBox.style.height = 'auto'; } else { this.textBox.classList.remove('expanded'); this.textBox.style.height = ''; } return; } if (this.isOpen) { this.animateOpen(); } else { this.animateClose(); } } } animateOpen() { const startHeight = this.textBox.offsetHeight; this.textBox.classList.add('expanded'); this.textBox.style.height = 'auto'; const endHeight = this.textBox.offsetHeight; this.textBox.style.height = `${startHeight}px`; void this.textBox.offsetHeight; // ADD CSS CLASS HERE this.textBox.classList.add('faq-is-animating'); this.textBox.style.height = `${endHeight}px`; const onTransitionEnd = (e) => { if (e.target !== this.textBox || e.propertyName !== 'height') return; this.textBox.removeEventListener('transitionend', onTransitionEnd); // REMOVE CSS CLASS HERE this.textBox.classList.remove('faq-is-animating'); if (this.isOpen) { this.textBox.style.height = 'auto'; } }; this.textBox.addEventListener('transitionend', onTransitionEnd); } animateClose() { this.textBox.classList.remove('expanded'); this.textBox.style.height = ''; const endHeight = this.textBox.offsetHeight; this.textBox.classList.add('expanded'); const startHeight = this.textBox.offsetHeight; this.textBox.style.height = `${startHeight}px`; void this.textBox.offsetHeight; // ADD CSS CLASS HERE this.textBox.classList.add('faq-is-animating'); this.textBox.style.height = `${endHeight}px`; const onTransitionEnd = (e) => { if (e.target !== this.textBox || e.propertyName !== 'height') return; this.textBox.removeEventListener('transitionend', onTransitionEnd); // REMOVE CSS CLASS HERE this.textBox.classList.remove('faq-is-animating'); if (!this.isOpen) { this.textBox.classList.remove('expanded'); this.textBox.style.height = ''; } }; this.textBox.addEventListener('transitionend', onTransitionEnd); } } const initFAQs = () => { setupListClamps(); const faqBars = document.querySelectorAll('[new_faq_bar]'); faqBars.forEach(bar => { if (!bar.dataset.faqInitialized) { new FAQController(bar); bar.dataset.faqInitialized = 'true'; } }); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initFAQs); } else { initFAQs(); }