1// Constantes globales pour les sélecteurs et classes, pour une meilleure maintenabilité. 2const POPUP_CONSTANTS = { 3 OVERLAY_ID: 'globalPopupOverlay', 4 TRIGGER_SELECTOR: '[data-popup-id]', 5 POPUP_SELECTOR: '.popup-moderne', 6 CONTENT_SELECTOR: '.popup-contenu', 7 CLOSE_BUTTON_SELECTOR: '.popup-fermer', 8 ACTIVE_CLASS: 'est-actif', 9 BODY_OPEN_CLASS: 'popup-ouverte', 10 ARIA_HIDDEN_ATTR: 'aria-hidden', 11 DATA_POPUP_URL: 'popupUrl', 12 DATA_POPUP_SOURCE_ID: 'popupSourceId', // pour chargement contenu div cachée dans la page 13 DATA_ORIGINAL_CONTENT: 'originalContent', 14}; 15 16const TABS_CONSTANTS = { 17 HIDDEN_CLASS: 'hidden', 18 // Les autres sélecteurs et classes sont passés en paramètres à setupTabs. 19}; 20 21// Variables d'état pour le système de popup 22let popupActive = null; 23let dernierElementFocus = null; 24let overlayElement = null; // Stocker l'élément overlay une fois récupéré 25 26// --- Fonctions du Système de Popup --- 27 28/** 29 * Ouvre une popup spécifiée par son ID et charge potentiellement du contenu. 30 * @param {string} popupId - L'ID de la popup à ouvrir. 31 * @param {HTMLElement} declencheur - L'élément HTML qui a déclenché l'ouverture de la popup. 32 */ 33async function ouvrirPopup(popupId, declencheur) { 34 if (popupActive && popupActive.id !== popupId) { 35 fermerPopup(false); // Ne pas restaurer le focus immédiatement. 36 } 37 38 const popup = document.getElementById(popupId); 39 if (!popup) { 40 console.error(`Popup avec l'ID "${popupId}" non trouvée.`); 41 return; 42 } 43 44 const contenuPopupDiv = popup.querySelector(POPUP_CONSTANTS.CONTENT_SELECTOR); 45 if (!contenuPopupDiv) { 46 console.error(`L'élément ${POPUP_CONSTANTS.CONTENT_SELECTOR} est introuvable dans la popup ID: ${popupId}`); 47 return; 48 } 49 50 // Sauvegarde le contenu HTML original de la section .popup-contenu si ce n'est pas déjà fait. 51 // Cela est utile si la popup est réutilisée sans URL externe ni source ID, 52 // ou si on veut pouvoir la restaurer à son état initial. 53 if (typeof popup.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT] === 'undefined') { 54 popup.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT] = contenuPopupDiv.innerHTML; 55 } 56 57 dernierElementFocus = document.activeElement; 58 popupActive = popup; 59 60 if (overlayElement) { 61 overlayElement.classList.add(POPUP_CONSTANTS.ACTIVE_CLASS); 62 } 63 popup.classList.add(POPUP_CONSTANTS.ACTIVE_CLASS); 64 popup.removeAttribute(POPUP_CONSTANTS.ARIA_HIDDEN_ATTR); 65 document.body.classList.add(POPUP_CONSTANTS.BODY_OPEN_CLASS); 66 67 const urlContenu = declencheur.dataset[POPUP_CONSTANTS.DATA_POPUP_URL]; 68 const sourceIdContenu = declencheur.dataset[POPUP_CONSTANTS.DATA_POPUP_SOURCE_ID]; 69 70 if (urlContenu) { 71 contenuPopupDiv.innerHTML = '<p class="popup-loading-message">Chargement du contenu...</p>'; 72 try { 73 const response = await fetch(urlContenu); 74 if (!response.ok) { 75 let errorText = response.statusText; 76 try { 77 const errorData = await response.text(); 78 if (errorData) errorText += ` - ${errorData.substring(0, 100)}`; 79 } catch (e) { /* Ignorer */ } 80 throw new Error(`Erreur HTTP ${response.status}: ${errorText}`); 81 } 82 const htmlContenu = await response.text(); 83 contenuPopupDiv.innerHTML = htmlContenu; 84 initTabs(); // Initialiser les onglets DANS le contenu chargé 85 86 // after 87 let after = declencheur.dataset['popupAfter']; 88 if(after != ''){ 89 eval(after); 90 } 91 92 } catch (error) { 93 console.error("Erreur lors du chargement du contenu externe de la popup :", error); 94 contenuPopupDiv.innerHTML = `<p class="popup-error-message">Impossible de charger le contenu externe : ${error.message}</p>`; 95 } 96 } else if (sourceIdContenu) { 97 const sourceElement = document.getElementById(sourceIdContenu); 98 if (sourceElement) { 99 contenuPopupDiv.innerHTML = sourceElement.innerHTML; 100 initTabs(); // Initialiser les onglets si le contenu local en contient 101 } else { 102 console.error(`Ãlément source avec l'ID "${sourceIdContenu}" non trouvé.`); 103 contenuPopupDiv.innerHTML = `<p class="popup-error-message">Impossible de trouver le contenu local (ID: ${sourceIdContenu}).</p>`; 104 } 105 } else { 106 // Pas d'URL externe ni de source ID, utiliser/restaurer le contenu original de la popup. 107 if (typeof popup.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT] !== 'undefined') { 108 contenuPopupDiv.innerHTML = popup.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT]; 109 // Si le contenu original pouvait contenir des onglets qui nécessitent une initialisation. 110 initTabs(); 111 } else { 112 contenuPopupDiv.innerHTML = '<p class="popup-no-content-message">Aucun contenu à afficher.</p>'; 113 } 114 } 115 116 const boutonFermer = popup.querySelector(POPUP_CONSTANTS.CLOSE_BUTTON_SELECTOR); 117 if (boutonFermer) { 118 boutonFermer.focus(); 119 } else { 120 if (!popup.hasAttribute('tabindex')) { 121 popup.setAttribute('tabindex', '-1'); 122 } 123 popup.focus(); 124 } 125} 126 127/** 128 * Ferme la popup actuellement active. 129 * @param {boolean} [restaurerFocus=true] - Indique si le focus doit être restauré. 130 */ 131function fermerPopup(restaurerFocus = true) { 132 if (popupActive) { 133 if (overlayElement) { 134 overlayElement.classList.remove(POPUP_CONSTANTS.ACTIVE_CLASS); 135 } 136 popupActive.classList.remove(POPUP_CONSTANTS.ACTIVE_CLASS); 137 popupActive.setAttribute(POPUP_CONSTANTS.ARIA_HIDDEN_ATTR, 'true'); 138 document.body.classList.remove(POPUP_CONSTANTS.BODY_OPEN_CLASS); 139 140 // Optionnel: Vider le contenu de la popup à la fermeture pour s'assurer qu'il est rechargé proprement 141 // ou restauré à son état original la prochaine fois, surtout si `initTabs` est appelé à chaque ouverture. 142 // const contenuPopupDiv = popupActive.querySelector(POPUP_CONSTANTS.CONTENT_SELECTOR); 143 // if (contenuPopupDiv && typeof popupActive.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT] !== 'undefined') { 144 // contenuPopupDiv.innerHTML = popupActive.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT]; 145 // } else if (contenuPopupDiv) { 146 // contenuPopupDiv.innerHTML = ''; // Ou un placeholder si originalContent n'existe pas 147 // } 148 149 150 if (restaurerFocus && dernierElementFocus) { 151 dernierElementFocus.focus(); 152 } 153 popupActive = null; 154 dernierElementFocus = null; 155 } 156} 157 158// --- Fonctions du Système d'Onglets --- 159 160/** 161 * Configure la logique pour un ensemble d'onglets. 162 * @param {string} tabContainerSelector - Sélecteur pour le conteneur des boutons d'onglets. 163 * @param {string} buttonSelector - Sélecteur pour les boutons d'onglets. 164 * @param {string} contentSelector - Sélecteur pour les panneaux de contenu d'onglets. 165 * @param {string} activeTabClassName - Nom de la classe CSS pour un bouton d'onglet actif. 166 * @param {string} activeContentClassName - Nom de la classe CSS pour un panneau de contenu actif. 167 * @param {boolean} [isMainTab=false] - Ajuste la recherche du parent de contenu. 168 */ 169function setupTabs(tabContainerSelector, buttonSelector, contentSelector, activeTabClassName, activeContentClassName, isMainTab = false) { 170 const tabContainers = document.querySelectorAll(tabContainerSelector); 171
172 tabContainers.forEach(container => { 173 const tabButtons = container.querySelectorAll(buttonSelector); 174 let contentParent = isMainTab ? container.closest('.guidestailles-container') : container.parentElement; 175 176 if (!contentParent) { 177 console.error("Parent pour le contenu des onglets non trouvé pour:", tabContainerSelector); 178 return; 179 } 180 const tabContents = contentParent.querySelectorAll(contentSelector); 181 182 tabButtons.forEach(button => { 183 button.addEventListener('click', () => { 184 tabButtons.forEach(btn => { 185 btn.classList.remove(activeTabClassName); 186 btn.setAttribute('aria-selected', 'false'); 187 }); 188 tabContents.forEach(content => { 189 content.classList.add(TABS_CONSTANTS.HIDDEN_CLASS); 190 content.classList.remove(activeContentClassName); 191 content.setAttribute('aria-hidden', 'true'); 192 }); 193 194 button.classList.add(activeTabClassName); 195 button.setAttribute('aria-selected', 'true'); 196 const targetContentId = button.dataset.tabTarget; 197 const targetSelector = targetContentId.startsWith('#') ? targetContentId : `#${targetContentId}`; 198 const targetContent = contentParent.querySelector(targetSelector); 199 200 if (targetContent) { 201 targetContent.classList.remove(TABS_CONSTANTS.HIDDEN_CLASS); 202 targetContent.classList.add(activeContentClassName); 203 targetContent.setAttribute('aria-hidden', 'false'); 204 } else { 205 // En production, on pourrait vouloir être moins verbeux ou logguer côté serveur si c'est critique. 206 // console.warn("Contenu cible non trouvé:", targetSelector, "dans:", contentParent); 207 } 208 }); 209 }); 210 // Optionnel: Activer le premier onglet par défaut si aucun n'est actif et s'il y a des boutons. 211 // if (tabButtons.length > 0 && !container.querySelector(`.${activeTabClassName}`)) { 212 // tabButtons[0].click(); 213 // } 214 }); 215} 216 217/** 218 * Initialise toutes les configurations d'onglets définies. 219 * Appelée typiquement après un fetch dans une popup pour activer les onglets du nouveau contenu. 220 */ 221function initTabs() { 222 setupTabs('.tabs-main', '.tab-main-button', '.tab-main-content', 'active-tab', 'active-content', true); 223 setupTabs('#textile .tabs-textile', '.tab-secondary-button', '.tab-secondary-content', 'active-tab-secondary', 'active-content-secondary'); 224 setupTabs('#velos .tabs-velos', '.tab-secondary-button', '.tab-secondary-content', 'active-tab-secondary', 'active-content-secondary'); 225 // Ajouter d'autres appels à setupTabs pour d'autres systèmes d'onglets si nécessaire. 226} 227 228 229// --- Fonctions d'Initialisation Principales --- 230 231/** 232 * Initialise le système de gestion des popups. 233 * Attache les écouteurs d'événements nécessaires. 234 */ 235function initializePopupSystem() { 236 overlayElement = document.getElementById(POPUP_CONSTANTS.OVERLAY_ID); 237 const declencheursPopup = document.querySelectorAll(POPUP_CONSTANTS.TRIGGER_SELECTOR); 238 const toutesPopups = document.querySelectorAll(POPUP_CONSTANTS.POPUP_SELECTOR); 239 240 if (!overlayElement) { 241 // En production, un avertissement dans la console peut toujours être utile pour les développeurs. 242 console.warn(`L'élément overlay avec l'ID '${POPUP_CONSTANTS.OVERLAY_ID}' est manquant. Certaines fonctionnalités pourraient être affectées.`); 243 } 244 245 declencheursPopup.forEach(bouton => { 246 const popupId = bouton.dataset.popupId; 247 if (popupId) { 248 bouton.addEventListener('click', (event) => { 249 event.preventDefault(); 250 ouvrirPopup(popupId, bouton); 251 }); 252 } else { 253 // console.warn("Un déclencheur n'a pas 'data-popup-id'.", bouton); 254 } 255 }); 256 257 toutesPopups.forEach(popup => { 258 const boutonFermer = popup.querySelector(POPUP_CONSTANTS.CLOSE_BUTTON_SELECTOR); 259 if (boutonFermer) { 260 boutonFermer.addEventListener('click', () => fermerPopup()); 261 } 262 }); 263 264 if (overlayElement) { 265 overlayElement.addEventListener('click', () => fermerPopup()); 266 } 267 268 document.addEventListener('keydown', (event) => { 269 if (event.key === 'Escape' && popupActive) { 270 fermerPopup(); 271 } 272 }); 273} 274 275/** 276 * Initialise les onglets statiques présents sur la page au chargement initial. 277 */ 278function initializeStaticTabs() { 279 // Si des onglets statiques doivent être initialisés au chargement de la page, 280 // leur initialisation se ferait ici. 281 // Actuellement, initTabs() est appelé uniquement depuis ouvrirPopup() pour le contenu dynamique. 282} 283 284 285// --- Point d'Entrée Principal --- 286// Attend que le DOM soit entièrement chargé avant d'exécuter les initialisations. 287document.addEventListener('DOMContentLoaded', () => {
288 initializePopupSystem(); 289 initializeStaticTabs(); 290}); 291 292 293 294 295 296 297 298 299// // Constantes globales pour les sélecteurs et classes, pour une meilleure maintenabilité. 300// const POPUP_CONSTANTS = { 301// OVERLAY_ID: 'globalPopupOverlay', 302// TRIGGER_SELECTOR: '[data-popup-id]', 303// POPUP_SELECTOR: '.popup-moderne', 304// CONTENT_SELECTOR: '.popup-contenu', 305// CLOSE_BUTTON_SELECTOR: '.popup-fermer', 306// ACTIVE_CLASS: 'est-actif', 307// BODY_OPEN_CLASS: 'popup-ouverte', 308// ARIA_HIDDEN_ATTR: 'aria-hidden', 309// DATA_POPUP_URL: 'popupUrl', 310// DATA_ORIGINAL_CONTENT: 'originalContent', 311// }; 312 313// const TABS_CONSTANTS = { 314// HIDDEN_CLASS: 'hidden', 315// // Les autres sélecteurs et classes sont passés en paramètres à setupTabs. 316// }; 317 318// // Variables d'état pour le système de popup 319// let popupActive = null; 320// let dernierElementFocus = null; 321// let overlayElement = null; // Stocker l'élément overlay une fois récupéré 322 323// // --- Fonctions du Système de Popup --- 324 325// /** 326// * Ouvre une popup spécifiée par son ID et charge potentiellement du contenu externe. 327// * @param {string} popupId - L'ID de la popup à ouvrir. 328// * @param {HTMLElement} declencheur - L'élément HTML qui a déclenché l'ouverture de la popup. 329// */ 330// async function ouvrirPopup(popupId, declencheur) { 331// if (popupActive && popupActive.id !== popupId) { 332// fermerPopup(false); // Ne pas restaurer le focus immédiatement. 333// } 334 335// const popup = document.getElementById(popupId); 336// if (!popup) { 337// console.error(`Popup avec l'ID "${popupId}" non trouvée.`); 338// return; 339// } 340 341// const contenuPopupDiv = popup.querySelector(POPUP_CONSTANTS.CONTENT_SELECTOR); 342// if (!contenuPopupDiv) { 343// console.error(`L'élément ${POPUP_CONSTANTS.CONTENT_SELECTOR} est introuvable dans la popup ID: ${popupId}`); 344// return; 345// } 346 347// if (typeof popup.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT] === 'undefined') { 348// popup.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT] = contenuPopupDiv.innerHTML; 349// } 350 351// dernierElementFocus = document.activeElement; 352// popupActive = popup; 353 354// if (overlayElement) { 355// overlayElement.classList.add(POPUP_CONSTANTS.ACTIVE_CLASS); 356// } 357// popup.classList.add(POPUP_CONSTANTS.ACTIVE_CLASS); 358// popup.removeAttribute(POPUP_CONSTANTS.ARIA_HIDDEN_ATTR); 359// document.body.classList.add(POPUP_CONSTANTS.BODY_OPEN_CLASS); 360 361// const urlContenu = declencheur.dataset[POPUP_CONSTANTS.DATA_POPUP_URL]; 362 363// if (urlContenu) { 364// contenuPopupDiv.innerHTML = '<p class="popup-loading-message">Chargement du contenu...</p>'; // Utiliser une classe pour le style 365// try { 366// const response = await fetch(urlContenu); 367// if (!response.ok) { 368// let errorText = response.statusText; 369// try { 370// const errorData = await response.text(); 371// if (errorData) errorText += ` - ${errorData.substring(0, 100)}`; 372// } catch (e) { /* Ignorer */ } 373// throw new Error(`Erreur HTTP ${response.status}: ${errorText}`); 374// } 375// const htmlContenu = await response.text(); 376// contenuPopupDiv.innerHTML = htmlContenu; 377// initTabs(); // Initialiser les onglets DANS le contenu chargé 378// } catch (error) { 379// console.error("Erreur lors du chargement du contenu de la popup :", error); 380// contenuPopupDiv.innerHTML = `<p class="popup-error-message">Impossible de charger le contenu : ${error.message}</p>`; // Classe pour style 381// } 382// } else { 383// if (typeof popup.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT] !== 'undefined') { 384// contenuPopupDiv.innerHTML = popup.dataset[POPUP_CONSTANTS.DATA_ORIGINAL_CONTENT]; 385// } else { 386// contenuPopupDiv.innerHTML = '<p class="popup-no-content-message">Aucun contenu à afficher.</p>'; // Classe pour style 387// } 388// } 389 390// const boutonFermer = popup.querySelector(POPUP_CONSTANTS.CLOSE_BUTTON_SELECTOR); 391// if (boutonFermer) { 392// boutonFermer.focus(); 393// } else { 394// if (!popup.hasAttribute('tabindex')) { 395// popup.setAttribute('tabindex', '-1'); 396// } 397// popup.focus(); 398// } 399// } 400 401// /** 402// * Ferme la popup actuellement active. 403// * @param {boolean} [restaurerFocus=true] - Indique si le focus doit être restauré. 404// */ 405// function fermerPopup(restaurerFocus = true) { 406// if (popupActive) { 407// if (overlayElement) { 408// overlayElement.classList.remove(POPUP_CONSTANTS.ACTIVE_CLASS); 409// } 410// popupActive.classList.remove(POPUP_CONSTANTS.ACTIVE_CLASS); 411// popupActive.setAttribute(POPUP_CONSTANTS.ARIA_HIDDEN_ATTR, 'true'); 412// document.body.classList.remove(POPUP_CONSTANTS.BODY_OPEN_CLASS); 413 414// if (restaurerFocus && dernierElementFocus) { 415// dernierElementFocus.focus(); 416// } 417// popupActive = null; 418// dernierElementFocus = null; 419// } 420// } 421 422// // --- Fonctions du Système d'Onglets --- 423 424// /** 425// * Configure la logique pour un ensemble d'onglets. 426// * @param {string} tabContainerSelector - Sélecteur pour le conteneur des boutons d'onglets. 427// * @param {string} buttonSelector - Sélecteur pour les boutons d'onglets. 428// * @param {string} contentSelector - Sélecteur pour les panneaux de contenu d'onglets. 429// * @param {string} activeTabClassName - Nom de la classe CSS pour un bouton d'onglet actif. 430// * @param {string} activeContentClassName - Nom de la classe CSS pour un panneau de contenu actif. 431// * @param {boolean} [isMainTab=false] - Ajuste la recherche du parent de contenu. 432// */ 433// function setupTabs(tabContainerSelector, buttonSelector, contentSelector, activeTabClassName, activeContentClassName, isMainTab = false) { 434// const tabContainers = document.querySelectorAll(tabContainerSelector); 435
436// tabContainers.forEach(container => { 437// const tabButtons = container.querySelectorAll(buttonSelector); 438// let contentParent = isMainTab ? container.closest('.guidestailles-container') : container.parentElement; 439 440// if (!contentParent) { 441// console.error("Parent pour le contenu des onglets non trouvé pour:", tabContainerSelector); 442// return; 443// } 444// const tabContents = contentParent.querySelectorAll(contentSelector); 445 446// tabButtons.forEach(button => { 447// button.addEventListener('click', () => { 448// tabButtons.forEach(btn => { 449// btn.classList.remove(activeTabClassName); 450// btn.setAttribute('aria-selected', 'false'); 451// }); 452// tabContents.forEach(content => { 453// content.classList.add(TABS_CONSTANTS.HIDDEN_CLASS); 454// content.classList.remove(activeContentClassName); 455// content.setAttribute('aria-hidden', 'true'); 456// }); 457 458// button.classList.add(activeTabClassName); 459// button.setAttribute('aria-selected', 'true'); 460// const targetContentId = button.dataset.tabTarget; 461// const targetSelector = targetContentId.startsWith('#') ? targetContentId : `#${targetContentId}`; 462// const targetContent = contentParent.querySelector(targetSelector); 463 464// if (targetContent) { 465// targetContent.classList.remove(TABS_CONSTANTS.HIDDEN_CLASS); 466// targetContent.classList.add(activeContentClassName); 467// targetContent.setAttribute('aria-hidden', 'false'); 468// } else { 469// // En production, on pourrait vouloir être moins verbeux ou logguer côté serveur si c'est critique. 470// // console.warn("Contenu cible non trouvé:", targetSelector, "dans:", contentParent); 471// } 472// }); 473// }); 474// // Optionnel: Activer le premier onglet par défaut si aucun n'est actif et s'il y a des boutons. 475// // if (tabButtons.length > 0 && !container.querySelector(`.${activeTabClassName}`)) { 476// // tabButtons[0].click(); 477// // } 478// }); 479// } 480 481// /** 482// * Initialise toutes les configurations d'onglets définies. 483// * Appelée typiquement après un fetch dans une popup pour activer les onglets du nouveau contenu. 484// */ 485// function initTabs() { 486// setupTabs('.tabs-main', '.tab-main-button', '.tab-main-content', 'active-tab', 'active-content', true); 487// setupTabs('#textile .tabs-textile', '.tab-secondary-button', '.tab-secondary-content', 'active-tab-secondary', 'active-content-secondary'); 488// setupTabs('#velos .tabs-velos', '.tab-secondary-button', '.tab-secondary-content', 'active-tab-secondary', 'active-content-secondary'); 489// // Ajouter d'autres appels à setupTabs pour d'autres systèmes d'onglets si nécessaire. 490// } 491 492 493// // --- Fonctions d'Initialisation Principales --- 494 495// /** 496// * Initialise le système de gestion des popups. 497// * Attache les écouteurs d'événements nécessaires. 498// */ 499// function initializePopupSystem() { 500// overlayElement = document.getElementById(POPUP_CONSTANTS.OVERLAY_ID); 501// const declencheursPopup = document.querySelectorAll(POPUP_CONSTANTS.TRIGGER_SELECTOR); 502// const toutesPopups = document.querySelectorAll(POPUP_CONSTANTS.POPUP_SELECTOR); 503 504// if (!overlayElement) { 505// // En production, un avertissement dans la console peut toujours être utile pour les développeurs. 506// console.warn(`L'élément overlay avec l'ID '${POPUP_CONSTANTS.OVERLAY_ID}' est manquant. Certaines fonctionnalités pourraient être affectées.`); 507// } 508 509// declencheursPopup.forEach(bouton => { 510// const popupId = bouton.dataset.popupId; 511// if (popupId) { 512// bouton.addEventListener('click', (event) => { 513// event.preventDefault(); 514// ouvrirPopup(popupId, bouton); 515// }); 516// } else { 517// // console.warn("Un déclencheur n'a pas 'data-popup-id'.", bouton); 518// } 519// }); 520 521// toutesPopups.forEach(popup => { 522// const boutonFermer = popup.querySelector(POPUP_CONSTANTS.CLOSE_BUTTON_SELECTOR); 523// if (boutonFermer) { 524// boutonFermer.addEventListener('click', () => fermerPopup()); 525// } 526// }); 527 528// if (overlayElement) { 529// overlayElement.addEventListener('click', () => fermerPopup()); 530// } 531 532// document.addEventListener('keydown', (event) => { 533// if (event.key === 'Escape' && popupActive) { 534// fermerPopup(); 535// } 536// }); 537// } 538 539// /** 540// * Initialise les onglets statiques présents sur la page au chargement initial. 541// */ 542// function initializeStaticTabs() { 543// // Si des onglets statiques doivent être initialisés au chargement de la page, 544// // leur initialisation se ferait ici. 545// // Actuellement, initTabs() est appelé uniquement depuis ouvrirPopup() pour le contenu dynamique. 546// } 547 548 549// // --- Point d'Entrée Principal --- 550// // Attend que le DOM soit entièrement chargé avant d'exécuter les initialisations. 551// document.addEventListener('DOMContentLoaded', () => {
552// initializePopupSystem(); 553// initializeStaticTabs(); 554// });
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.