/* ==========================================================================
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();
}