LE COURSIER || Journal d'Investigation & Géopolitique
// script.js - Scripts personnalisés et utilitaires
// Utilitaires généraux
class LeCoursierUtils {
static debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
static throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
}
}
static formatDate(date, locale = 'fr-FR') {
return new Date(date).toLocaleDateString(locale, {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
}
static truncateText(text, maxLength) {
if (text.length <= maxLength) return text;
return text.substr(0, maxLength).trim() + '...';
}
static getRandomColor() {
const colors = [
'var(--rouge-panafricain)',
'var(--jaune-panafricain)',
'var(--vert-panafricain)'
];
return colors[Math.floor(Math.random() * colors.length)];
}
}
// Gestionnaire de cookies
class CookieManager {
static setCookie(name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
static getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
static eraseCookie(name) {
document.cookie = name + '=; Max-Age=-99999999;';
}
}
// Gestionnaire de thème
class ThemeManager {
constructor() {
this.currentTheme = this.getStoredTheme() || 'light';
this.init();
}
init() {
this.applyTheme();
this.setupThemeToggle();
}
getStoredTheme() {
return CookieManager.getCookie('theme') ||
localStorage.getItem('lecoursier-theme');
}
storeTheme(theme) {
CookieManager.setCookie('theme', theme, 365);
localStorage.setItem('lecoursier-theme', theme);
}
applyTheme() {
document.documentElement.setAttribute('data-theme', this.currentTheme);
// Appliquer les variables CSS spécifiques au thème
if (this.currentTheme === 'dark') {
document.documentElement.style.setProperty('--background', '#1a1a1a');
document.documentElement.style.setProperty('--text', '#ffffff');
document.documentElement.style.setProperty('--card-bg', '#2d2d2d');
document.documentElement.style.setProperty('--border-color', '#444');
} else {
document.documentElement.style.setProperty('--background', '#ffffff');
document.documentElement.style.setProperty('--text', '#333333');
document.documentElement.style.setProperty('--card-bg', '#ffffff');
document.documentElement.style.setProperty('--border-color', '#ddd');
}
}
setupThemeToggle() {
// Dans une implémentation réelle, on pourrait ajouter un bouton de changement de thème
console.log('Theme manager initialisé. Thème actuel:', this.currentTheme);
}
toggleTheme() {
this.currentTheme = this.currentTheme === 'light' ? 'dark' : 'light';
this.storeTheme(this.currentTheme);
this.applyTheme();
}
}
// Gestionnaire d'analytics
class AnalyticsManager {
static trackEvent(category, action, label = null, value = null) {
if (typeof gtag !== 'undefined') {
gtag('event', action, {
'event_category': category,
'event_label': label,
'value': value
});
}
// Log pour le développement
console.log(`Analytics: ${category} - ${action}`, { label, value });
}
static trackPageView(pagePath) {
if (typeof gtag !== 'undefined') {
gtag('config', 'G-3VBXLVPQJ0', {
'page_path': pagePath
});
}
}
}
// Initialisation des fonctionnalités avancées
document.addEventListener('DOMContentLoaded', function() {
// Initialiser le gestionnaire de thème
const themeManager = new ThemeManager();
// Suivre les événements utilisateur
setupAnalyticsTracking();
// Gérer les formulaires avancés
setupFormValidation();
// Initialiser les tooltips Bootstrap
initBootstrapComponents();
// Configurer le service worker pour PWA (optionnel)
if ('serviceWorker' in navigator) {
registerServiceWorker();
}
console.log('Scripts personnalisés initialisés');
});
function setupAnalyticsTracking() {
// Suivre les clics sur les liens externes
document.querySelectorAll('a[href^="http"]').forEach(link => {
if (!link.href.includes(window.location.hostname)) {
link.addEventListener('click', function() {
AnalyticsManager.trackEvent(
'external_link',
'click',
this.href,
this.textContent.trim()
);
});
}
});
// Suivre les téléchargements
document.querySelectorAll('a[href$=".pdf"], a[href$=".doc"], a[href$=".docx"]').forEach(link => {
link.addEventListener('click', function() {
AnalyticsManager.trackEvent(
'download',
'click',
this.href,
this.textContent.trim()
);
});
});
// Suivre les soumissions de formulaire
document.querySelectorAll('form').forEach(form => {
form.addEventListener('submit', function() {
AnalyticsManager.trackEvent(
'form',
'submit',
this.id || this.className,
1
);
});
});
// Suivre le temps passé sur la page
let timeOnPage = 0;
const interval = setInterval(() => {
timeOnPage += 5;
// Envoyer des événements à des intervalles spécifiques
if (timeOnPage === 30) {
AnalyticsManager.trackEvent('engagement', '30_seconds', window.location.pathname);
}
if (timeOnPage === 60) {
AnalyticsManager.trackEvent('engagement', '1_minute', window.location.pathname);
}
if (timeOnPage === 180) {
AnalyticsManager.trackEvent('engagement', '3_minutes', window.location.pathname);
clearInterval(interval);
}
}, 5000);
// Nettoyer l'intervalle quand la page est déchargée
window.addEventListener('beforeunload', () => {
clearInterval(interval);
AnalyticsManager.trackEvent('engagement', 'time_on_page', window.location.pathname, timeOnPage);
});
}
function setupFormValidation() {
const forms = document.querySelectorAll('form[data-validate]');
forms.forEach(form => {
form.addEventListener('submit', function(e) {
if (!validateForm(this)) {
e.preventDefault();
showFormErrors(this);
}
});
// Validation en temps réel
const inputs = form.querySelectorAll('input[required], textarea[required]');
inputs.forEach(input => {
input.addEventListener('blur', function() {
validateInput(this);
});
});
});
}
function validateForm(form) {
let isValid = true;
const inputs = form.querySelectorAll('input[required], textarea[required]');
inputs.forEach(input => {
if (!validateInput(input)) {
isValid = false;
}
});
return isValid;
}
function validateInput(input) {
const value = input.value.trim();
let isValid = true;
let errorMessage = '';
// Réinitialiser les styles d'erreur
input.classList.remove('error');
const existingError = input.nextElementSibling;
if (existingError && existingError.classList.contains('error-message')) {
existingError.remove();
}
// Validation de base
if (!value) {
isValid = false;
errorMessage = 'Ce champ est requis';
} else if (input.type === 'email' && !isValidEmail(value)) {
isValid = false;
errorMessage = 'Veuillez entrer une adresse email valide';
} else if (input.type === 'tel' && !isValidPhone(value)) {
isValid = false;
errorMessage = 'Veuillez entrer un numéro de téléphone valide';
}
// Afficher l'erreur si nécessaire
if (!isValid) {
input.classList.add('error');
const errorElement = document.createElement('div');
errorElement.className = 'error-message';
errorElement.textContent = errorMessage;
errorElement.style.cssText = `
color: var(--rouge-panafricain);
font-size: 0.8rem;
margin-top: 5px;
`;
input.parentNode.insertBefore(errorElement, input.nextSibling);
}
return isValid;
}
function isValidEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
function isValidPhone(phone) {
const re = /^[\+]?[0-9\s\-\(\)]+$/;
return re.test(phone);
}
function showFormErrors(form) {
// Animation pour attirer l'attention sur les erreurs
const firstError = form.querySelector('.error');
if (firstError) {
firstError.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
// Animation de pulsation
firstError.style.animation = 'pulse 0.5s ease-in-out 3';
setTimeout(() => {
firstError.style.animation = '';
}, 1500);
}
// Ajouter l'animation CSS
const style = document.createElement('style');
style.textContent = `
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(227, 27, 35, 0.4); }
70% { box-shadow: 0 0 0 10px rgba(227, 27, 35, 0); }
100% { box-shadow: 0 0 0 0 rgba(227, 27, 35, 0); }
}
.error {
border-color: var(--rouge-panafricain) !important;
background-color: rgba(227, 27, 35, 0.05) !important;
}
`;
document.head.appendChild(style);
setTimeout(() => {
if (style.parentNode) {
style.parentNode.removeChild(style);
}
}, 2000);
}
function initBootstrapComponents() {
// Initialiser les tooltips
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
// Initialiser les popovers
const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
popoverTriggerList.map(function (popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl);
});
}
function registerServiceWorker() {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js').then(registration => {
console.log('ServiceWorker enregistré avec succès:', registration.scope);
}).catch(error => {
console.log('Échec de l\'enregistrement du ServiceWorker:', error);
});
});
}
// Export pour utilisation dans d'autres modules
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
LeCoursierUtils,
CookieManager,
ThemeManager,
AnalyticsManager
};
}
🔴 Enquête exclusive : Les nouveaux enjeux diplomatiques en Afrique de l'Ouest •
📰 Analyse : Impacts de la crise énergétique sur les économies émergentes •
🌍 Dossier spécial : Mouvements de jeunesse et démocratie en Afrique francophone •
Média indépendant spécialisé dans l'enquête approfondie et l'analyse géopolitique.
Notre mission : exercer un "devoir d'enquêter" et un "courage de révéler" pour informer le public,
promouvoir la transparence et tenir les puissants responsables.
Fondé en 2017, LE COURSIER s'est imposé comme une référence pour ceux qui cherchent
des informations vérifiées et des analyses approfondies sur les enjeux internationaux.
Investigation Rigoureuse
Nous recourons à des sources variées, multiplions les recoupements et
résistons à la tentation de l'exclusivité pour garantir la fiabilité de nos informations.
Analyse Géopolitique
Décryptage des dynamiques internationales, des relations entre États et
des enjeux stratégiques qui façonnent notre monde.
Indépendance Totale
Nous sommes indépendants de tous les pouvoirs économiques, politiques et idéologiques.
Seuls nos lecteurs peuvent nous acheter.
Thèmes abordés
Politique étrangèreConflits & SécuritéÉconomie mondialeMouvements sociauxEnvironnementDiplomatieDroits humainsTechnologie
Notre Équipe
Une équipe internationale de journalistes d'investigation, d'analystes géopolitiques
et de chercheurs universitaires.
Gara Takpara
Rédacteur en chef
15 ans d'expérience en journalisme d'investigation
Starkes panafrikanisches Design mit prägnanter Botschaft
LE COURSIER liefert tiefgründige Recherchen zu globalen Themen, um Klarheit zu schaffen und die Mächtigen zur Rechenschaft zu ziehen. Vertrauen Sie auf unabhängige Analysen, die Sie nirgendwo sonst finden.
This section provides a detailed and comprehensive overview of your company’s mission, values, and history. It highlights the key principles and values that drive the purpose, goals, and long-term success of your brand and business operations.
Le Coursier
LE COURSIER präsentiert sorgfältig recherchierte Analysen und Berichte, die tiefere Einblicke in globale Zusammenhänge bieten und zum kritischen Denken anregen.
Unabhängige Berichte, die den Mächtigen auf den Zahn fühlen
Entdecken Sie, wie wir tiefgehende Recherchen durchführen und komplexe geopolitische Zusammenhänge verständlich aufbereiten
Wie investigative Analyse globale Machtstrukturen offenlegt
Diese Reportage erläutert, wie gründliche Recherche und Faktenprüfung zur Aufdeckung internationaler Beziehungsgeflechte beitragen und Missstände offenlegen
Mit fundierter Recherche nachhaltigen Journalismus fördern
Dieser Beitrag zeigt, wie LE COURSIER durch kritische Analysen globale Themen beleuchtet und zur gesellschaftlichen Verantwortung anregt
Vertiefte Einblicke gewinnen durch unabhängige geopolitische Analyse
Dieser Artikel demonstriert, wie detaillierte Reportagen komplexe Außenpolitik, Konflikte und Wirtschaftsfragen verständlich machen