// Configuration partagée des types d'événements avec leurs emojis et descriptions
window.EVENT_TYPES = {
// Community / OSM
'community.osm.event': {
emoji: '🗺️',
label: 'Événement OpenStreetMap',
category: 'Communauté',
description: 'Événement lié à la communauté OpenStreetMap'
},
// Culture / Arts
'culture.arts': {
emoji: '🎨',
label: 'Arts et culture',
category: 'Culture',
description: 'Événement artistique et culturel'
},
'culture.geek': {
emoji: '🤓',
label: 'Culture geek',
category: 'Culture',
description: 'Événement geek, technologie, gaming'
},
'culture.music': {
emoji: '🎵',
label: 'Musique',
category: 'Culture',
description: 'Événement musical général'
},
// Music specific
'music.festival': {
emoji: '🎪',
label: 'Festival de musique',
category: 'Musique',
description: 'Festival musical'
},
// Power / Energy
'power.production.unavail': {
emoji: '⚡',
label: 'Production électrique indisponible',
category: 'Énergie',
description: 'Arrêt ou réduction de production électrique'
},
// Sale / Commerce
'sale': {
emoji: '🛒',
label: 'Vente / Commerce',
category: 'Commerce',
description: 'Événement commercial, vente, marché'
},
// Time / Temporal
'time.daylight.summer': {
emoji: '☀️',
label: 'Heure d\'été',
category: 'Temps',
description: 'Passage à l\'heure d\'été'
},
// Tourism
'tourism.exhibition': {
emoji: '🖼️',
label: 'Exposition',
category: 'Tourisme',
description: 'Exposition, salon, foire'
},
// Traffic / Transportation
'traffic.accident': {
emoji: '💥',
label: 'Accident',
category: 'Circulation',
description: 'Accident de la circulation'
},
'traffic.incident': {
emoji: '⚠️',
label: 'Incident de circulation',
category: 'Circulation',
description: 'Incident sur la route'
},
'traffic.obstacle': {
emoji: '🚧',
label: 'Obstacle',
category: 'Circulation',
description: 'Obstacle sur la voie'
},
'traffic.partially_closed': {
emoji: '🚦',
label: 'Voie partiellement fermée',
category: 'Circulation',
description: 'Fermeture partielle de voie'
},
'traffic.roadwork': {
emoji: '',
label: 'Travaux routiers',
category: 'Circulation',
description: 'Travaux sur la chaussée'
},
'wildlife': {
emoji: '🦌',
label: 'Animal',
category: 'Vie sauvage',
description: 'Détection d\'animaux'
},
'traffic.mammoth': {
emoji: '🦣',
label: 'Mammouth laineux',
category: 'Obstacle',
description: 'Un mammouth laineux bloque la route'
},
'hazard.piranha': {
emoji: '🐟',
label: 'Piranha dans la piscine',
category: 'Danger',
description: 'Des pirana attaquent dans cette piscine'
}
};
// Fonction pour obtenir les suggestions d'autocomplétion
function getEventTypeSuggestions(input) {
const inputLower = input.toLowerCase();
const suggestions = [];
for (const [key, config] of Object.entries(window.EVENT_TYPES)) {
// Recherche dans la clé, le label et la catégorie
const searchableText = `${key} ${config.label} ${config.category}`.toLowerCase();
if (searchableText.includes(inputLower)) {
suggestions.push({
value: key,
label: `${config.emoji} ${config.label}`,
category: config.category,
fullText: `${key} - ${config.label}`
});
}
}
// Trier par pertinence (correspondance exacte en premier)
suggestions.sort((a, b) => {
const aExact = a.value.toLowerCase().startsWith(inputLower);
const bExact = b.value.toLowerCase().startsWith(inputLower);
if (aExact && !bExact) return -1;
if (!aExact && bExact) return 1;
return a.value.localeCompare(b.value);
});
return suggestions.slice(0, 10); // Limiter à 10 suggestions
}
// Fonction pour initialiser l'autocomplétion sur un champ
function initializeEventTypeAutocomplete(inputElement, onSelect) {
if (!inputElement) return;
let suggestionsContainer = null;
let currentSuggestions = [];
let selectedIndex = -1;
let selectorButton = null;
// Créer le bouton de sélection
function createSelectorButton() {
selectorButton = document.createElement('button');
selectorButton.type = 'button';
selectorButton.className = 'event-type-selector-btn';
selectorButton.innerHTML = '📋 Types d\'événements';
selectorButton.style.cssText = `
margin-top: 5px;
padding: 6px 12px;
background-color: #0078ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
display: inline-block;
`;
selectorButton.addEventListener('click', function() {
showAllEventTypes();
});
const parent = inputElement.parentElement;
parent.appendChild(selectorButton);
}
// Créer le conteneur de suggestions
function createSuggestionsContainer() {
suggestionsContainer = document.createElement('div');
suggestionsContainer.className = 'autocomplete-suggestions';
suggestionsContainer.style.cssText = `
position: absolute;
top: 100%;
left: 0;
right: 0;
max-height: 300px;
overflow-y: auto;
background: white;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 1000;
display: none;
margin-top: 2px;
`;
// Positionner le conteneur parent en relatif
const parent = inputElement.parentElement;
if (parent.style.position !== 'relative') {
parent.style.position = 'relative';
}
parent.appendChild(suggestionsContainer);
}
// Afficher tous les types d'événements dans un beau sélecteur
function showAllEventTypes() {
const allTypes = Object.entries(window.EVENT_TYPES).map(([key, config]) => ({
value: key,
emoji: config.emoji,
label: config.label,
category: config.category,
description: config.description || '',
fullText: `${key} - ${config.label}`
}));
showEventTypeSelector(allTypes);
}
// Afficher le sélecteur de types d'événements
function showEventTypeSelector(types) {
if (!suggestionsContainer) return;
currentSuggestions = types;
selectedIndex = -1;
// Grouper par catégorie
const groupedTypes = {};
types.forEach(type => {
if (!groupedTypes[type.category]) {
groupedTypes[type.category] = [];
}
groupedTypes[type.category].push(type);
});
let html = `