const mapContainer = d3.select("#map"); const modal = document.getElementById("country-modal"); const countryName = document.getElementById("country-name"); const countryCategory = document.getElementById("country-category"); const countryData = document.getElementById("country-data"); const closeModalButton = document.getElementById("close-modal"); const legendContainer = document.getElementById("category-legend"); const countrySearchInputDesktop = document.getElementById("country-search"); const countryListContainerDesktop = document.getElementById("country-list"); const countryListCountDesktop = document.getElementById("country-list-count"); const countrySearchInputMobile = document.getElementById("country-search-mobile"); const countryListContainerMobile = document.getElementById("country-list-mobile"); const countryListCountMobile = document.getElementById("country-list-count-mobile"); const openMobileCountryListButton = document.getElementById("open-mobile-country-list"); const closeCountryListModalButton = document.getElementById("close-country-list-modal"); const countryListModal = document.getElementById("country-list-modal"); const legendToggleButton = document.getElementById("toggle-mobile-legend"); const mapTooltip = document.getElementById("map-tooltip"); const worldGeoJsonUrl = "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_50m_admin_0_map_units.geojson"; const rawPolicyDataUrl = "./znep_gta_pays_etrangers.txt"; const legacyColorByCode = { VERT: "#22c55e", BLEU: "#3b82f6", ORANGE: "#f59e0b", ROUGE: "#ef4444", }; const colorByAuthorizationCode = { "10": "#22c55e", "21": "#facc15", "22": "#f59e0b", "23": "#ef4444", "30": "#0a0a0a", "99": "#ef4444", }; const explicitCategoryTitleByCode = { "10": "Libre circulation (sans formalité)", "21": "Autorisation ministérielle renforcée", "22": "Autorisation préalable + avis PSD", "23": "Autorisation CFA / autorité assimilée", "30": "Interdiction de séjour", "99": "Autorisation selon zone de destination", }; const procedureSummaryByAuthorizationCode = { "10": "Déplacement possible sans autorisation préalable spécifique.", "21": "Autorisation ministérielle obligatoire avant départ.", "22": "Autorisation préalable obligatoire avec avis PSD.", "23": "Autorisation CFA (ou autorité assimilée) obligatoire avant départ.", "30": "Destination interdite : déplacement non autorisé.", "99": "Autorisation variable selon la zone/pays de destination.", }; const noteServiceUpdateDate = "20260316"; const noteServiceProcedureReference = `ANNEXE II à la circulaire n" l 1 400/ARM/SGA/DRH-MD/SR-RH/SDFM/FM5 du 30 juillet 2024. Message n"5}l397lARM/CMlAIP du 13 mars2026`; const defaultCountryColor = "#6b7280"; const forcedPolicyIsoByMatchedParentIso = { GB: ["GI"], NO: ["BV"], US: ["UM"], }; const mapIsoToPolicyIsoAlias = { "CN-TW": "TW", TL: "TP", CW: "AN", SX: "AN", BQ: "AN", }; const mapNameToPolicyIsoAlias = { antigua: "AG", barbuda: "AG", "federation of bosnia and herzegovina": "BA", "republic srpska": "BA", "flemish region": "BE", "walloon region": "BE", brussels: "BE", gaza: "PS", "west bank": "PS", "united states minor outlying islands": "UM", "autonomous region of bougainville": "PG", bougainville: "PG", azores: "PT", madeira: "PT", wales: "GB", scotland: "GB", england: "GB", "northern ireland": "GB", "nouvelle caledonie": "FR", "new caledonia": "FR", "polynesie francaise": "FR", "french polynesia": "FR", "saint barthelemy": "FR", "saint martin": "FR", "saint pierre et miquelon": "FR", "saint pierre and miquelon": "FR", "terres australes et antarctiques francaises": "FR", "french southern and antarctic lands": "FR", "wallis et futuna": "FR", "wallis and futuna": "FR", "chypre du nord": "CY", "northern cyprus": "CY", somaliland: "SO", "glacier de siachen": "IN", "siachen glacier": "IN", }; let width = 0; let height = 0; let countries = []; let countryShadowPaths = null; let countryPaths = null; let countryPolicyByIso2 = new Map(); let countryPolicyByName = new Map(); let categoryByCode = new Map(); let lastAnalysis = null; let countryEntries = []; let countryByKey = new Map(); const svg = mapContainer.append("svg").attr("aria-hidden", "true"); const zoomLayer = svg.append("g"); const countryShadowLayer = zoomLayer .append("g") .attr("class", "country-shadow-layer") .attr("transform", "translate(1.8,1.8)"); const countryLayer = zoomLayer.append("g"); const projection = d3.geoRobinson ? d3.geoRobinson() : d3.geoEqualEarth(); const path = d3.geoPath(projection); let currentTransform = d3.zoomIdentity; const zoom = d3 .zoom() .scaleExtent([1, 40]) .on("start", () => { hideCountryTooltip(); }) .on("zoom", (event) => { currentTransform = event.transform; zoomLayer.attr("transform", currentTransform); }); function normalizeCountryName(name) { return String(name || "") .normalize("NFD") .replace(/[\u0300-\u036f]/g, "") .toLowerCase() .replace(/[^a-z0-9]+/g, " ") .trim(); } function getCountryLabel(feature) { return ( feature.properties?.NAME_FR || feature.properties?.NAME_EN || feature.properties?.NAME || "Pays inconnu" ); } function getCountryIso2(feature) { const rawIso2 = getCountryIso2Raw(feature); if (!rawIso2) { return ""; } return mapIsoToPolicyIsoAlias[rawIso2] || rawIso2; } function getCountryIso2Raw(feature) { const direct = String(feature.properties?.ISO_A2 || "").toUpperCase().trim(); if (direct && direct !== "-99") { return direct; } const fallback = String(feature.properties?.ISO_A2_EH || "") .toUpperCase() .trim(); if (fallback && fallback !== "-99") { return fallback; } return ""; } function getFlagEmojiFromIso2(iso2) { const code = String(iso2 || "").toUpperCase(); if (!/^[A-Z]{2}$/.test(code)) { return "🏳️"; } const first = code.codePointAt(0) + 127397; const second = code.codePointAt(1) + 127397; return String.fromCodePoint(first, second); } function htmlToText(htmlString) { const parser = new DOMParser(); const doc = parser.parseFromString(String(htmlString || ""), "text/html"); return (doc.body.textContent || "").replace(/\s+/g, " ").trim(); } function formatDate(yyyymmdd) { const value = String(yyyymmdd || ""); if (!/^\d{8}$/.test(value)) { return value; } if (value === "99991231") { return "Sans fin"; } const year = value.slice(0, 4); const month = value.slice(4, 6); const day = value.slice(6, 8); return `${day}/${month}/${year}`; } function escapeHtml(value) { return String(value) .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll("\"", """) .replaceAll("'", "'"); } function getCategoryDisplayLabel(code, fallbackLabel) { return ( explicitCategoryTitleByCode[String(code || "")] || fallbackLabel || `Catégorie ${code}` ); } function getCategoryColor(code, fallbackColorCode) { return ( colorByAuthorizationCode[String(code || "")] || legacyColorByCode[String(fallbackColorCode || "")] || defaultCountryColor ); } function summarizeProcedureText(rawText, categoryCode) { const code = String(categoryCode || ""); const fallbackSummary = procedureSummaryByAuthorizationCode[code] || ""; const cleaned = String(rawText || "").replace(/\s+/g, " ").trim(); if (!cleaned) { return fallbackSummary || "Non renseignée"; } const fragments = cleaned .split(/[.;]\s+|\n+/) .map((value) => value.replace(/^[\s\-•\d).]+/, "").trim()) .filter(Boolean); const keywords = /(autorisation|autorise|interdit|interdiction|avis|accord|demande|validation|cfa|psd|minist[eè]re|depart|départ|avant)/i; const selected = []; for (let i = 0; i < fragments.length; i += 1) { const fragment = fragments[i]; if (fragment.length < 18) { continue; } if (!keywords.test(fragment) && selected.length > 0) { continue; } selected.push(fragment); if (selected.length >= 2) { break; } } if (selected.length === 0 && fragments.length > 0) { selected.push(fragments[0]); } let literalSummary = selected.join(" / "); if (literalSummary.length > 210) { literalSummary = `${literalSummary.slice(0, 207)}...`; } if (!fallbackSummary) { return literalSummary || "Non renseignée"; } return literalSummary ? `${fallbackSummary} ${literalSummary}` : fallbackSummary; } function isConcernedByMarch2026Note(policy) { return ( String(policy?.beginDate || "") === noteServiceUpdateDate && String(policy?.updateDate || "") === noteServiceUpdateDate ); } function parseFlatTable(flatTable) { if (!Array.isArray(flatTable) || flatTable.length < 2) { return []; } const columnCount = Number(flatTable[0]); if (!Number.isInteger(columnCount) || columnCount <= 0) { return []; } const headers = flatTable.slice(1, columnCount + 1); const rows = []; for (let index = columnCount + 1; index < flatTable.length; index += columnCount) { const row = {}; for (let col = 0; col < columnCount; col += 1) { row[headers[col]] = flatTable[index + col] ?? ""; } rows.push(row); } return rows; } function isBetterCountryRow(candidate, current) { const candidateActive = candidate.ENDDA === "99991231" ? 1 : 0; const currentActive = current.ENDDA === "99991231" ? 1 : 0; if (candidateActive !== currentActive) { return candidateActive > currentActive; } const candidateBegda = String(candidate.BEGDA || ""); const currentBegda = String(current.BEGDA || ""); if (candidateBegda !== currentBegda) { return candidateBegda > currentBegda; } const candidateAedtm = String(candidate.AEDTM || ""); const currentAedtm = String(current.AEDTM || ""); return candidateAedtm > currentAedtm; } function parsePolicyModel(rawText) { const parsedJson = JSON.parse(rawText); const rawCountryRows = parseFlatTable(parsedJson.modelmasterListData); const rawCategoryRows = parseFlatTable(parsedJson.modelmasterListCatData); const countryRowsByIso = new Map(); rawCountryRows.forEach((row) => { const iso2 = String(row.LAND1 || "").toUpperCase().trim(); if (!iso2) { return; } const current = countryRowsByIso.get(iso2); if (!current || isBetterCountryRow(row, current)) { countryRowsByIso.set(iso2, row); } }); const countriesData = Array.from(countryRowsByIso.values()).map((row) => ({ iso2: String(row.LAND1 || "").toUpperCase(), countryNameFr: String(row.LANDX50 || ""), categoryCode: String(row.CATEGORIE || ""), categoryLabel: String(row.LBL_CATEGORIE || ""), colorCode: String(row.COLOR || ""), beginDate: String(row.BEGDA || ""), endDate: String(row.ENDDA || ""), beginDateText: String(row.BEGDA_TXT || ""), endDateText: String(row.ENDDA_TXT || ""), updateDate: String(row.AEDTM || ""), iconPath: String(row.DESCRIPTIF || ""), })); const categoriesData = rawCategoryRows.map((row) => ({ code: String(row.CATEGORIE || ""), label: String(row.LBL_CATEGORIE || ""), colorCode: String(row.COLOR || ""), beginDate: String(row.BEGDA || ""), endDate: String(row.ENDDA || ""), descriptionHtml: String(row.DESCRIPTIF_WDA || row.DESCRIPTIF || ""), descriptionText: htmlToText(row.DESCRIPTIF_WDA || row.DESCRIPTIF || ""), })); return { countriesData, categoriesData, }; } function getCountryPolicyForFeature(feature) { const iso2 = getCountryIso2(feature); if (iso2 && countryPolicyByIso2.has(iso2)) { return countryPolicyByIso2.get(iso2); } const names = [ feature.properties?.NAME_FR, feature.properties?.NAME_EN, feature.properties?.NAME, feature.properties?.ADMIN, feature.properties?.NAME_LONG, ]; for (let i = 0; i < names.length; i += 1) { const normalized = normalizeCountryName(names[i]); if (normalized && countryPolicyByName.has(normalized)) { return countryPolicyByName.get(normalized); } const aliasIso = mapNameToPolicyIsoAlias[normalized]; if (aliasIso && countryPolicyByIso2.has(aliasIso)) { return countryPolicyByIso2.get(aliasIso); } } return null; } function getCountryColor(feature) { const policy = getCountryPolicyForFeature(feature); if (!policy) { return defaultCountryColor; } return getCategoryColor(policy.categoryCode, policy.colorCode); } function moveCountryTooltip(event) { if (!mapTooltip.classList.contains("visible")) { return; } const [pointerX, pointerY] = d3.pointer(event, document.body); const rawX = Number.isFinite(event?.clientX) ? event.clientX : pointerX; const rawY = Number.isFinite(event?.clientY) ? event.clientY : pointerY; const offset = 14; const tooltipWidth = mapTooltip.offsetWidth || 160; const tooltipHeight = mapTooltip.offsetHeight || 36; const maxX = window.innerWidth - tooltipWidth - 8; const maxY = window.innerHeight - tooltipHeight - 8; const x = Math.max(8, Math.min(maxX, rawX + offset)); const y = Math.max(8, Math.min(maxY, rawY + offset)); mapTooltip.style.left = `${x}px`; mapTooltip.style.top = `${y}px`; } function showCountryTooltip(event, feature) { mapTooltip.textContent = getCountryLabel(feature); mapTooltip.classList.add("visible"); mapTooltip.setAttribute("aria-hidden", "false"); moveCountryTooltip(event); } function hideCountryTooltip() { mapTooltip.classList.remove("visible"); mapTooltip.setAttribute("aria-hidden", "true"); } function buildCountryEntries() { countryByKey = new Map(countries.map((feature) => [featureKey(feature), feature])); countryEntries = countries .map((feature) => { const policy = getCountryPolicyForFeature(feature); const mapIso2 = getCountryIso2Raw(feature); const iso2 = mapIso2 || policy?.iso2 || getCountryIso2(feature); return { key: featureKey(feature), name: getCountryLabel(feature), iso2, flag: getFlagEmojiFromIso2(iso2), }; }) .sort((a, b) => { return a.name.localeCompare(b.name, "fr", { sensitivity: "base" }); }); } function renderCountryList(filterValue = "") { const normalizedFilter = normalizeCountryName(filterValue); const filtered = countryEntries.filter((entry) => { const byName = normalizeCountryName(entry.name).includes(normalizedFilter); const byIso = String(entry.iso2 || "") .toLowerCase() .includes(normalizedFilter); return byName || byIso; }); const countText = `${filtered.length} / ${countryEntries.length} pays`; countryListCountDesktop.textContent = countText; countryListCountMobile.textContent = countText; let listHtml = ""; if (filtered.length === 0) { listHtml = '
  • Aucun pays trouvé.
  • '; } else { listHtml = filtered .map((entry) => { return `
  • `; }) .join(""); } countryListContainerDesktop.innerHTML = listHtml; countryListContainerMobile.innerHTML = listHtml; } function focusCountryOnMap(feature) { const bounds = path.bounds(feature); const x0 = bounds?.[0]?.[0]; const y0 = bounds?.[0]?.[1]; const x1 = bounds?.[1]?.[0]; const y1 = bounds?.[1]?.[1]; if (![x0, y0, x1, y1].every(Number.isFinite)) { return; } const featureWidth = Math.max(1, x1 - x0); const featureHeight = Math.max(1, y1 - y0); const centerX = (x0 + x1) / 2; const centerY = (y0 + y1) / 2; // Zoom cible plus fort au clic, ajusté à la taille du pays. const autoScale = 0.62 / Math.max(featureWidth / width, featureHeight / height); const targetScale = Math.min(20, Math.max(currentTransform.k, 4.5, autoScale)); const translateX = width / 2 - targetScale * centerX; const translateY = height / 2 - targetScale * centerY; const targetTransform = d3.zoomIdentity .translate(translateX, translateY) .scale(targetScale); svg.transition().duration(420).call(zoom.transform, targetTransform); } function openCountryListModal() { countryListModal.classList.add("open"); countryListModal.setAttribute("aria-hidden", "false"); countrySearchInputMobile.focus(); } function closeCountryListModal() { countryListModal.classList.remove("open"); countryListModal.setAttribute("aria-hidden", "true"); } function closeLegendOnMobile() { legendContainer.classList.remove("mobile-open"); legendToggleButton.setAttribute("aria-expanded", "false"); } function handleCountryListClick(event) { const button = event.target.closest("button[data-country-key]"); if (!button) { return; } const feature = countryByKey.get(button.dataset.countryKey); if (!feature) { return; } focusCountryOnMap(feature); openModalForFeature(feature); closeCountryListModal(); } function initCountryListEvents() { const syncAndRender = (value, source) => { const nextValue = value || ""; if (source !== "desktop" && countrySearchInputDesktop.value !== nextValue) { countrySearchInputDesktop.value = nextValue; } if (source !== "mobile" && countrySearchInputMobile.value !== nextValue) { countrySearchInputMobile.value = nextValue; } renderCountryList(nextValue); }; countrySearchInputDesktop.addEventListener("input", (event) => { syncAndRender(event.target.value, "desktop"); }); countrySearchInputMobile.addEventListener("input", (event) => { syncAndRender(event.target.value, "mobile"); }); countryListContainerDesktop.addEventListener("click", handleCountryListClick); countryListContainerMobile.addEventListener("click", handleCountryListClick); openMobileCountryListButton.addEventListener("click", openCountryListModal); closeCountryListModalButton.addEventListener("click", closeCountryListModal); countryListModal.addEventListener("click", (event) => { if (event.target === countryListModal) { closeCountryListModal(); } }); legendToggleButton.addEventListener("click", () => { const isOpen = legendContainer.classList.toggle("mobile-open"); legendToggleButton.setAttribute("aria-expanded", String(isOpen)); }); } function updateLegend() { if (!lastAnalysis) { legendContainer.innerHTML = ""; return; } const categories = [...lastAnalysis.categoryCounts.entries()].sort((a, b) => { if (a[0] === "30" && b[0] !== "30") { return 1; } if (b[0] === "30" && a[0] !== "30") { return -1; } return Number(a[0]) - Number(b[0]); }); const items = categories .map(([code, count]) => { const category = categoryByCode.get(code); const label = getCategoryDisplayLabel(code, category?.label); const hex = getCategoryColor(code, category?.colorCode); return `
  • Code ${code} - ${label} (${count})
  • `; }) .join(""); legendContainer.innerHTML = `

    Légende catégories

    `; } function setCountryDataHtml(lines) { const rows = lines .map( ([label, value]) => `
    ${escapeHtml( label )}${escapeHtml(value)}
    ` ) .join(""); countryData.innerHTML = rows; } function openModalForFeature(feature) { const mapLabel = getCountryLabel(feature); const policy = getCountryPolicyForFeature(feature); const mapIso2 = getCountryIso2Raw(feature); const iso2 = mapIso2 || policy?.iso2 || getCountryIso2(feature); const flag = getFlagEmojiFromIso2(iso2); countryName.textContent = `${flag} ${mapLabel}`; if (!policy) { countryCategory.textContent = "Aucune donnée de catégorie pour ce pays."; setCountryDataHtml([ ["Source", "Carte Natural Earth"], ["Code ISO2 carte", getCountryIso2(feature) || "N/A"], ]); } else { const category = categoryByCode.get(policy.categoryCode); const categoryLabel = getCategoryDisplayLabel( policy.categoryCode, category?.label || policy.categoryLabel ); countryCategory.textContent = `${categoryLabel} (code ${policy.categoryCode})`; const procedureText = summarizeProcedureText( category?.descriptionText || "", policy.categoryCode ); const fullProcedureText = isConcernedByMarch2026Note(policy) ? `${procedureText}\n\n${noteServiceProcedureReference}` : procedureText; setCountryDataHtml([ ["Pays (donnée source)", policy.countryNameFr || mapLabel], ["Code ISO2", policy.iso2], ["Début validité", formatDate(policy.beginDate)], ["Fin validité", formatDate(policy.endDate)], ["Dernière maj", formatDate(policy.updateDate)], ["Procédure", fullProcedureText || "Non renseignée"], ]); } modal.classList.add("open"); modal.setAttribute("aria-hidden", "false"); } function closeModal() { modal.classList.remove("open"); modal.setAttribute("aria-hidden", "true"); } function handleCountryClick(event, feature) { if (event.defaultPrevented) { return; } if (event.currentTarget && typeof event.currentTarget.blur === "function") { event.currentTarget.blur(); } focusCountryOnMap(feature); openModalForFeature(feature); } function featureKey(feature) { const iso3 = feature.properties?.ADM0_A3 || feature.properties?.ISO_A3 || "-"; const name = feature.properties?.NAME_EN || feature.properties?.NAME || "unknown"; return `${iso3}:${name}`; } function updateProjectionAndDrawing() { if (!countryPaths || !countryShadowPaths || countries.length === 0) { return; } const rect = mapContainer.node().getBoundingClientRect(); width = Math.max(320, rect.width); height = Math.max(240, rect.height); svg.attr("viewBox", `0 0 ${width} ${height}`); projection.fitExtent( [ [10, 10], [width - 10, height - 10], ], { type: "FeatureCollection", features: countries } ); countryShadowPaths.attr("d", path); countryPaths.attr("d", path); zoom .extent([ [0, 0], [width, height], ]) .translateExtent([ [-width, -height], [width * 2, height * 2], ]); svg.call(zoom).call(zoom.transform, currentTransform); } function analyzeMatching() { const categoryCounts = new Map(); const matchedIso2 = new Set(); let matchedMapCountries = 0; countryPolicyByIso2.forEach((policy) => { const categoryCode = policy.categoryCode || "N/A"; categoryCounts.set(categoryCode, (categoryCounts.get(categoryCode) || 0) + 1); }); countries.forEach((feature) => { const policy = getCountryPolicyForFeature(feature); if (!policy) { return; } matchedMapCountries += 1; matchedIso2.add(policy.iso2); }); Object.entries(forcedPolicyIsoByMatchedParentIso).forEach( ([parentIso, forcedIsoList]) => { if (!matchedIso2.has(parentIso)) { return; } forcedIsoList.forEach((forcedIso) => { matchedIso2.add(forcedIso); }); } ); const totalPolicyCountries = countryPolicyByIso2.size; const unmatchedMapCountries = countries.filter((feature) => !getCountryPolicyForFeature(feature)).length; const unmatchedIso2 = [...countryPolicyByIso2.keys()].filter((iso2) => !matchedIso2.has(iso2)); lastAnalysis = { totalPolicyCountries, matchedMapCountries, unmatchedMapCountries, categoryCounts, unmatchedIso2, }; } Promise.all([d3.json(worldGeoJsonUrl), d3.text(rawPolicyDataUrl)]) .then(([geoJson, rawPolicyText]) => { const parsedPolicy = parsePolicyModel(rawPolicyText); countryPolicyByIso2 = new Map(parsedPolicy.countriesData.map((item) => [item.iso2, item])); countryPolicyByName = new Map( parsedPolicy.countriesData .map((item) => [normalizeCountryName(item.countryNameFr), item]) .filter(([name]) => Boolean(name)) ); categoryByCode = new Map(parsedPolicy.categoriesData.map((item) => [item.code, item])); countries = geoJson.features.filter( (feature) => feature.properties?.NAME_EN !== "Antarctica" ); countryShadowPaths = countryShadowLayer .selectAll("path") .data(countries, featureKey) .join("path") .attr("class", "country-shadow"); countryPaths = countryLayer .selectAll("path") .data(countries, featureKey) .join("path") .attr("class", "country") .attr("fill", getCountryColor) .attr("tabindex", 0) .on("pointerenter", (event, feature) => { showCountryTooltip(event, feature); }) .on("pointermove", (event) => { moveCountryTooltip(event); }) .on("pointerleave", () => { hideCountryTooltip(); }) .on("mouseenter", (event, feature) => { showCountryTooltip(event, feature); }) .on("mouseover", (event, feature) => { showCountryTooltip(event, feature); }) .on("mouseenter", (event, feature) => { showCountryTooltip(event, feature); }) .on("mousemove", (event) => { moveCountryTooltip(event); }) .on("mouseleave", () => { hideCountryTooltip(); }) .on("focus", (event, feature) => { showCountryTooltip(event, feature); }) .on("click", handleCountryClick) .on("keydown", (event, feature) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); openModalForFeature(feature); } }) .on("blur", () => { hideCountryTooltip(); }); countryPaths .selectAll("title") .data((feature) => [feature]) .join("title") .text((feature) => getCountryLabel(feature)); buildCountryEntries(); renderCountryList(); analyzeMatching(); updateLegend(); updateProjectionAndDrawing(); }) .catch((error) => { mapContainer .append("p") .style("color", "#b91c1c") .style("margin", "1rem") .text("Erreur lors du chargement de la carte ou des données."); // eslint-disable-next-line no-console console.error(error); }); window.addEventListener("resize", () => { updateProjectionAndDrawing(); hideCountryTooltip(); if (window.innerWidth > 760) { closeCountryListModal(); closeLegendOnMobile(); } }); initCountryListEvents(); closeModalButton.addEventListener("click", closeModal); modal.addEventListener("click", (event) => { if (event.target === modal) { closeModal(); } }); document.addEventListener("keydown", (event) => { if (event.key !== "Escape") { return; } if (countryListModal.classList.contains("open")) { closeCountryListModal(); return; } if (legendContainer.classList.contains("mobile-open")) { closeLegendOnMobile(); return; } if (modal.classList.contains("open")) { closeModal(); } });