site-mva-global-fret/js/main.js
serge db43583a62
Some checks are pending
Deploy site to GitHub Pages / deploy (push) Waiting to run
fix(js): animate-on-scroll threshold 0.1 ? 0 (mobile cgv + politique invisible bug) (#7)
2026-05-07 16:37:39 +03:00

163 lines
4.8 KiB
JavaScript

document.addEventListener('DOMContentLoaded', () => {
const lang = localStorage.getItem('mva-lang') || 'fr';
applyLanguage(lang);
setupNav();
setupScrollEffects();
setupAnimations();
setupFAQ();
setActiveNavLink();
});
function applyLanguage(lang) {
document.documentElement.lang = lang;
localStorage.setItem('mva-lang', lang);
document.querySelectorAll('.lang-switcher button').forEach(btn => {
btn.classList.toggle('active', btn.dataset.lang === lang);
});
const t = translations[lang];
if (!t) return;
document.querySelectorAll('[data-i18n]').forEach(el => {
const keys = el.dataset.i18n.split('.');
let val = t;
for (const k of keys) {
val = val?.[k];
}
if (val !== undefined && val !== null) {
el.textContent = val;
}
});
document.querySelectorAll('[data-i18n-html]').forEach(el => {
const keys = el.dataset.i18nHtml.split('.');
let val = t;
for (const k of keys) {
val = val?.[k];
}
if (val !== undefined && val !== null) {
el.innerHTML = val.replace(/\n/g, '<br>');
}
});
document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
const keys = el.dataset.i18nPlaceholder.split('.');
let val = t;
for (const k of keys) {
val = val?.[k];
}
if (val !== undefined && val !== null) {
el.placeholder = val;
}
});
// Blocs de contenu long par langue (ex: page CGV)
document.querySelectorAll('[data-lang-block]').forEach(el => {
el.style.display = el.dataset.langBlock === lang ? '' : 'none';
});
}
function setupNav() {
document.querySelectorAll('.lang-switcher button').forEach(btn => {
btn.addEventListener('click', () => {
applyLanguage(btn.dataset.lang);
});
});
const menuToggle = document.getElementById('menuToggle');
const mobileNav = document.getElementById('mobileNav');
const overlay = document.getElementById('overlay');
if (menuToggle && mobileNav) {
menuToggle.addEventListener('click', () => {
menuToggle.classList.toggle('open');
mobileNav.classList.toggle('open');
overlay?.classList.toggle('open');
document.body.style.overflow = mobileNav.classList.contains('open') ? 'hidden' : '';
});
overlay?.addEventListener('click', () => {
menuToggle.classList.remove('open');
mobileNav.classList.remove('open');
overlay.classList.remove('open');
document.body.style.overflow = '';
});
mobileNav.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
menuToggle.classList.remove('open');
mobileNav.classList.remove('open');
overlay?.classList.remove('open');
document.body.style.overflow = '';
});
});
}
}
function setupScrollEffects() {
const header = document.querySelector('.header');
if (!header) return;
let lastScroll = 0;
window.addEventListener('scroll', () => {
const scrollY = window.scrollY;
header.classList.toggle('scrolled', scrollY > 50);
lastScroll = scrollY;
}, { passive: true });
}
function setupAnimations() {
const elements = document.querySelectorAll('.animate-on-scroll');
if (!elements.length) return;
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
// threshold: 0 (= fire dès qu'1px du bloc entre dans le viewport).
// Avant : threshold 0.1 (= 10%) ne fire jamais sur mobile portrait pour
// les pages cgv.html + politique-confidentialite.html dont les blocs
// .animate-on-scroll font 2000-3000px de hauteur (contenu trilingue
// FR/EN/MG verbose) — la viewport mobile ~600px n'atteint jamais 10%.
}, { threshold: 0, rootMargin: '0px 0px -50px 0px' });
elements.forEach(el => observer.observe(el));
}
function setupFAQ() {
document.querySelectorAll('.faq-question').forEach(btn => {
btn.addEventListener('click', () => {
const item = btn.closest('.faq-item');
const answer = item.querySelector('.faq-answer');
const isOpen = item.classList.contains('open');
document.querySelectorAll('.faq-item.open').forEach(openItem => {
openItem.classList.remove('open');
openItem.querySelector('.faq-answer').style.maxHeight = '0';
});
if (!isOpen) {
item.classList.add('open');
answer.style.maxHeight = answer.scrollHeight + 'px';
}
});
});
}
function setActiveNavLink() {
const path = window.location.pathname;
const filename = path.split('/').pop() || 'index.html';
document.querySelectorAll('.nav a, .mobile-nav a').forEach(link => {
const href = link.getAttribute('href');
if (href === filename || (filename === '' && href === 'index.html')) {
link.classList.add('active');
link.setAttribute('aria-current', 'page');
}
});
}