403Webshell
Server IP : 46.105.57.169  /  Your IP : 216.73.217.35
Web Server : Apache
System : Linux webm002.cluster120.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User : verseaumee ( 152031)
PHP Version : 8.5.7
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/verseaumee/quaadraa/js/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/verseaumee/quaadraa/js/main.js
'use strict';

window.addEventListener('load', () => {
  const loader = document.getElementById('page-loader');
  if (loader) {
    setTimeout(() => loader.classList.add('loaded'), 800);
  }
});

(function initHeader() {
  const header = document.getElementById('site-header');
  if (!header) return;

  const onScroll = () => {
    header.classList.toggle('scrolled', window.scrollY > 60);
  };
  window.addEventListener('scroll', onScroll, { passive: true });
  onScroll();
})();

(function initNav() {
  document.querySelectorAll('.nav-dropdown-btn').forEach(btn => {
    btn.addEventListener('click', () => {
      const expanded = btn.getAttribute('aria-expanded') === 'true';
      document.querySelectorAll('.nav-dropdown-btn').forEach(b => {
        b.setAttribute('aria-expanded', 'false');
        b.closest('.has-dropdown')?.querySelector('.dropdown-panel')?.classList.remove('open');
      });
      if (!expanded) {
        btn.setAttribute('aria-expanded', 'true');
        btn.closest('.has-dropdown')?.querySelector('.dropdown-panel')?.classList.add('open');
      }
    });
  });

  document.addEventListener('click', e => {
    if (!e.target.closest('.has-dropdown')) {
      document.querySelectorAll('.nav-dropdown-btn').forEach(b => {
        b.setAttribute('aria-expanded', 'false');
        b.closest('.has-dropdown')?.querySelector('.dropdown-panel')?.classList.remove('open');
      });
    }
  });

  const hamburger = document.querySelector('.nav-hamburger');
  const mobileMenu = document.getElementById('mobile-menu');
  const overlay    = document.querySelector('.mobile-overlay');

  const openMenu = () => {
    hamburger.classList.add('open');
    hamburger.setAttribute('aria-expanded', 'true');
    mobileMenu.hidden = false;
    overlay.classList.add('active');
    document.body.style.overflow = 'hidden';
    mobileMenu.querySelector('a')?.focus();
  };

  const closeMenu = () => {
    hamburger.classList.remove('open');
    hamburger.setAttribute('aria-expanded', 'false');
    mobileMenu.hidden = true;
    overlay.classList.remove('active');
    document.body.style.overflow = '';
    hamburger.focus();
  };

  hamburger?.addEventListener('click', () => {
    mobileMenu.hidden ? openMenu() : closeMenu();
  });
  overlay?.addEventListener('click', closeMenu);

  document.addEventListener('keydown', e => {
    if (e.key === 'Escape' && !mobileMenu?.hidden) closeMenu();
  });
})();

(function initCarousel() {
  const carousel = document.getElementById('news-carousel');
  if (!carousel) return;

  const cards     = carousel.querySelectorAll('.news-card');
  const dotsWrap  = document.querySelector('.carousel-dots');
  const prevBtn   = document.querySelector('.carousel-prev');
  const nextBtn   = document.querySelector('.carousel-next');

  if (!cards.length) return;

  let currentIndex = 0;
  let autoTimer;

  cards.forEach((_, i) => {
    const dot = document.createElement('button');
    dot.className = 'carousel-dot' + (i === 0 ? ' active' : '');
    dot.setAttribute('role', 'tab');
    dot.setAttribute('aria-label', `Actualité ${i + 1}`);
    dot.setAttribute('aria-selected', i === 0 ? 'true' : 'false');
    dot.addEventListener('click', () => goTo(i));
    dotsWrap?.appendChild(dot);
  });

  const dots = () => dotsWrap?.querySelectorAll('.carousel-dot');

  function goTo(index) {
    currentIndex = Math.max(0, Math.min(index, cards.length - 1));
    const card = cards[currentIndex];
    
    carousel.scrollTo({
      left: card.offsetLeft,
      behavior: 'smooth'
    });

    dots()?.forEach((d, i) => {
      d.classList.toggle('active', i === currentIndex);
      d.setAttribute('aria-selected', i === currentIndex ? 'true' : 'false');
    });
  }

  prevBtn?.addEventListener('click', () => {
    goTo(currentIndex > 0 ? currentIndex - 1 : cards.length - 1);
    resetAuto();
  });
  nextBtn?.addEventListener('click', () => {
    goTo(currentIndex < cards.length - 1 ? currentIndex + 1 : 0);
    resetAuto();
  });

  function startAuto() {
    autoTimer = setInterval(() => {
      goTo(currentIndex < cards.length - 1 ? currentIndex + 1 : 0);
    }, 5000);
  }
  function resetAuto() { clearInterval(autoTimer); startAuto(); }

  carousel.addEventListener('mouseenter', () => clearInterval(autoTimer));
  carousel.addEventListener('mouseleave', startAuto);

  let startX = 0;
  carousel.addEventListener('touchstart', e => { startX = e.touches[0].clientX; }, { passive: true });
  carousel.addEventListener('touchend', e => {
    const dx = e.changedTouches[0].clientX - startX;
    if (Math.abs(dx) > 50) {
      goTo(dx < 0 ? Math.min(currentIndex + 1, cards.length - 1) : Math.max(currentIndex - 1, 0));
      resetAuto();
    }
  });

  startAuto();
})();

