Team Ai
Apppublic

MAALOUFimad02/Machine_Learning_Training

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
shared.js395 linesDownload Raw Back to js
1/* ═══════════════════════════════════════════════════════════════════════════2   ML ACADEMY — SHARED JAVASCRIPT3   Animations et interactions communes à toutes les pages4   ═══════════════════════════════════════════════════════════════════════════ */5 6// ═══════════════════════════════════════════════════════════════════════════7// NAVIGATION ACTIVE STATE8// ═══════════════════════════════════════════════════════════════════════════9document.addEventListener('DOMContentLoaded', () => {10  // Mark active nav link based on current page11  const currentPage = window.location.pathname.split('/').pop() || 'index.html';12  13  document.querySelectorAll('.nav-link').forEach(link => {14    const href = link.getAttribute('href');15    if (href === currentPage || (currentPage === '' && href === 'index.html')) {16      link.classList.add('active');17    } else {18      link.classList.remove('active');19    }20  });21});22 23// ═══════════════════════════════════════════════════════════════════════════24// SMOOTH SCROLL FOR ANCHOR LINKS25// ═══════════════════════════════════════════════════════════════════════════26document.querySelectorAll('a[href^="#"]').forEach(anchor => {27  anchor.addEventListener('click', function(e) {28    e.preventDefault();29    const target = document.querySelector(this.getAttribute('href'));30    if (target) {31      const offsetTop = target.offsetTop - 100; // Account for fixed navbar32      window.scrollTo({33        top: offsetTop,34        behavior: 'smooth'35      });36    }37  });38});39 40// ═══════════════════════════════════════════════════════════════════════════41// SCROLL ANIMATIONS OBSERVER42// ═══════════════════════════════════════════════════════════════════════════43const scrollObserverOptions = {44  root: null,45  rootMargin: '0px 0px -100px 0px',46  threshold: 0.147};48 49const scrollObserver = new IntersectionObserver((entries) => {50  entries.forEach(entry => {51    if (entry.isIntersecting) {52      entry.target.classList.add('visible');53      54      // Add stagger delay for child elements if needed55      const staggerChildren = entry.target.querySelectorAll('.stagger-child');56      staggerChildren.forEach((child, index) => {57        child.style.animationDelay = `${index * 0.1}s`;58        child.classList.add('animate-in');59      });60    }61  });62}, scrollObserverOptions);63 64// Observe all elements with scroll-animate class65document.querySelectorAll('.scroll-animate').forEach(el => {66  scrollObserver.observe(el);67});68 69// ═══════════════════════════════════════════════════════════════════════════70// NAVBAR SCROLL EFFECT71// ═══════════════════════════════════════════════════════════════════════════72let lastScrollY = window.scrollY;73let ticking = false;74 75function updateNavbar() {76  const navbar = document.querySelector('.navbar');77  78  if (window.scrollY > 50) {79    navbar.style.background = 'rgba(15, 15, 26, 0.95)';80    navbar.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.3)';81  } else {82    navbar.style.background = 'rgba(15, 15, 26, 0.85)';83    navbar.style.boxShadow = 'none';84  }85  86  ticking = false;87}88 89window.addEventListener('scroll', () => {90  lastScrollY = window.scrollY;91  92  if (!ticking) {93    window.requestAnimationFrame(updateNavbar);94    ticking = true;95  }96});97 98// ═══════════════════════════════════════════════════════════════════════════99// PARALLAX EFFECT FOR HERO BACKGROUND100// ═══════════════════════════════════════════════════════════════════════════101const heroBg = document.querySelector('.hero-bg');102if (heroBg) {103  window.addEventListener('scroll', () => {104    const scrolled = window.scrollY;105    heroBg.style.transform = `translateY(${scrolled * 0.3}px)`;106  });107}108 109// ═══════════════════════════════════════════════════════════════════════════110// TYPING EFFECT FOR HERO TEXT (optional)111// ═══════════════════════════════════════════════════════════════════════════112function typeWriter(element, text, speed = 50) {113  let i = 0;114  element.textContent = '';115  116  function type() {117    if (i < text.length) {118      element.textContent += text.charAt(i);119      i++;120      setTimeout(type, speed);121    }122  }123  124  type();125}126 127// ═══════════════════════════════════════════════════════════════════════════128// COUNTER ANIMATION FOR STATS129// ═══════════════════════════════════════════════════════════════════════════130function animateCounter(element, target, duration = 2000) {131  let start = 0;132  const increment = target / (duration / 16);133  134  function updateCounter() {135    start += increment;136    if (start < target) {137      element.textContent = Math.floor(start);138      requestAnimationFrame(updateCounter);139    } else {140      element.textContent = target;141    }142  }143  144  updateCounter();145}146 147// Observe stat elements and animate when visible148const statObserver = new IntersectionObserver((entries) => {149  entries.forEach(entry => {150    if (entry.isIntersecting && !entry.target.classList.contains('counted')) {151      entry.target.classList.add('counted');152      const target = parseInt(entry.target.dataset.target);153      if (!isNaN(target)) {154        animateCounter(entry.target, target);155      }156    }157  });158}, { threshold: 0.5 });159 160document.querySelectorAll('[data-target]').forEach(el => {161  statObserver.observe(el);162});163 164// ═══════════════════════════════════════════════════════════════════════════165// MAGNETIC BUTTON EFFECT166// ═══════════════════════════════════════════════════════════════════════════167document.querySelectorAll('.btn').forEach(button => {168  button.addEventListener('mousemove', (e) => {169    const rect = button.getBoundingClientRect();170    const x = e.clientX - rect.left - rect.width / 2;171    const y = e.clientY - rect.top - rect.height / 2;172    173    button.style.transform = `translate(${x * 0.1}px, ${y * 0.1}px)`;174  });175  176  button.addEventListener('mouseleave', () => {177    button.style.transform = '';178  });179});180 181// ═══════════════════════════════════════════════════════════════════════════182// CARD HOVER 3D EFFECT183// ═══════════════════════════════════════════════════════════════════════════184document.querySelectorAll('.card, .feature-card, .module-card').forEach(card => {185  card.addEventListener('mousemove', (e) => {186    const rect = card.getBoundingClientRect();187    const x = e.clientX - rect.left;188    const y = e.clientY - rect.top;189    190    const centerX = rect.width / 2;191    const centerY = rect.height / 2;192    193    const rotateX = (y - centerY) / 20;194    const rotateY = (centerX - x) / 20;195    196    card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateZ(10px)`;197  });198  199  card.addEventListener('mouseleave', () => {200    card.style.transform = '';201  });202});203 204// ═══════════════════════════════════════════════════════════════════════════205// GLITCH EFFECT FOR TEXT (optional)206// ═══════════════════════════════════════════════════════════════════════════207function glitchText(element, originalText) {208  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';209  let iterations = 0;210  211  const interval = setInterval(() => {212    element.textContent = originalText213      .split('')214      .map((char, index) => {215        if (index < iterations) {216          return originalText[index];217        }218        return chars[Math.floor(Math.random() * chars.length)];219      })220      .join('');221    222    if (iterations >= originalText.length) {223      clearInterval(interval);224    }225    226    iterations += 1 / 3;227  }, 30);228}229 230// ═══════════════════════════════════════════════════════════════════════════231// PARTICLE MOUSE INTERACTION232// ═══════════════════════════════════════════════════════════════════════════233const particlesContainer = document.querySelector('.particles-container');234if (particlesContainer) {235  document.addEventListener('mousemove', (e) => {236    const particles = particlesContainer.querySelectorAll('.particle');237    const mouseX = e.clientX / window.innerWidth;238    const mouseY = e.clientY / window.innerHeight;239    240    particles.forEach((particle, index) => {241      const speed = (index + 1) * 0.5;242      const x = (mouseX - 0.5) * speed * 20;243      const y = (mouseY - 0.5) * speed * 20;244      245      particle.style.transform = `translate(${x}px, ${y}px)`;246    });247  });248}249 250// ═══════════════════════════════════════════════════════════════════════════251// LOADING ANIMATION252// ═══════════════════════════════════════════════════════════════════════════253window.addEventListener('load', () => {254  document.body.classList.add('loaded');255  256  // Animate elements with delay257  document.querySelectorAll('[data-delay]').forEach(el => {258    const delay = parseInt(el.dataset.delay);259    setTimeout(() => {260      el.classList.add('animate-in');261    }, delay);262  });263});264 265// ═══════════════════════════════════════════════════════════════════════════266// FORM VALIDATION HELPERS267// ═══════════════════════════════════════════════════════════════════════════268function validateEmail(email) {269  const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;270  return re.test(email);271}272 273function validateRequired(value) {274  return value.trim().length > 0;275}276 277// ═══════════════════════════════════════════════════════════════════════════278// TOOLTIP SYSTEM279// ═══════════════════════════════════════════════════════════════════════════280function createTooltip(element, text) {281  const tooltip = document.createElement('div');282  tooltip.className = 'tooltip';283  tooltip.textContent = text;284  tooltip.style.cssText = `285    position: absolute;286    background: var(--bg-tertiary);287    color: var(--text-primary);288    padding: 8px 12px;289    border-radius: 6px;290    font-size: 0.8rem;291    white-space: nowrap;292    z-index: 1000;293    opacity: 0;294    transition: opacity 0.3s ease;295    pointer-events: none;296  `;297  298  document.body.appendChild(tooltip);299  300  element.addEventListener('mouseenter', () => {301    const rect = element.getBoundingClientRect();302    tooltip.style.left = `${rect.left + rect.width / 2 - tooltip.offsetWidth / 2}px`;303    tooltip.style.top = `${rect.top - tooltip.offsetHeight - 8}px`;304    tooltip.style.opacity = '1';305  });306  307  element.addEventListener('mouseleave', () => {308    tooltip.style.opacity = '0';309  });310}311 312// ═══════════════════════════════════════════════════════════════════════════313// COPY TO CLIPBOARD314// ═══════════════════════════════════════════════════════════════════════════315async function copyToClipboard(text) {316  try {317    await navigator.clipboard.writeText(text);318    showNotification('Copié dans le presse-papier !', 'success');319  } catch (err) {320    showNotification('Erreur lors de la copie', 'error');321  }322}323 324// ═══════════════════════════════════════════════════════════════════════════325// NOTIFICATION SYSTEM326// ═══════════════════════════════════════════════════════════════════════════327function showNotification(message, type = 'info') {328  const notification = document.createElement('div');329  notification.className = `notification notification-${type}`;330  notification.textContent = message;331  notification.style.cssText = `332    position: fixed;333    top: 80px;334    right: 20px;335    padding: 12px 24px;336    background: var(--bg-card);337    border: 1px solid var(--border-color);338    border-radius: 8px;339    font-size: 0.9rem;340    z-index: 10000;341    animation: slideInRight 0.3s ease;342  `;343  344  if (type === 'success') {345    notification.style.borderColor = 'var(--success)';346    notification.style.color = 'var(--success)';347  } else if (type === 'error') {348    notification.style.borderColor = 'var(--danger)';349    notification.style.color = 'var(--danger)';350  }351  352  document.body.appendChild(notification);353  354  setTimeout(() => {355    notification.style.animation = 'slideOutRight 0.3s ease';356    setTimeout(() => notification.remove(), 300);357  }, 3000);358}359 360// ═══════════════════════════════════════════════════════════════════════════361// KEYBOARD SHORTCUTS362// ═══════════════════════════════════════════════════════════════════════════363document.addEventListener('keydown', (e) => {364  // Ctrl/Cmd + K for search (if implemented)365  if ((e.ctrlKey || e.metaKey) && e.key === 'k') {366    e.preventDefault();367    // Open search modal368  }369  370  // Escape to close modals371  if (e.key === 'Escape') {372    document.querySelectorAll('.modal.open').forEach(modal => {373      modal.classList.remove('open');374    });375  }376});377 378// ═══════════════════════════════════════════════════════════════════════════379// PREFERS REDUCED MOTION380// ═══════════════════════════════════════════════════════════════════════════381const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');382 383if (prefersReducedMotion.matches) {384  document.documentElement.style.setProperty('--transition-fast', '0s');385  document.documentElement.style.setProperty('--transition-base', '0s');386  document.documentElement.style.setProperty('--transition-slow', '0s');387}388 389// ═══════════════════════════════════════════════════════════════════════════390// CONSOLE EASTER EGG391// ═══════════════════════════════════════════════════════════════════════════392console.log('%c🧠 ML Academy', 'font-size: 24px; font-weight: bold; color: #6366f1;');393console.log('%cFormation Machine Learning — GE-MCI 4A', 'font-size: 14px; color: #94a3b8;');394console.log('%cBienvenue dans la console ! Curieux de voir comment ça marche ?', 'font-size: 12px; color: #64748b;');395