From 2bc83a17dd589aaccc77a97ff7e46a9e93eb3d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Tue, 17 Feb 2026 15:20:23 +0100 Subject: [PATCH] fix: handle SVG group elements in world map for multi-path countries The SVG world map uses group elements for countries with complex shapes (US, CN, RU, GB, etc.), but the JS only queried elements, causing 36 countries to be missing from the map. Also removes the SVG element that was overriding the custom tooltip. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --- internal/web/static/dashboard.js | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/internal/web/static/dashboard.js b/internal/web/static/dashboard.js index 3e0aaec..d55ba14 100644 --- a/internal/web/static/dashboard.js +++ b/internal/web/static/dashboard.js @@ -158,9 +158,14 @@ var svg = container.querySelector('svg'); if (!svg) return; - var paths = svg.querySelectorAll('path[id]'); - paths.forEach(function(path) { - var id = path.id.toLowerCase(); + // Remove SVG title to prevent browser native tooltip + var svgTitle = svg.querySelector('title'); + if (svgTitle) svgTitle.remove(); + + // Select both <path id="xx"> and <g id="xx"> country elements + var elements = svg.querySelectorAll('path[id], g[id]'); + elements.forEach(function(el) { + var id = el.id.toLowerCase(); if (id.charAt(0) === '_') return; // skip non-country paths var count = lookup[id]; @@ -169,26 +174,34 @@ var r = Math.round(30 + intensity * 69); // 30 -> 99 var g = Math.round(30 + intensity * 72); // 30 -> 102 var b = Math.round(62 + intensity * 179); // 62 -> 241 - path.style.fill = 'rgb(' + r + ',' + g + ',' + b + ')'; + var color = 'rgb(' + r + ',' + g + ',' + b + ')'; + // For <g> elements, color child paths; for <path>, color directly + if (el.tagName.toLowerCase() === 'g') { + el.querySelectorAll('path').forEach(function(p) { + p.style.fill = color; + }); + } else { + el.style.fill = color; + } } - path.addEventListener('mouseenter', function(e) { + el.addEventListener('mouseenter', function(e) { var cc = id.toUpperCase(); var n = lookup[id] || 0; tooltip.textContent = cc + ': ' + n.toLocaleString() + ' attempts'; tooltip.style.display = 'block'; }); - path.addEventListener('mousemove', function(e) { + el.addEventListener('mousemove', function(e) { tooltip.style.left = (e.clientX + 12) + 'px'; tooltip.style.top = (e.clientY - 10) + 'px'; }); - path.addEventListener('mouseleave', function() { + el.addEventListener('mouseleave', function() { tooltip.style.display = 'none'; }); - path.addEventListener('click', function() { + el.addEventListener('click', function() { var input = document.querySelector('#filter-form input[name="country"]'); if (input) { input.value = id.toUpperCase(); @@ -196,7 +209,7 @@ } }); - path.style.cursor = 'pointer'; + el.style.cursor = 'pointer'; }); }