// World map web component for brewlog stats page. // Map data: Al MacDonald, edited by Fritz Lekschas. License: CC BY-SA 3.0 const WORLD_SVG = ` Author: Al MacDonald Editor: Fritz Lekschas License: CC BY-SA 3.0 ID: ISO 3166-1 or "_[a-zA-Z]" if an ISO code is not available`; customElements.define("world-map", class extends HTMLElement { static get observedAttributes() { return ["data-countries", "data-max", "data-selected"]; } connectedCallback() { this._scheduleRender(); } attributeChangedCallback(name) { if (!this.isConnected) return; if (name === "data-selected") { this._recolor(); } else { this._scheduleRender(); } } _scheduleRender() { if (this._pendingRender) return; this._pendingRender = true; requestAnimationFrame(() => { this._pendingRender = false; this._render(); }); } _parseCountries() { const attr = this.getAttribute("data-countries") || ""; const counts = new Map(); if (attr) { attr.split(",").forEach((pair) => { const [code, count] = pair.split(":"); if (code && count) counts.set(code.trim().toLowerCase(), parseInt(count, 10)); }); } this._counts = counts; this._max = parseInt(this.getAttribute("data-max") || "1", 10) || 1; } _render() { this._parseCountries(); this.innerHTML = ""; const container = document.createElement("div"); container.innerHTML = WORLD_SVG; const svg = container.querySelector("svg"); if (!svg) return; svg.style.width = "100%"; svg.style.height = "auto"; svg.style.display = "block"; this.appendChild(svg); this._recolor(); } _recolor() { const svg = this.querySelector("svg"); if (!svg) return; if (!this._counts) this._parseCountries(); const selected = (this.getAttribute("data-selected") || "").toLowerCase(); const counts = this._counts; const max = this._max; const applyStyle = (el, fill) => { el.style.fill = fill; el.style.stroke = "#9ca3af"; el.style.strokeWidth = "0.3"; }; const colorFor = (code) => { const count = counts.get(code); if (selected) { if (code === selected && count) return "rgba(185, 28, 28, 1)"; return count ? "#d6d3d1" : "#f5f5f4"; } if (count) { const alpha = (0.15 + 0.85 * (count / max)).toFixed(2); return `rgba(220, 38, 38, ${alpha})`; } return "#f5f5f4"; }; svg.querySelectorAll("path[id], g[id]").forEach((el) => { const code = el.id.toLowerCase(); const fill = colorFor(code); if (el.tagName === "g") { el.querySelectorAll("path").forEach((p) => applyStyle(p, fill)); } else { applyStyle(el, fill); } }); } });