Files
kaubuntu.re/js/main.js
T

430 lines
16 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function() {
// Détection de l'état de connexion
function updateOnlineStatus() {
const offlineIndicator = document.querySelector('.offline-indicator');
if (!navigator.onLine) {
if (!offlineIndicator) {
const indicator = document.createElement('div');
indicator.className = 'offline-indicator show';
indicator.textContent = 'Mode hors ligne - Fonctionnalités limitées';
document.body.insertBefore(indicator, document.body.firstChild);
}
} else {
if (offlineIndicator) {
offlineIndicator.remove();
}
}
}
// Écouter les changements de connexion
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOnlineStatus);
// Vérifier l'état initial
updateOnlineStatus();
// Gestion du menu mobile
const mobileMenuToggle = document.querySelector('.mobile-menu-toggle');
const mobileMenu = document.querySelector('.mobile-menu');
const mobileMenuClose = document.querySelector('.mobile-menu-close');
if (mobileMenuToggle) {
mobileMenuToggle.addEventListener('click', function() {
mobileMenu.classList.add('active');
document.body.style.overflow = 'hidden'; // Empêche le défilement de la page
});
}
if (mobileMenuClose) {
mobileMenuClose.addEventListener('click', function() {
mobileMenu.classList.remove('active');
document.body.style.overflow = ''; // Réactive le défilement
});
}
// Gestion du theme (mode clair/sombre)
const themeToggle = document.querySelector('#theme-toggle');
const html = document.documentElement;
// Charger le thème sauvegardé ou détecter la préférence système
function initTheme() {
const savedTheme = localStorage.getItem('theme');
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
let currentTheme = savedTheme;
if (!savedTheme) {
currentTheme = systemPrefersDark ? 'dark' : 'light';
}
applyTheme(currentTheme);
updateThemeIcon(currentTheme);
}
// Appliquer le thème
function applyTheme(theme) {
if (theme === 'dark') {
html.setAttribute('data-theme', 'dark');
} else {
html.removeAttribute('data-theme');
}
}
// Mettre à jour l'icône du bouton
function updateThemeIcon(theme) {
if (themeToggle) {
const icon = themeToggle.querySelector('i');
if (theme === 'dark') {
icon.classList.remove('fa-sun');
icon.classList.add('fa-moon');
themeToggle.setAttribute('aria-label', 'Basculer vers le mode clair');
themeToggle.setAttribute('title', 'Mode clair');
} else {
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
themeToggle.setAttribute('aria-label', 'Basculer vers le mode sombre');
themeToggle.setAttribute('title', 'Mode sombre');
}
}
}
// Basculer le thème
function toggleTheme() {
const currentTheme = html.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
applyTheme(newTheme);
updateThemeIcon(newTheme);
localStorage.setItem('theme', newTheme);
}
// Event listener pour le bouton
if (themeToggle) {
themeToggle.addEventListener('click', toggleTheme);
}
// Écouter les changements de préférence système
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
if (!localStorage.getItem('theme')) {
const newTheme = e.matches ? 'dark' : 'light';
applyTheme(newTheme);
updateThemeIcon(newTheme);
}
});
// Initialiser le thème
initTheme();
// Gestion des carousels
const carousels = document.querySelectorAll('.carousel');
carousels.forEach(carousel => {
const container = carousel.querySelector('.carousel-container');
const dots = carousel.querySelectorAll('.carousel-dot');
const items = carousel.querySelectorAll('.carousel-item');
if (dots.length > 0 && items.length > 0) {
let currentIndex = 0;
let startX = 0;
let currentX = 0;
let isDragging = false;
let startTransform = 0;
function getItemWidth() {
return items[0].offsetWidth + parseInt(getComputedStyle(items[0]).marginRight);
}
function updateCarousel(index) {
const itemWidth = getItemWidth();
const newTransform = -index * itemWidth;
container.style.transform = `translateX(${newTransform}px)`;
// Mettre à jour les dots
dots.forEach(d => d.classList.remove('active'));
if (dots[index]) {
dots[index].classList.add('active');
}
currentIndex = index;
}
dots.forEach((dot, index) => {
dot.addEventListener('click', function() {
updateCarousel(index);
});
});
container.addEventListener('touchstart', function(e) {
isDragging = true;
startX = e.touches[0].clientX;
const transform = window.getComputedStyle(container).transform;
if (transform !== 'none') {
const matrix = new DOMMatrix(transform);
startTransform = matrix.m41;
} else {
startTransform = 0;
}
container.style.transition = 'none';
}, { passive: true });
container.addEventListener('touchmove', function(e) {
if (!isDragging) return;
currentX = e.touches[0].clientX;
const diff = currentX - startX;
const newTransform = startTransform + diff;
container.style.transform = `translateX(${newTransform}px)`;
}, { passive: true });
container.addEventListener('touchend', function(e) {
if (!isDragging) return;
isDragging = false;
container.style.transition = 'transform 0.5s ease';
const diff = currentX - startX;
const threshold = 50; // Distance minimale pour considérer un swipe
// Déterminer la direction du swipe
if (Math.abs(diff) > threshold) {
if (diff > 0 && currentIndex > 0) {
// Swipe vers la droite - item précédent
updateCarousel(currentIndex - 1);
} else if (diff < 0 && currentIndex < items.length - 1) {
// Swipe vers la gauche - item suivant
updateCarousel(currentIndex + 1);
} else {
// Retour à la position actuelle
updateCarousel(currentIndex);
}
} else {
// Mouvement trop petit, retour à la position actuelle
updateCarousel(currentIndex);
}
currentX = 0;
}, { passive: true });
// Support du drag sur desktop (optionnel)
container.addEventListener('mousedown', function(e) {
isDragging = true;
startX = e.clientX;
const transform = window.getComputedStyle(container).transform;
if (transform !== 'none') {
const matrix = new DOMMatrix(transform);
startTransform = matrix.m41;
} else {
startTransform = 0;
}
container.style.transition = 'none';
container.style.cursor = 'grabbing';
e.preventDefault();
});
document.addEventListener('mousemove', function(e) {
if (!isDragging) return;
currentX = e.clientX;
const diff = currentX - startX;
const newTransform = startTransform + diff;
container.style.transform = `translateX(${newTransform}px)`;
});
document.addEventListener('mouseup', function(e) {
if (!isDragging) return;
isDragging = false;
container.style.transition = 'transform 0.5s ease';
container.style.cursor = 'grab';
const diff = currentX - startX;
const threshold = 50;
if (Math.abs(diff) > threshold) {
if (diff > 0 && currentIndex > 0) {
updateCarousel(currentIndex - 1);
} else if (diff < 0 && currentIndex < items.length - 1) {
updateCarousel(currentIndex + 1);
} else {
updateCarousel(currentIndex);
}
} else {
updateCarousel(currentIndex);
}
currentX = 0;
});
}
});
// Gestion des clics sur les vidéos
function initVideoCardClicks() {
const videoCards = document.querySelectorAll('.video-card');
videoCards.forEach(card => {
if (!card.hasAttribute('data-click-initialized')) {
card.setAttribute('data-click-initialized', 'true');
card.addEventListener('click', function() {
const videoId = this.dataset.videoId;
if (videoId) {
window.location.href = 'video.php?id=' + videoId;
}
});
}
});
}
// Initialiser les clics sur les vidéos existantes
initVideoCardClicks();
// Lazy loading des images
function initLazyLoading() {
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
const src = img.getAttribute('data-src');
if (src) {
img.src = src;
img.removeAttribute('data-src');
}
observer.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => {
imageObserver.observe(img);
});
} else {
// Fallback pour les navigateurs qui ne supportent pas IntersectionObserver
document.querySelectorAll('img[data-src]').forEach(img => {
const src = img.getAttribute('data-src');
if (src) {
img.src = src;
img.removeAttribute('data-src');
}
});
}
}
// Initialiser le lazy loading
initLazyLoading();
// Gestion des boutons "Voir plus"
const viewMoreButtons = document.querySelectorAll('.view-more');
viewMoreButtons.forEach(button => {
// Déterminer le type de vidéos à charger
const section = button.closest('.video-section');
const sectionTitle = section.querySelector('.section-title').textContent.trim().toLowerCase();
const videoGrid = section.querySelector('.video-grid');
let videoType = '';
let categoryId = null;
if (sectionTitle.includes('dernières')) {
videoType = 'recent';
} else if (sectionTitle.includes('tendances')) {
videoType = 'trending';
} else if (sectionTitle.includes('indépendance')) {
videoType = 'independence';
} else {
// Vérifier si c'est une section de catégorie
const categorySection = section.querySelector('[data-category-id]');
if (categorySection) {
videoType = 'category';
categoryId = categorySection.dataset.categoryId;
} else if (section.hasAttribute('data-category-id')) {
videoType = 'category';
categoryId = section.dataset.categoryId;
}
}
// Si aucun type reconnu, ne pas configurer l'événement
if (!videoType) return;
// Stocker le numéro de page actuel
button.dataset.page = '1';
button.addEventListener('click', function() {
const page = parseInt(this.dataset.page);
// Changer le texte du bouton pendant le chargement
button.textContent = 'Chargement...';
button.disabled = true;
// Préparer l'URL avec les paramètres
let url = `ajax/load-more-videos.php?type=${videoType}&page=${page}`;
if (videoType === 'category' && categoryId) {
url += `&category=${categoryId}`;
}
// Préparer les données avec token CSRF
const formData = new FormData();
formData.append('csrf_token', document.querySelector('meta[name="csrf-token"]').getAttribute('content'));
// Faire la requête AJAX
fetch(url, {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Ajouter les nouvelles vidéos à la grille
const tempDiv = document.createElement('div');
tempDiv.innerHTML = data.html;
// Ajouter chaque vidéo à la grille
while (tempDiv.firstChild) {
videoGrid.appendChild(tempDiv.firstChild);
}
// Mettre à jour le numéro de page
this.dataset.page = data.page + 1;
// Réinitialiser le texte du bouton
button.textContent = 'Voir plus';
button.disabled = false;
// Si plus de vidéos à charger, masquer le bouton
if (!data.hasMore) {
button.style.display = 'none';
}
// Initialiser les clics sur les nouvelles vidéos
initVideoCardClicks();
// Initialiser le lazy loading pour les nouvelles images
initLazyLoading();
} else {
// En cas d'erreur, afficher un message et réactiver le bouton
console.error('Erreur lors du chargement des vidéos:', data.error);
button.textContent = 'Voir plus';
button.disabled = false;
}
})
.catch(error => {
console.error('Erreur lors de la requête AJAX:', error);
button.textContent = 'Voir plus';
button.disabled = false;
});
});
});
// Scroll vers le haut avec effet moderne quand on clique sur le logo du footer
const footerLogo = document.querySelector('.footer-logo');
if (footerLogo) {
footerLogo.addEventListener('click', function() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
}
});