PageSourceSearch

https://www.creditmutuel-equity.eu/partage/fr/CSD/scripts/core.js

js creditmutuel-equity.eu collected 2026-10-09 18:24:11 UTC 50,356 bytes, 1,492 lines download raw bytes

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 + '&nbsp;</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.