1/*========================================================================== 22. Extraction des paramétres d'URL 3========================================================================== */ 4function getVar(key, default_) { 5 if (default_ == null) default_ = 0; 6 key = key.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); 7 var regex = new RegExp("[\\?&#]" + key + "=([^&#]*)"); 8 var qs = regex.exec(window.location.href); 9 if (qs == null) return default_; 10 else return qs[1]; 11} 12 13class AdfLightbox { 14 constructor(el) { 15 this.el = el; 16 this.ogImgEl = el.querySelector("img"); 17 this.lightBoxEl; 18 this.buttonEl; 19 } 20 21 init() { 22 this.el.addEventListener("click", (e) => { 23 e.preventDefault(); 24 25 this.openLightbox(); 26 }); 27 28 return this; 29 } 30 31 openLightbox() { 32 if (document.querySelector(".lightbox-img-opened")) { 33 return; 34 } 35 36 const imgName = this.ogImgEl.getAttribute("alt") ? `${this.ogImgEl.getAttribute("alt")}` : "l'image"; 37 38 this.lightBoxEl = document.createElement("div"); 39 this.lightBoxEl.classList.add("lightbox-img-opened"); 40 41 this.lightBoxEl.innerHTML = `<img src="${this.el.href}">`; 42 43 this.lightBoxEl.setAttribute("role", "dialog"); 44 this.lightBoxEl.setAttribute("aria-label", imgName); 45 this.lightBoxEl.setAttribute("aria-modal", "true"); 46 47 this.buttonEl = document.createElement("button"); 48 this.buttonEl.setAttribute("type", "button"); 49 this.buttonEl.classList.add("lightbox-img-opened__button"); 50 this.buttonEl.innerHTML = `Fermer <span class="sr-only">${imgName}</span>`; 51 this.lightBoxEl.insertAdjacentElement("beforeend", this.buttonEl); 52 53 document.body.insertAdjacentElement("beforeend", this.lightBoxEl); 54 55 this.buttonEl.addEventListener("click", () => { 56 this.closeLightbox(); 57 }); 58 59 this.buttonEl.focus(); 60 61 document.body.style = "margin: 0; height: 100%; overflow: hidden;"; 62 } 63 64 closeLightbox() { 65 this.buttonEl.remove(); 66 this.buttonEl = undefined; 67 68 this.lightBoxEl.remove(); 69 this.lightBoxEl = undefined; 70 71 this.el.focus(); 72 73 document.body.style = ""; 74 } 75} 76 77// Lightbox Image 78document.addEventListener("DOMContentLoaded", function () { 79 const lightboxImgEls = document.querySelectorAll(".cc .lightbox-img"); 80 81 lightboxImgEls.forEach((el) => { 82 new AdfLightbox(el).init(); 83 }); 84 85 // Voir plus/moins 86 var pathname = window.location.pathname; 87 var langue = pathname.substr(1, 2); 88 89 var showChar = 200; 90 var ellipsestext = "..."; 91 92 var moretext, lesstext; 93 94 switch (langue) { 95 case "de": 96 moretext = "Mehr sehen"; 97 lesstext = "Weniger sehen"; 98 break; 99 case "en": 100 moretext = "Read more"; 101 lesstext = "Read less"; 102 break; 103 default: 104 moretext = "Voir plus"; 105 lesstext = "Voir moins"; 106 break; 107 } 108 109// Parcourir tous les éléments "div" dans "div.readmore div" 110document.querySelectorAll("div.readmore div").forEach(function (div) { 111 var content = div.innerHTML; 112 var contentText = div.textContent; 113 114 if (content.length > showChar) { 115 var c = content.slice(0, showChar); 116 var h = content.slice(showChar); 117 118 var html = c + '<span class="moreellipses">' + ellipsestext + ' </span>' + 119 '<span class="morecontent" style="display: none;">' + h + 120 '<a href="#" class="morelink more">' + moretext + '</a></span>'; 121 div.innerHTML = html; 122 } 123}); 124 125// Gestionnaire d'événement pour les liens "morelink" 126document.addEventListener("click", function (event) { 127 var target = event.target; 128 129 if (target.classList.contains("morelink")) { 130 event.preventDefault(); 131 132 if (target.classList.contains("less")) { 133 target.classList.remove("less"); 134 target.textContent = moretext; 135 } else { 136 target.classList.add("less"); 137 target.textContent = lesstext; 138 } 139 140 var ellipses = target.parentElement.previousElementSibling; 141 var moreContent = target.parentElement; 142 143 ellipses.style.display = ellipses.style.display === "none" ? "" : "none"; 144 moreContent.style.display = moreContent.style.display === "none" ? "" : "none"; 145 } 146}); 147 148 149 150 // Scroll to top 151/* function scroll_to_top(div) { 152 $(div).click(function () { 153 $("html,body").animate({ scrollTop: 0 }, "slow"); 154 }); 155 $(window).scroll(function () { 156 if ($(window).scrollTop() < 500) { 157 $(div).fadeOut(); 158 } else { 159 $(div).fadeIn(); 160 } 161 }); 162 } 163 scroll_to_top("#scroll_to_top"); 164*/ 165 166function scrollToTop(div) { 167 const targetElement = document.querySelector(div); 168 169 if (!targetElement) { 170 console.info(`Element not found: ${div} - Skipping scrollToTop setup.`); 171 return; 172 } 173 174 targetElement.addEventListener("click", function () { 175 window.scrollTo({ top: 0, behavior: "smooth" }); 176 });
177 178 window.addEventListener("scroll", function () { 179 targetElement.style.display = window.scrollY < 500 ? "none" : "block"; 180 }); 181} 182 183 scrollToTop("#scroll_to_top"); 184 185 186 187 188 // Bannières 189 document.querySelectorAll(".custom-banner").forEach((banner) => { 190 let primColor = banner.getAttribute("data-color-prim"); 191 let secColor = banner.getAttribute("data-color-sec"); 192 let txtColor = banner.getAttribute("data-color-txt"); 193 let txtBtn = banner.getAttribute("data-color-btn"); 194 let bgImg = banner.getAttribute("data-image"); 195 196 if (primColor) { 197 banner.style.backgroundColor = primColor; 198 } 199 200 if (secColor) { 201 banner.querySelectorAll(".bubble, .actions .button").forEach(el => { 202 el.style.background = secColor; 203 }); 204 205 banner.querySelectorAll(".actions .button").forEach(button => { 206 button.addEventListener("mouseover", () => button.style.opacity = "0.8"); 207 button.addEventListener("mouseout", () => button.style.opacity = "1"); 208 button.addEventListener("focusin", () => button.style.opacity = "0.7"); 209 button.addEventListener("focusout", () => button.style.opacity = "1"); 210 }); 211 } 212 213 if (txtColor) { 214 banner.style.color = txtColor; 215 banner.querySelectorAll("h2, h3, p, li").forEach(el => { 216 el.style.color = txtColor; 217 }); 218 banner.querySelectorAll(".line").forEach(el => { 219 el.style.background = txtColor; 220 el.style.opacity = "0.6"; 221 }); 222 } 223 224 if (txtBtn) { 225 banner.querySelectorAll(".actions a").forEach(el => { 226 el.style.color = txtBtn; 227 }); 228 } 229 230 if (bgImg) { 231 banner.style.backgroundImage = `url(/partage/fr/${bgImg}.jpg)`; 232 } 233 }); 234 235 236}); 237 238// Gestion du menu sticky 239let menuTop = 0; 240document.addEventListener("DOMContentLoaded", function () { 241 // Valeur de scroll 242 if (document.querySelector(".ei_header") != null) {menuTop = document.querySelector(".ei_header").offsetHeight} 243 244 let sectionIndex = -1; 245 246 if (document.querySelector("aside.sticky nav")) { 247 // Décomptage des sections présentes dans la page 248 let sections = document.querySelectorAll(".cc article section"); 249 let menuElements = document.querySelectorAll("aside.sticky nav ul li"); 250 251 function addSubMenu(){ 252 if (document.querySelectorAll('.sous-menu')){ 253 document.querySelectorAll('.sous-menu').forEach(function(item){ 254 item.remove() 255 }) 256 } 257 sections.forEach(function(section){ 258 if (!section.getAttribute('data-sousmenu')) return; 259 let sectionH2Id = section.getAttribute('aria-labelledby'); 260 const menuItem = Array.from(menuElements).find(li => { 261 const anchor = li.querySelector('a'); 262 return anchor && anchor.getAttribute('href').includes('#' + sectionH2Id); 263 }); 264 265 let sectionsSousMenus = section.querySelectorAll('h3'); 266 if (sectionsSousMenus.length > 0){ 267 const sousMenuUl = document.createElement('ul'); 268 sousMenuUl.classList.add('sous-menu'); 269 270 sectionsSousMenus.forEach(function(sousmenu, index){ 271 if (!sousmenu.id || sousmenu.id === ""){sousmenu.id = "sousmenu-" + index} 272 273 const sousMenuItem = document.createElement('li'); 274 const sousMenuLink = document.createElement('a'); 275 sousMenuLink.href = '#' + sousmenu.id; 276 sousMenuLink.textContent = sousmenu.textContent; 277 278 sousMenuItem.appendChild(sousMenuLink); 279 sousMenuUl.appendChild(sousMenuItem); 280 }); 281 282 if (menuItem) {menuItem.appendChild(sousMenuUl)} 283 } 284 }); 285 } 286 // Fonction pour le Aria 287 function removeAriaCurrent() { 288 let menuElementCurrent = document.querySelector('aside.sticky nav ul li strong a[aria-current="true"]'); 289 290 if (menuElementCurrent) { 291 menuElementCurrent.removeAttribute("aria-current"); 292 let menuElementCurrentContainer = menuElementCurrent.parentElement.parentElement; 293 menuElementCurrentContainer.appendChild(menuElementCurrent); 294 let menuElementCurrentStrongToDelete = menuElementCurrentContainer.querySelector("strong"); 295 menuElementCurrentContainer.removeChild(menuElementCurrentStrongToDelete); 296 } 297 addSubMenu(); 298 } 299 // Fonction update pour les sous-menus
300 function updateActiveSubmenuItem(){ 301 document.querySelector("html").removeAttribute("data-submenu"); 302 const activeSection = sections[sectionIndex]; 303 if (!activeSection || !activeSection.getAttribute('data-sousmenu')) { 304 return; 305 } 306 const sectionH3s= activeSection.querySelectorAll('h3'); 307 if (sectionH3s.length === 0) return; 308 let scrollTop = window.pageYOffset || document.documentElement.scrollTop; 309 let menuBottom = scrollTop + menuTop; 310 document.querySelectorAll('.sous-menu a[aria-current="true"]').forEach(item => { 311 item.removeAttribute("aria-current"); 312 if (item.parentElement.tagName === "STRONG") { 313 let parentLi = item.parentElement.parentElement; 314 parentLi.appendChild(item); 315 parentLi.removeChild(item.parentElement); 316 } 317 }); 318 319 let activeH3Index = -1; 320 for (let i = 0; i < sectionH3s.length; i++) { 321 let h3Top = scrollTop + sectionH3s[i].getBoundingClientRect().top; 322 let nextH3Top = (i < sectionH3s.length - 1) ? 323 scrollTop + sectionH3s[i + 1].getBoundingClientRect().top : 324 Infinity; 325 326 // Si nous sommes entre ce h3 et le suivant, ou si c'est le dernier h3 327 if (h3Top - 1 <= menuBottom && menuBottom < nextH3Top - 1) { 328 activeH3Index = i; 329 break; 330 } 331 } 332 // Si nous avons trouvé un h3 actif 333 if (activeH3Index !== -1) { 334 // Trouver l'élément de sous-menu correspondant 335 const activeH3 = sectionH3s[activeH3Index]; 336 document.querySelector("html").setAttribute("data-submenu", activeH3Index); 337 const sectionH2Id = activeSection.getAttribute('aria-labelledby'); 338 339 // Trouver le menuItem parent 340 const menuItem = Array.from(menuElements).find(li => { 341 const anchor = li.querySelector('a'); 342 return anchor && anchor.getAttribute('href').includes('#' + sectionH2Id); 343 }); 344 345 if (menuItem) { 346 const sousMenu = menuItem.querySelector('.sous-menu'); 347 if (sousMenu) { 348 // Trouver le lien du sous-menu qui pointe vers ce h3 349 const sousMenuLink = Array.from(sousMenu.querySelectorAll('a')).find(a => 350 a.getAttribute('href') === '#' + activeH3.id 351 ); 352 353 if (sousMenuLink) { 354 // Mettre en évidence ce lien 355 sousMenuLink.setAttribute("aria-current", "true"); 356 let strongWrapper = document.createElement("strong"); 357 sousMenuLink.parentElement.insertBefore(strongWrapper, sousMenuLink); 358 strongWrapper.appendChild(sousMenuLink); 359 } 360 } 361 } 362 } 363 } 364 365 addSubMenu(); 366 367 window.addEventListener("scroll", function () { 368 let scrollTop = window.pageYOffset || document.documentElement.scrollTop; 369 let menuBottom = scrollTop + menuTop; 370 let pageHeight = document.body.scrollHeight; 371 372 // Annuler la function si on est pas encore entré dans la partie avec les sections 373 if (menuBottom < scrollTop + sections[0].getBoundingClientRect().top - 1) { 374 removeAriaCurrent(); 375 return; 376 } 377 378 // Si on est en bas de page, sélection de la dernière entrée de menu 379 if (scrollTop == pageHeight - window.innerHeight) {sectionIndex = sections.length - 1} 380 381 // Sinon on la définit: 382 else { 383 // Verif pour chaque section 384 for (let currentSectionIndex = 0; currentSectionIndex < sections.length; currentSectionIndex++) { 385 let currentSectionEl = sections[currentSectionIndex]; 386 let nextSectionEl = sections[currentSectionIndex + 1]; 387 388 // Récupération des valeurs Y en pixels des deux éléments par rapport au haut de page 389 let currentSectionElTop = scrollTop + currentSectionEl.getBoundingClientRect().top; 390 let nextSectionElTop = scrollTop + (nextSectionEl ? nextSectionEl.getBoundingClientRect().top : undefined); 391 392 // Si la valeur de scroll est comprise entre le haut de la section vérifier et celle qui suit (si elle existe), c'est cette valeur qui est retenue 393 if (currentSectionElTop - 1 <= menuBottom && (!nextSectionElTop || menuBottom < nextSectionElTop - 1)) { 394 sectionIndex = currentSectionIndex; 395 396 break; 397 } 398 } 399 } 400 401 // Update de l'attribut data-section 402 document.querySelector("html").setAttribute("data-section", sectionIndex); 403 404 // Reset de la valeur aria current définissant quelle entrée de menu à highlight dans le side menu 405 removeAriaCurrent(); 406 407 let menuElementToSetCurrent = menuElements[sectionIndex]; 408 409 if (menuElementToSetCurrent && !menuElementToSetCurrent.querySelector('a[aria-current="true"]')) { 410 let menuElementNewCurrent = menuElementToSetCurrent.querySelector("a"); 411 menuElementNewCurrent.setAttribute("aria-current", "true"); 412 let strongWrapper = document.createElement("strong"); 413 menuElementToSetCurrent.insertBefore(strongWrapper, menuElementNewCurrent); 414 strongWrapper.appendChild(menuElementNewCurrent); 415 } 416
417 updateActiveSubmenuItem(); 418 419 }); 420 } 421}); 422 423document.addEventListener("DOMContentLoaded", function () { 424 // Sticky IE 425 // Gestion du sticky menu dans IE 426 if (browserIsInternetExplorer()) { 427 // Recherche de l'élément de menu sticky 428 var stickyMenu = document.querySelector("aside.sticky nav"); 429 430 // Si on en trouve un... 431 if (stickyMenu) { 432 var stickyMenuTopValue = parseInt(window.getComputedStyle(stickyMenu).top); 433 (stickyMenuInitialY = stickyMenu.parentElement.offsetTop), (scrollValue = 0), (scrolledPastMenuTop = false), (scrolledPastBodyBottom = false), (parentContainer = stickyMenu.parentElement.parentElement), (parentContainerInitialHeight = stickyMenu.parentElement.parentElement.offsetHeight), (headerHeight = document.querySelector("header").offsetHeight); 434 435 // A chaque scroll 436 window.addEventListener("scroll", function () { 437 // Récupération de la valeur de scroll 438 scrollValue = document.documentElement.scrollTop; 439 440 // Si on scrolle au delà du haut du menu sticky 441 scrolledPastMenuTop = scrollValue > stickyMenuInitialY - stickyMenuTopValue; 442 // Le bas du menu dépasse le bas du main? 443 scrolledPastBodyBottom = scrollValue + stickyMenuTopValue + stickyMenu.offsetHeight + parseInt(window.getComputedStyle(stickyMenu).paddingBottom) > parentContainer.offsetTop + parentContainer.offsetHeight - parseInt(window.getComputedStyle(parentContainer).paddingBottom); 444 445 // Si ces deux conditions sont réunies; on passe le menu en position fixed. 446 if (scrolledPastMenuTop) { 447 if (!scrolledPastBodyBottom) { 448 stickyMenu.style.position = "fixed"; 449 stickyMenu.style.marginTop = "0px"; 450 } else { 451 stickyMenu.style.position = "static"; 452 stickyMenu.style.marginTop = parentContainer.offsetHeight - (stickyMenuTopValue + stickyMenu.offsetHeight) + "px"; 453 } 454 } 455 // Si on retourne en haut de page, le menu redeviens statique 456 else { 457 stickyMenu.style.position = "static"; 458 stickyMenu.style.marginTop = "0px"; 459 } 460 }); 461 462 // Au resize de la fenêtre, redimensionnement du menu pour qu'il prenne le bon espace 463 window.addEventListener("resize", function () { 464 stickyMenu.style.width = stickyMenu.parentNode.offsetWidth + "px"; 465 }); 466 467 // Init resize 468 var menuInitialResizeEvent = new CustomEvent("resize"); 469 window.dispatchEvent(menuInitialResizeEvent); 470 } 471 } 472}); 473 474/*========================================================================== 4751. Gestion des cookie et du LocalStorage 476========================================================================== */ 477 478var pathCookiesRgdp = "/fr/"; 479// var pathCookiesRgdp="/"+window.location.pathname.substr(1, 2)+"/"; 480 481function setCookie(name, value, days, path) { 482 if (path == undefined) path = "/"; 483 var expires; 484 if (days) { 485 var date = new Date(); 486 date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); 487 expires = "; expires=" + date.toGMTString(); 488 } else expires = ""; 489 document.cookie = name + "=" + value + expires + "; path=" + path; 490} 491// ex : creation / ecriture cookie pour 1 journee : setCookie('myCookie', 'myValue', 1); 492 493function getCookie(name) { 494 var nameEQ = name + "="; 495 var ca = document.cookie.split(";"); 496 for (var i = 0; i < ca.length; i++) { 497 var c = ca[i]; 498 while (c.charAt(0) == " ") c = c.substring(1, c.length); 499 if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); 500 } 501 return null; 502} 503// lecture cookie : getCookie('myCookie'); 504 505function deleteCookie(name) { 506 document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC"; 507} 508//delete cookie : deleteCookie('myCookie'); 509 510function deleteCookie(name) { 511 setCookie(name, "", -1); 512} 513// RAZ cookies : deleteCookie('myCookie'); 514 515function setLocalData(name, value, days) { 516 // Le navigateur supporte le localStorage 517 if (typeof window.localStorage == "undefined") setCookie(name, value, days); 518 else localStorage.setItem(name, value); 519} 520 521function getLocalData(name) { 522 // Le navigateur supporte le localStorage 523 var resultat; 524 if (typeof window.localStorage == "undefined") resultat = getCookie(name); 525 else resultat = localStorage.getItem(name); 526 527 return resultat; 528} 529 530function removeLocalData(name) { 531 // Le navigateur supporte le localStorage 532 if (typeof window.localStorage == "undefined") deleteCookie(name); 533 else removeItem(name); 534} 535 536// pour retro-compatibilit� anciens sites ---------------- 537function ReadCookie(cookieName) { 538 // Lire les cookies du site 539 var theCookie = "" + document.cookie; 540 var ind = theCookie.indexOf(cookieName); 541 if (ind == -1 || cookieName == "") return ""; 542 var ind1 = theCookie.indexOf(";", ind); 543 if (ind1 == -1) ind1 = theCookie.length; 544 return unescape(theCookie.substring(ind + cookieName.length + 1, ind1)); 545} 546//-------------------------------------------------------- 547// pour protection-des-donnees.html 548 549//Cette fonction retourne la date d'expiration du cookie de consentement 550function getCookieExpireDate() { 551 var cookieTimeout = 34214400000; // Le nombre de millisecondes que font 13 mois 552 var date = new Date(); 553 date.setTime(date.getTime() + cookieTimeout); 554 var expires = "; expires=" + date.toGMTString(); 555 return expires; 556} 557 558// Retourne true si le navigateur utilisé est IE. 559var browserIsInternetExplorer = function () { 560 var ua = window.navigator.userAgent; 561 var msie = ua.indexOf("MSIE "); 562 563 return msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./); 564}; 565 566/* =================== Tableaux responsives ============================ */ 567function responsiveEntries(table) { 568 cols = table.find("thead th:not([colspan])"); 569 linesTH = table.find("tbody th"); 570 linesTD = table.find("tbody td"); 571 linesTDwidthColspan = []; 572 for (var c = 0; c < linesTD.length; c++) { 573 linesTDwidthColspan.push(linesTD[c]); 574 if (linesTD[c].colSpan > 1) { 575 colspan = linesTD[c].colSpan - 1; 576 for (var cs = 0; cs < colspan; cs++) { 577 linesTDwidthColspan.push(linesTD[c]); 578 } 579 } 580 } 581 newTables = ""; 582 for (var t = 0; t < cols.length; t++) { 583 newTables += '<table class="one-entry border RWD-M-alt">'; 584 newTables += "<caption>" + cols[t].innerHTML + "</caption>"; 585 newTables += "<tbody>"; 586 for (var l = 0; l < linesTH.length; l++) { 587 newTables += "<tr>"; 588 newTables += '<th scope="row">' + linesTH[l].innerHTML + "</th>"; 589 590 if (linesTDwidthColspan[t + l * cols.length]) { 591 newTables += "<td>" + linesTDwidthColspan[t + l * cols.length].innerHTML + "</td>"; 592 } 593 594 newTables += "</tr>"; 595 } 596 newTables += "</tbody>"; 597 newTables += "</table>"; 598 } 599 // table.hide(); 600 table.after(newTables); 601} 602 603function responsiveLists(table) { 604 lines = table.find("tbody tr"); 605 linesTH = table.find("thead th"); 606 linesTD = table.find("tbody td"); 607 colspan = 1; 608 colspanVal = ""; 609 colspanCount = 0; 610 newTables = ""; 611 for (var t = 0; t < lines.length; t++) { 612 if (linesTD[t * linesTH.length - colspanCount].className == "group") { 613 newTables += '<h3 class="RWD-M-alt">' + linesTD[t * linesTH.length - colspanCount].innerHTML + "</h3>"; 614 colspanCount += linesTH.length - 1; 615 } else { 616 if (lines[t].id) { 617 newTables += '<table class="one-entry border RWD-M-alt" id="ALT-' + lines[t].id + '">'; 618 } else { 619 newTables += '<table class="one-entry border RWD-M-alt">'; 620 } 621 newTables += "<caption>" + linesTD[t * linesTH.length - colspanCount].innerHTML + "</caption>"; 622 newTables += "<tbody>"; 623 for (var l = 1; l < linesTH.length; l++) { 624 newTables += "<tr>"; 625 newTables += '<th scope="row">' + linesTH[l].innerHTML + "</th>"; 626 if (colspan > 1) { 627 newTables += "<td>" + colspanVal + "</td>"; 628 colspan--; 629 } else { 630 if (linesTD[l + t * linesTH.length - colspanCount]) { 631 newTables += "<td>" + linesTD[l + t * linesTH.length - colspanCount].innerHTML.replace("#", "#ALT-") + "</td>"; 632 if (linesTD[l + t * linesTH.length - colspanCount].colSpan > 1) { 633 colspan = linesTD[l + t * linesTH.length - colspanCount].colSpan; 634 colspanVal = linesTD[l + t * linesTH.length - colspanCount].innerHTML.replace("#", "#ALT-"); 635 colspanCount += colspan - 1; 636 } 637 } 638 } 639 newTables += "</tr>"; 640 } 641 newTables += "</tbody>"; 642 newTables += "</table>"; 643 } 644 } 645 table.after(newTables); 646} 647 648/* 649function initResponsiveTable(e) { 650 $("table.two-entry.RWD-M").each(function () { 651 responsiveEntries($(this)); 652 }); 653 $("table.list.RWD-M").each(function () { 654 responsiveLists($(this)); 655 }); 656} 657$(document).ready(initResponsiveTable); 658*/ 659 660function initResponsiveTable() { 661 document.querySelectorAll("table.two-entry.RWD-M").forEach(function (table) { 662 responsiveEntries(table); 663 });
664 665 document.querySelectorAll("table.list.RWD-M").forEach(function (table) { 666 responsiveLists(table); 667 }); 668} 669 670document.addEventListener("DOMContentLoaded", initResponsiveTable); 671 672 673 674 675/*========================================================================== 6763. Etendre la zone de clic 677========================================================================== */ 678 679function initClicks() { 680 document.querySelectorAll("[data-click='yes']").forEach(function (element) { 681 let lien; 682 683 // Rechercher un élément <a> sans la classe "label" 684 element.querySelectorAll("a").forEach(function (el) { 685 if (!el.classList.contains("label")) { 686 lien = el; 687 return false; // on quitte le foreach 688 } 689 }); 690 691 if (typeof lien === "object") { 692 element.classList.add("clickable"); 693 694 // Supprime tous les écouteurs de clic précédents pour éviter les doublons 695 const clone = element.cloneNode(true); 696 element.parentNode.replaceChild(clone, element); 697 698 clone.addEventListener("click", function (e) { 699 lien.click(); 700 e.stopPropagation(); 701 }); 702 703 lien.addEventListener("click", function (e) { 704 console.log(this.getAttribute("href")); 705 e.stopPropagation(); 706 }); 707 } 708 }); 709} 710 711document.addEventListener("DOMContentLoaded", initClicks); 712 713/* 714function initLightboxClicks(e) { 715 $("[data-lightbox-click='yes']").each(function () { 716 var lien; 717 $(this) 718 .find("a") 719 .each(function (index, el) { 720 if (!$(this).hasClass("label")) { 721 lien = $(this); 722 return false; //on quite le each 723 } 724 }); 725 726 if (typeof lien == "object") { 727 $(this).addClass("clickable"); 728 $(this).unbind("click"); 729 $(this).click(function (e) { 730 lien.get(0).click(); 731 //e.stopPropagation(); 732 }); 733 } 734 735 $(".clickable .lightbox").click(function (e) { 736 //e.preventDefault(); 737 }); 738 }); 739} 740$(document).ready(initLightboxClicks); 741*/ 742/*========================================================================== 7434. lightbox 744========================================================================== */ 745 746 747 748 749// Fonction utilitaire pour créer la lightbox 750function createLightbox({ opener, href, title, width, height, type }) { 751 const page = document.querySelector("#lightbox_page"); 752 const lightbox_class = href.slice(-3) === "pdf" ? ' class="pdf"' : ""; 753 let lightbox_code; 754 755 // Construction du code HTML de la lightbox 756 if (width && height) { 757 lightbox_code = `<dialog id="lightbox"${lightbox_class} role="dialog" aria-labelledby="lightbox_title" style="width:${width};height:${height};"><div role="document">`; 758 } else if (!width && height) { 759 lightbox_code = `<dialog id="lightbox"${lightbox_class} role="dialog" aria-labelledby="lightbox_title" class="nowidth" style="height:${height};"><div role="document">`; 760 } else if (width && !height) { 761 lightbox_code = `<dialog id="lightbox"${lightbox_class} role="dialog" aria-labelledby="lightbox_title" class="noheight" style="width:${width};"><div role="document">`; 762 } else { 763 lightbox_code = `<dialog id="lightbox"${lightbox_class} role="dialog" aria-labelledby="lightbox_title" class="nowidth noheight"><div role="document">`; 764 } 765 766 // Boutons et titre 767 lightbox_code += `<button id="lightbox_close" class="close" data-opener="${opener}" title="Fermer"><span class="invisible">Fermer</span></button>`; 768 if (lightbox_class) { 769 lightbox_code += `<a href="${href}" target="_blank" id="lightbox_fullscreen" class="fullscreen" title="Plein écran"><span class="invisible">Voir le <abbr>PDF</abbr> en plein écran</span></a>`; 770 } else { 771 lightbox_code += `<a href="${href}" target="_blank" id="lightbox_fullscreen" class="fullscreen" title="Plein écran"><span class="invisible">Ouvrir en plein écran</span></a>`; 772 } 773 if (title) { 774 lightbox_code += `<h1 id="lightbox_title">${title}</h1>`; 775 } 776 777 // Contenu selon le type 778 if (type === "iframe") { 779 lightbox_code += `<iframe src="${href}"></iframe>`; 780 } else if (type === "innerHtml") { 781 const targetElement = document.querySelector(href); 782 lightbox_code += targetElement ? targetElement.innerHTML : ""; 783 } else if (type === "image") { 784 lightbox_code += `<figure><img src="${href}" alt="" /></figure>`; 785 } 786 lightbox_code += "</div></dialog>"; 787 788 // Ajout de la lightbox au DOM 789 page.insertAdjacentHTML("afterend", lightbox_code); 790 791 // Gestion des événements clavier pour fermer avec "Escape" 792 const iframe = document.querySelector("#lightbox iframe"); 793 if (iframe) { 794 iframe.addEventListener("load", function () { 795 const contents = iframe.contentDocument || iframe.contentWindow.document; 796 if (contents) { 797 const body = contents.body; 798 if (body) { 799 body.addEventListener("keydown", function (event) { 800 if (event.key === "Escape" || event.keyCode === 27) { 801 closeLightboxes(); 802 } 803 }); 804 } 805 } 806 }); 807 } 808 809 // Masquer la page principale 810 if (page) { 811 page.setAttribute("aria-hidden", "true"); 812 } 813 814 // Ajout de l'overlay et animation
815 const overlay = document.createElement("div"); 816 overlay.id = "overlay"; 817 overlay.title = "Fermer"; 818 819 const invisibleText = document.createElement("span"); 820 invisibleText.classList.add("invisible"); 821 invisibleText.textContent = "Fermer la fenêtre"; 822 overlay.appendChild(invisibleText); 823 824 const lightbox = document.getElementById("lightbox"); 825 lightbox.insertAdjacentElement("afterend", overlay); 826 827 overlay.style.display = "block"; 828 overlay.style.opacity = 0; 829 830 let opacity = 0; 831 const fadeIn = setInterval(() => { 832 opacity += 0.02; 833 overlay.style.opacity = opacity; 834 if (opacity >= 0.6) clearInterval(fadeIn); 835 }, 10); 836 837 lightbox.style.top = "0px"; 838 839 let currentTop = 0; 840 const targetTop = 140; 841 const animateDown = setInterval(() => { 842 currentTop += (targetTop - currentTop) * 0.1; 843 lightbox.style.top = `${currentTop}px`; 844 if (Math.abs(currentTop - targetTop) < 1) { 845 lightbox.style.top = `${targetTop}px`; 846 clearInterval(animateDown); 847 } 848 }, 20); 849 850 // Focus sur le bouton de fermeture 851 const closeButton = document.getElementById("lightbox_close"); 852 if (closeButton) closeButton.focus(); 853} 854 855// Fonction openLightbox: élément string URL 856function openLightbox(href) { 857 const type = href.startsWith("#") 858 ? "innerHtml" 859 : href.endsWith("jpg") || href.endsWith("gif") || href.endsWith("png") 860 ? "image" 861 : "iframe"; 862 863 createLightbox({ 864 opener: "test", 865 href, 866 title: "", 867 width: "", 868 height: "", 869 type, 870 }); 871} 872 873// Fonction openLightboxes : élément HTML 874function openLightboxes(link) { 875 const options = link.dataset; 876 const href = link.getAttribute("href"); 877 const type = href.startsWith("#") 878 ? "innerHtml" 879 : href.endsWith("jpg") || href.endsWith("gif") || href.endsWith("png") 880 ? "image" 881 : "iframe"; 882 883 createLightbox({ 884 opener: link.id, 885 href, 886 title: options.lightboxTitle || "", 887 width: options.lightboxWidth || "", 888 height: options.lightboxHeight || "", 889 type, 890 }); 891} 892 893 894function closeLightboxes() { 895 896 var closeButton = document.getElementById("lightbox_close"); 897 var focusSelector = "#" + closeButton.getAttribute("data-opener"); 898 var focusElement = document.querySelector(focusSelector); 899 900 var lightbox = document.getElementById("lightbox"); 901 var overlay = document.getElementById("overlay"); 902 var page = document.getElementById("lightbox_page"); 903 904 page.removeAttribute("aria-hidden"); 905 906 if (lightbox) lightbox.remove(); 907 if (overlay) overlay.remove(); 908 909 if (focusElement) focusElement.focus(); 910 } 911 912 913function initLightboxes(e) { 914 // init 915 //console.log( $('a.lightbox').length + " lightbox(s)"); 916 917 if (document.querySelectorAll("a.lightbox").length) { 918 document.querySelectorAll("a.lightbox").forEach(function (link, index) { 919 if (link.getAttribute("id") === null) { 920 link.setAttribute("id", "open_lightbox_" + index); 921 } 922 }); 923 924 if (document.getElementById("lightbox_page") === null) { 925 var wrapper = document.createElement('div'); 926 wrapper.id = 'lightbox_page'; 927 document.body.appendChild(wrapper); 928 Array.from(document.body.childNodes).forEach(function (node) { 929 if (node !== wrapper) { 930 wrapper.appendChild(node); 931 } 932 }); 933 } 934 935 // Au clic sur un a.lightbox 936 /*document.addEventListener("DOMContentLoaded", function() { 937 document.querySelectorAll("a.lightbox").forEach(function(element) { 938 element.addEventListener("click", function(event) { 939 openLightboxes(element); 940 event.preventDefault(); 941 }); 942 }); 943 }); 944*/ 945 946/* 947 document.body.addEventListener("click", function (event) { 948 const element = event.target.closest("a.lightbox"); 949 event.preventDefault(); 950 if (element) { 951 // Simule l'objet encapsulé par jQuery 952 const encapsulatedObject = { 953 0: element, // Ãlément DOM natif 954 length: 1, // Toujours un seul élément dans ce contexte 955 dataset: { ...element.dataset }, // Tous les data-* sous forme d'objet 956 }; 957 openLightboxes(element); 958 } 959 }); 960*/ 961 962 document.body.addEventListener("click", function (event) { 963 const element = event.target.closest("a.lightbox"); 964 965 if (element) { 966 event.preventDefault(); 967 openLightboxes(element); 968 } 969 }); 970 971 972 /*document.body.addEventListener('click', function (event) { 973 if (event.target.matches === 'a.lightbox') { 974 openLightboxes(thisElement); 975 event.preventDefault(); 976 } 977 });*/ 978 979 // Bouton de fermeture (et touche ESC) 980 document.body.addEventListener('click', function (event) { 981 if (event.target.id === 'lightbox_close' || event.target.matches('.lightbox_close') || event.target.id === 'overlay') { 982 closeLightboxes(); 983 } 984 }); 985 986 // Ãcouteur pour la touche ESC 987 document.body.addEventListener('keydown', function (event) { 988 // Vérifie si la touche 'Escape' est pressée 989 if (event.key === 'Escape' || event.keyCode === 27) { 990 closeLightboxes(); 991 } 992 }); 993 994 995 996 // Au besoin, on peut d�clencher l'ouverture de la lightbox via un param�tre "open" dans l'URL prenant la valeur de l'ID du lien � d�clencher 997 //id2open = getVar('open'); 998 //if (id2open != 0) { 999 // console.log('id2open: ' + id2open); 1000 // $("a#"+id2open).click(); 1001 // var eventClick = new Event('click'); 1002 // document.querySelector("a#"+id2open).dispatchEvent(eventClick); 1003 //openLightboxes($("a.lightbox#" + id2open)); 1004 //} 1005 } 1006} 1007 1008// Polyfill customevent 1009// Polyfill pour CustomEvent (JS natif) 1010(function () { 1011 if (typeof window.CustomEvent === "function") return; 1012 1013 function CustomEvent(event, params) { 1014 params = params || { bubbles: false, cancelable: false, detail: undefined }; 1015 var evt = document.createEvent("CustomEvent"); 1016 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 1017 return evt; 1018 } 1019 1020 CustomEvent.prototype = window.Event.prototype; 1021 window.CustomEvent = CustomEvent; 1022})(); 1023 1024// Appel de `initLightboxes` une fois le DOM chargé 1025document.addEventListener("DOMContentLoaded", initLightboxes); 1026 1027// Gestion de la liste déroulante (JS natif) 1028document.addEventListener("DOMContentLoaded", function () { 1029 // Click en dehors d'une liste déroulante : Fermeture 1030 document.addEventListener("click", function (e) { 1031 const clickedElement = e.target; 1032 1033 // Si le clic est sur un lien ou un élément dans une liste déroulante, on ignore 1034 if (clickedElement.closest("a") || clickedElement.closest(".list")) { 1035 return; // Ne fait rien, laisse le clic passer 1036 } 1037 1038 // Sinon, fermer toutes les listes déroulantes 1039 document.querySelectorAll(".list ul.list").forEach(function (ul) { 1040 ul.style.display = "none"; // Cache toutes les listes déroulantes 1041 }); 1042 1043 document.querySelectorAll(".list p.sel.open").forEach(function (sel) { 1044 sel.classList.remove("open"); // Retire la classe "open" des éléments sélectionnés 1045 }); 1046 });
1047 1048 // Gestion du clic sur un élément `.list p.sel` 1049 document.querySelectorAll(".cc .list p.sel").forEach(function (sel) { 1050 sel.addEventListener("click", function (e) { 1051 e.stopPropagation(); // Empêche la propagation pour ne pas déclencher le clic global 1052 const nextElement = this.nextElementSibling; // Récupère l'élément suivant (ul.list) 1053 1054 if (nextElement && nextElement.tagName === "UL") { 1055 // Basculer l'affichage du ul 1056 if (nextElement.style.display === "block") { 1057 nextElement.style.display = "none"; 1058 } else { 1059 nextElement.style.display = "block"; 1060 } 1061 1062 // Basculer la classe "open" 1063 this.classList.toggle("open"); 1064 } 1065 }); 1066 }); 1067}); 1068 1069 1070 1071 1072 1073/** 1074 * Retourne une fonction qui, tant qu'elle continue à être invoquée, 1075 * ne sera pas exécutée. La fonction ne sera exécutée que lorsque 1076 * l'on cessera de l'appeler pendant plus de N millisecondes. 1077 * Si le paramètre `immediate` vaut vrai, alors la fonction 1078 * sera exécutée au premier appel au lieu du dernier. 1079 * Paramètres : 1080 * - func : la fonction à `debouncer` 1081 * - wait : le nombre de millisecondes (N) à attendre avant 1082 * d'appeler func() 1083 * - immediate (optionnel) : Appeler func() à la première invocation 1084 * au lieu de la dernière (Faux par défaut) 1085 * - context (optionnel) : le contexte dans lequel appeler func() 1086 * (this par défaut) 1087 */ 1088function debounce(func, wait, immediate, context) { 1089 var result; 1090 var timeout = null; 1091 1092 return function () { 1093 var ctx = context || this, 1094 args = arguments; 1095 var later = function () { 1096 timeout = null; 1097 if (!immediate) result = func.apply(ctx, args); 1098 }; 1099 var callNow = immediate && !timeout; 1100 // Tant que la fonction est appelée, on reset le timeout. 1101 clearTimeout(timeout); 1102 timeout = setTimeout(later, wait); 1103 if (callNow) result = func.apply(ctx, args); 1104 1105 return result; 1106 }; 1107} 1108 1109// Fonction modulo négatif 1110function mod(n, m) { 1111 return ((n % m) + m) % m; 1112} 1113 1114// Polyfill Array.prototype.map 1115// Production steps of ECMA-262, Edition 5, 15.4.4.19 1116// Reference: http://es5.github.io/#x15.4.4.19 1117/** 1118 * Exemple d'utilisation: 1119 * let numbers = [1, 4, 9] 1120 let roots = numbers.map(function(num) { 1121 return Math.sqrt(num) 1122 }) 1123 // roots is now [1, 2, 3] 1124 // numbers is still [1, 4, 9] 1125 */ 1126 1127if (!Array.prototype.map) { 1128 Array.prototype.map = function (callback /*, thisArg*/) { 1129 var T, A, k; 1130 1131 if (this == null) { 1132 throw new TypeError("this is null or not defined"); 1133 } 1134 1135 // 1. Let O be the result of calling ToObject passing the |this| 1136 // value as the argument. 1137 var O = Object(this); 1138 1139 // 2. Let lenValue be the result of calling the Get internal 1140 // method of O with the argument "length". 1141 // 3. Let len be ToUint32(lenValue). 1142 var len = O.length >>> 0; 1143 1144 // 4. If IsCallable(callback) is false, throw a TypeError exception. 1145 // See: http://es5.github.com/#x9.11 1146 if (typeof callback !== "function") { 1147 throw new TypeError(callback + " is not a function"); 1148 } 1149 1150 // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. 1151 if (arguments.length > 1) { 1152 T = arguments[1]; 1153 } 1154 1155 // 6. Let A be a new array created as if by the expression new Array(len) 1156 // where Array is the standard built-in constructor with that name and 1157 // len is the value of len. 1158 A = new Array(len); 1159 1160 // 7. Let k be 0 1161 k = 0; 1162 1163 // 8. Repeat, while k < len 1164 while (k < len) { 1165 var kValue, mappedValue; 1166 1167 // a. Let Pk be ToString(k). 1168 // This is implicit for LHS operands of the in operator 1169 // b. Let kPresent be the result of calling the HasProperty internal 1170 // method of O with argument Pk. 1171 // This step can be combined with c 1172 // c. If kPresent is true, then 1173 if (k in O) { 1174 // i. Let kValue be the result of calling the Get internal 1175 // method of O with argument Pk. 1176 kValue = O[k]; 1177 1178 // ii. Let mappedValue be the result of calling the Call internal 1179 // method of callback with T as the this value and argument 1180 // list containing kValue, k, and O. 1181 mappedValue = callback.call(T, kValue, k, O); 1182 1183 // iii. Call the DefineOwnProperty internal method of A with arguments 1184 // Pk, Property Descriptor 1185 // { Value: mappedValue, 1186 // Writable: true, 1187 // Enumerable: true, 1188 // Configurable: true }, 1189 // and false. 1190 1191 // In browsers that support Object.defineProperty, use the following: 1192 // Object.defineProperty(A, k, { 1193 // value: mappedValue, 1194 // writable: true, 1195 // enumerable: true, 1196 // configurable: true 1197 // }); 1198 1199 // For best browser support, use the following: 1200 A[k] = mappedValue; 1201 } 1202 // d. Increase k by 1. 1203 k++; 1204 } 1205 1206 // 9. return A 1207 return A; 1208 }; 1209} 1210 1211// Polyfill foreach 1212if (window.NodeList && !NodeList.prototype.forEach) { 1213 NodeList.prototype.forEach = function (callback, thisArg) { 1214 thisArg = thisArg || window; 1215 for (var i = 0; i < this.length; i++) { 1216 callback.call(thisArg, this[i], i, this); 1217 } 1218 }; 1219} 1220 1221/*document.addEventListener('DOMContentLoaded', function () { 1222 var youtubePlayers = document.getElementsByClassName('youtube-player'); 1223 for (var i=0, len=youtubePlayers.length|0; i<len; i=i+1|0) { 1224 youtubePlayer = youtubePlayers[i].getElementsByTagName('iframe')[0]; 1225 if (isSolutionAccepted('youtube')) { 1226 var youtubeSRC = youtubePlayer.dataset.src; 1227 youtubePlayer.setAttribute('src',youtubeSRC); 1228 } else { 1229 $( ".youtube-player > iframe" ).hide(); 1230 var div = document.createElement('div'); 1231 div.innerHTML = '<div id="youtube-consent-txt"><p>Le visionnage de cette vidéo est susceptible d\'entrainer un dépôt de cookies de la part de l\'opérateur de la plate-forme vidéo vers laquelle vous serez dirigé. Compte-tenu du refus du dépôt de cookies que vous avez exprimé, afin de respecter votre choix, nous avons bloqué la lecture de cette vidéo.</p><p>Si vous souhaitez continuer et lire la vidéo, <a href="'+cookiePolicyLink+'">vous devez nous donner votre accord</a>.</p></div>'; 1232 youtubePlayers[i].insertBefore( div, null ); 1233 1234 } 1235 } 1236}, false);*/ 1237 1238HTMLElement.prototype.setAttributes = function (attrs) { 1239 for (var key in attrs) { 1240 this.setAttribute(key, attrs[key]); 1241 } 1242}; 1243 1244// SVGElement classList polyfill 1245if (!("classList" in SVGElement.prototype)) { 1246 Object.defineProperty(SVGElement.prototype, "classList", { 1247 get: function get() { 1248 var _this = this; 1249 1250 return { 1251 contains: function contains(className) { 1252 return _this.className.baseVal.split(" ").indexOf(className) !== -1; 1253 }, 1254 add: function add(className) { 1255 var newClass = (_this.getAttribute("class") + " " + className).trim(); 1256 return _this.setAttribute("class", newClass); 1257 }, 1258 remove: function remove(className) { 1259 var classes = _this.getAttribute("class") || ""; 1260 var regex = new RegExp("(?:^|\\s)" + className + "(?!\\S)", "g"); 1261 classes = classes.replace(regex, "").trim(); 1262 _this.setAttribute("class", classes); 1263 }, 1264 toggle: function toggle(className) { 1265 if (this.contains(className)) { 1266 this.remove(className); 1267 } else { 1268 this.add(className); 1269 } 1270 }, 1271 }; 1272 }, 1273 }); 1274} 1275 1276// Polyfill Object 1277if (!Object.assign) { 1278 Object.defineProperty(Object, "assign", { 1279 enumerable: false, 1280 configurable: true, 1281 writable: true, 1282 value: function (target) { 1283 "use strict"; 1284 if (target === undefined || target === null) { 1285 throw new TypeError("Cannot convert first argument to object"); 1286 } 1287 1288 var to = Object(target); 1289 for (var i = 1; i < arguments.length; i++) { 1290 var nextSource = arguments[i]; 1291 if (nextSource === undefined || nextSource === null) { 1292 continue; 1293 } 1294 nextSource = Object(nextSource); 1295 1296 var keysArray = Object.keys(Object(nextSource)); 1297 for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { 1298 var nextKey = keysArray[nextIndex]; 1299 var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); 1300 if (desc !== undefined && desc.enumerable) { 1301 to[nextKey] = nextSource[nextKey]; 1302 } 1303 } 1304 } 1305 return to; 1306 }, 1307 }); 1308} 1309 1310if (!Object.entries) { 1311 Object.entries = function (obj) { 1312 var ownProps = Object.keys(obj), 1313 i = ownProps.length, 1314 resArray = new Array(i); 1315 while (i--) resArray[i] = [ownProps[i], obj[ownProps[i]]]; 1316 1317 return resArray; 1318 }; 1319} 1320 1321// Clamp 1322Math.clamp = function (num, min, max) { 1323 return Math.min(Math.max(num, min), max); 1324}; 1325 1326// String polyfills 1327if (!String.prototype.startsWith) { 1328 Object.defineProperty(String.prototype, "startsWith", { 1329 value: function (search, rawPos) { 1330 var pos = rawPos > 0 ? rawPos | 0 : 0; 1331 return this.substring(pos, pos + search.length) === search; 1332 }, 1333 }); 1334} 1335 1336if (!String.prototype.includes) { 1337 String.prototype.includes = function (search, start) { 1338 "use strict"; 1339 1340 if (search instanceof RegExp) { 1341 throw TypeError("first argument must not be a RegExp"); 1342 } 1343 if (start === undefined) { 1344 start = 0; 1345 } 1346 return this.indexOf(search, start) !== -1; 1347 }; 1348} 1349 1350// Polyfill array 1351if (!Array.prototype.includes) { 1352 //or use Object.defineProperty 1353 Array.prototype.includes = function (search) { 1354 return !!~this.indexOf(search); 1355 }; 1356} 1357if (!Array.prototype.indexOf) { 1358 Array.prototype.indexOf = (function (Object, max, min) { 1359 "use strict"; 1360 return function indexOf(member, fromIndex) { 1361 if (this === null || this === undefined) throw TypeError("Array.prototype.indexOf called on null or undefined"); 1362 1363 var that = Object(this), 1364 Len = that.length >>> 0, 1365 i = min(fromIndex | 0, Len); 1366 if (i < 0) i = max(0, Len + i); 1367 else if (i >= Len) return -1; 1368 1369 if (member === void 0) { 1370 for (; i !== Len; ++i) if (that[i] === void 0 && i in that) return i; // undefined 1371 } else if (member !== member) { 1372 for (; i !== Len; ++i) if (that[i] !== that[i]) return i; // NaN 1373 } else for (; i !== Len; ++i) if (that[i] === member) return i; // all else 1374 1375 return -1; // if the value was not found, then return -1 1376 }; 1377 })(Object, Math.max, Math.min); 1378} 1379 1380// Polyfill Element.remove() 1381(function (elem) { 1382 for (var i = 0; i < elem.length; i++) { 1383 if (!window[elem[i]] || "remove" in window[elem[i]].prototype) continue; 1384 window[elem[i]].prototype.remove = function () { 1385 this.parentNode.removeChild(this); 1386 }; 1387 } 1388})(["Element", "CharacterData", "DocumentType"]); 1389 1390function getCoords(elem) { 1391 var box = elem.getBoundingClientRect(); 1392 1393 var body = document.body; 1394 var docEl = document.documentElement; 1395 1396 var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; 1397 var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft; 1398 1399 var clientTop = docEl.clientTop || body.clientTop || 0; 1400 var clientLeft = docEl.clientLeft || body.clientLeft || 0; 1401 1402 var top = box.top + scrollTop - clientTop; 1403 var left = box.left + scrollLeft - clientLeft; 1404 1405 return { x: Math.round(left), y: Math.round(top) }; 1406} 1407 1408// Rendre le bouton "imprimer" activable via la touche espace 1409document.addEventListener("DOMContentLoaded", () => { 1410 const printButton = document.querySelector(".cc a.print"); 1411 1412 if (!printButton) return; 1413 1414 printButton.addEventListener("keydown", (e) => { 1415 if (e.code === "Space") { 1416 e.preventDefault(); 1417 e.target.click(); 1418 } 1419 }); 1420}); 1421// Auto canonical 1422document.addEventListener('DOMContentLoaded', () => {
1423 // Récupérer l'URL de la page actuelle 1424 const currentUrl = window.location.href; 1425 const baseUrl = window.location.origin; 1426 1427 // Fonction pour vérifier si un lien existe déjà 1428 function linkExists(rel) { 1429 const existingLinks = document.head.getElementsByTagName('link'); 1430 for (let i = 0; i < existingLinks.length; i++) { 1431 if (existingLinks[i].getAttribute('rel') === rel ) { 1432 return true; 1433 } 1434 } 1435 return false; 1436 } 1437 1438 const hreflangUrls = [ 1439 { lang: 'fr', url: `${baseUrl}${window.location.pathname}${window.location.search}` }, 1440 ]; 1441 1442 // Canonical URL 1443 if (!linkExists('canonical', currentUrl)) { 1444 const canonicalLink = document.createElement('link'); 1445 canonicalLink.setAttribute('rel', 'canonical'); 1446 canonicalLink.href = currentUrl; 1447 document.head.appendChild(canonicalLink); 1448 hreflangUrls.forEach(({ lang, url }) => { 1449 const hreflangLink = document.createElement('link'); 1450 hreflangLink.setAttribute('rel', 'alternate'); 1451 hreflangLink.setAttribute('hreflang', lang); 1452 hreflangLink.href = url; 1453 document.head.appendChild(hreflangLink); 1454 }); 1455 } 1456}); 1457 1458// Auto scroll lien # 1459document.addEventListener('DOMContentLoaded', function() { 1460 const links = document.querySelectorAll('a[href^="#"]'); 1461 1462 function handleLinkClick(event) { 1463 event.preventDefault(); 1464 1465 const targetId = this.getAttribute('href').substring(1); 1466 const targetElement = document.getElementById(targetId); 1467 1468 if (targetElement) { 1469 const headerHeight = document.querySelector('.ei_header').offsetHeight; 1470 const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset; 1471 const offsetPosition = targetPosition - headerHeight; 1472 1473 window.scrollTo({top: offsetPosition, behavior: 'smooth'}); 1474 history.pushState(null, null, `#${targetId}`); 1475 } 1476 } 1477 1478 links.forEach(link => {link.addEventListener('click', handleLinkClick)}); 1479 1480 window.addEventListener('popstate', function() { 1481 const hash = window.location.hash.substring(1); 1482 if (hash) { 1483 const targetElement = document.getElementById(hash); 1484 if (targetElement) { 1485 const headerHeight = document.querySelector('.ei-header').offsetHeight; 1486 const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset; 1487 const offsetPosition = targetPosition - headerHeight; 1488 window.scrollTo({top: offsetPosition, behavior: 'smooth'}); 1489 } 1490 } 1491 }); 1492});
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.