course-landing / script.js
KairosEtp's picture
Create an online course landing page with course overview, curriculum breakdown with expandable modules, instructor credentials, student testimonials with videos, pricing and enrollment options, FAQ section, and money-back guarantee badge.
dfbfae0 verified
(function () {
const qs = (sel, ctx = document) => ctx.querySelector(sel);
const qsa = (sel, ctx = document) => Array.from(ctx.querySelectorAll(sel));
// Mobile menu
const menuToggle = qs('#menuToggle');
const mobileMenu = qs('#mobileMenu');
if (menuToggle && mobileMenu) {
menuToggle.addEventListener('click', () => {
const isHidden = mobileMenu.classList.contains('hidden');
mobileMenu.classList.toggle('hidden', !isHidden);
menuToggle.setAttribute('aria-expanded', String(isHidden));
});
}
// Expand/Collapse all curriculum modules
const expandBtn = qs('#expandAll');
const modules = qsa('.module');
if (expandBtn && modules.length) {
const toggleAll = () => {
const shouldOpen = expandBtn.dataset.state !== 'open';
modules.forEach((mod) => {
const content = qs('.module-content', mod);
const icon = qs('.module-icon', mod);
const summaryBtn = qs('.module-toggle', mod);
if (shouldOpen) {
openModule(mod, content, icon, summaryBtn, false);
} else {
closeModule(mod, content, icon, summaryBtn, false);
}
});
expandBtn.dataset.state = shouldOpen ? 'open' : 'closed';
const icon = qs('i', expandBtn);
if (icon) {
icon.setAttribute('data-feather', shouldOpen ? 'minus-square' : 'plus-square');
// Replace icon
if (window.feather && typeof feather.replace === 'function') {
feather.replace();
}
}
};
expandBtn.addEventListener('click', toggleAll);
}
// Individual module toggle
function openModule(module, content, icon, summaryBtn, animate = true) {
summaryBtn.setAttribute('aria-expanded', 'true');
content.classList.remove('hidden');
content.classList.add('open');
if (icon) icon.style.transform = 'rotate(180deg)';
if (animate) {
// auto height animation
content.style.maxHeight = '0px';
requestAnimationFrame(() => {
content.style.maxHeight = content.scrollHeight + 'px';
});
const onEnd = (e) => {
if (e.propertyName !== 'max-height') return;
content.style.maxHeight = 'none';
content.removeEventListener('transitionend', onEnd);
};
content.addEventListener('transitionend', onEnd);
} else {
content.style.maxHeight = 'none';
}
}
function closeModule(module, content, icon, summaryBtn, animate = true) {
summaryBtn.setAttribute('aria-expanded', 'false');
if (animate) {
// from current height to 0
content.style.maxHeight = content.scrollHeight + 'px';
requestAnimationFrame(() => {
content.style.maxHeight = '0px';
});
const onEnd = (e) => {
if (e.propertyName !== 'max-height') return;
content.classList.remove('open');
content.classList.add('hidden');
content.style.maxHeight = '';
content.removeEventListener('transitionend', onEnd);
};
content.addEventListener('transitionend', onEnd);
} else {
content.classList.remove('open');
content.classList.add('hidden');
content.style.maxHeight = '';
}
if (icon) icon.style.transform = 'rotate(0deg)';
}
modules.forEach((mod) => {
const content = qs('.module-content', mod);
const icon = qs('.module-icon', mod);
const summaryBtn = qs('.module-toggle', mod);
summaryBtn.addEventListener('click', (e) => {
e.preventDefault();
const isOpen = summaryBtn.getAttribute('aria-expanded') === 'true';
if (isOpen) {
closeModule(mod, content, icon, summaryBtn, true);
} else {
openModule(mod, content, icon, summaryBtn, true);
}
});
});
// FAQ accordion behavior: only one open at a time
const faqs = qsa('#faq details');
if (faqs.length) {
faqs.forEach((faq) => {
faq.addEventListener('toggle', () => {
if (faq.open) {
faqs.forEach((other) => {
if (other !== faq) other.removeAttribute('open');
});
}
});
});
}
// Smooth scroll offset for fixed header
const offset = 16; // header height-ish
qsa('a[href^="#"]').forEach((a) => {
a.addEventListener('click', (e) => {
const id = a.getAttribute('href');
if (!id || id === '#') return;
const el = qs(id);
if (!el) return;
e.preventDefault();
const top = el.getBoundingClientRect().top + window.scrollY - offset;
window.scrollTo({ top, behavior: 'smooth' });
history.pushState(null, '', id);
});
});
// Footer year
const yearEl = qs('#year');
if (yearEl) {
yearEl.textContent = String(new Date().getFullYear());
}
// Replace Feather icons if dynamically inserted
if (window.feather && typeof feather.replace === 'function') {
feather.replace();
}
})();