(function initScrollReveal() {
  if (!('IntersectionObserver' in window)) return;

  const elements = document.querySelectorAll('[data-scroll-reveal], [data-reveal], [data-reveal-delay]');

  const style = document.createElement('style');
  style.textContent = `
    [data-scroll-reveal], [data-reveal] {
      opacity: 0;
      transform: translateY(30px);
      transition: opacity .8s cubic-bezier(0.16,1,0.3,1), transform .8s cubic-bezier(0.16,1,0.3,1);
    }
    [data-reveal-delay] {
      opacity: 0;
      transform: translateY(20px);
      transition: opacity .7s cubic-bezier(0.16,1,0.3,1) var(--reveal-delay, 0ms),
                  transform .7s cubic-bezier(0.16,1,0.3,1) var(--reveal-delay, 0ms);
    }
    [data-scroll-reveal].revealed,
    [data-reveal].revealed,
    [data-reveal-delay].revealed {
      opacity: 1;
      transform: none;
    }
  `;
  document.head.appendChild(style);

  document.querySelectorAll('[data-reveal-delay]').forEach(el => {
    el.style.setProperty('--reveal-delay', el.dataset.revealDelay + 'ms');
  });

  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.classList.add('revealed');
        observer.unobserve(entry.target);
      }
    });
  }, { threshold: 0.12, rootMargin: '0px 0px -60px 0px' });

  elements.forEach(el => observer.observe(el));
})();

(function initCounters() {
  const counters = document.querySelectorAll('[data-count]');
  if (!counters.length) return;

  const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
      if (!entry.isIntersecting) return;
      const el  = entry.target;
      const end = parseInt(el.dataset.count, 10);
      const dur = 1500;
      const step = end / (dur / 16);
      let current = 0;
      const tick = () => {
        current = Math.min(current + step, end);
        el.textContent = Math.floor(current) + (el.dataset.suffix || '');
        if (current < end) requestAnimationFrame(tick);
      };
      requestAnimationFrame(tick);
      observer.unobserve(el);
    });
  }, { threshold: 0.5 });

  counters.forEach(c => observer.observe(c));
})();

document.querySelectorAll('a[href^="#"]').forEach(anchor => {
  anchor.addEventListener('click', e => {
    const target = document.querySelector(anchor.getAttribute('href'));
    if (!target) return;
    e.preventDefault();
    const headerH = parseInt(getComputedStyle(document.documentElement)
      .getPropertyValue('--header-h')) || 110;
    const top = target.getBoundingClientRect().top + window.scrollY - headerH - 16;
    window.scrollTo({ top, behavior: 'smooth' });
  });
});

(function initContactForm() {
  const form = document.querySelector('.contact-form');
  if (!form) return;

  form.querySelectorAll('input[required], textarea[required]').forEach(field => {
    field.addEventListener('blur', () => {
      const group = field.closest('.form-group');
      if (!group) return;
      if (!field.value.trim()) {
        group.classList.add('has-error');
      } else {
        group.classList.remove('has-error');
      }
    });
  });

  form.addEventListener('submit', e => {
    const btn = form.querySelector('.btn-submit');
    if (btn) {
      btn.disabled = true;
      btn.textContent = 'Envoi en cours…';
    }
  });
})();

Youez - 2016 - github.com/yon3zu
LinuXploit