fix: replace buggy JS map with clean responsive table
- No more external CDN dependencies (jsdelivr) - Fully bilingual EN/DE table with country flags - Color-coded status badges - Mobile-responsive - Consistent with privacy policy (no external resources) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
{{ $lang := .Page.Language.Lang }}
|
||||
<style>
|
||||
.csm-container {
|
||||
max-width: 100%;
|
||||
margin: 2rem 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
}
|
||||
.csm-container h3 {
|
||||
text-align: center;
|
||||
@@ -15,55 +15,44 @@
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.csm-map-wrapper {
|
||||
position: relative;
|
||||
background: #f8fafc;
|
||||
border-radius: 12px;
|
||||
padding: 1rem;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
.csm-map-wrapper svg {
|
||||
.csm-table {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.csm-map-wrapper path.country {
|
||||
stroke: #fff;
|
||||
stroke-width: 0.5;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.csm-map-wrapper path.country:hover {
|
||||
opacity: 0.8;
|
||||
stroke-width: 1.5;
|
||||
stroke: #1a365d;
|
||||
}
|
||||
.csm-tooltip {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background: #1a365d;
|
||||
color: #fff;
|
||||
.csm-table th {
|
||||
background: #1e40af;
|
||||
color: white;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 8px;
|
||||
font-size: 0.85rem;
|
||||
max-width: 280px;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
}
|
||||
.csm-tooltip .csm-tt-title {
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.25rem;
|
||||
.csm-table td {
|
||||
padding: 0.65rem 1rem;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
vertical-align: top;
|
||||
}
|
||||
.csm-tooltip .csm-tt-status {
|
||||
.csm-table tr:hover {
|
||||
background: #f0fdf4;
|
||||
}
|
||||
.csm-status {
|
||||
display: inline-block;
|
||||
padding: 0.15rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.9;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.csm-enforced { background: #1e40af; color: white; }
|
||||
.csm-passed { background: #3b82f6; color: white; }
|
||||
.csm-progress { background: #93c5fd; color: #1e3a5f; }
|
||||
.csm-guidelines { background: #dbeafe; color: #1e3a5f; }
|
||||
.csm-legend {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
margin-top: 1rem;
|
||||
margin-top: 1.5rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.csm-legend-item {
|
||||
@@ -77,227 +66,70 @@
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.csm-table { font-size: 0.85rem; }
|
||||
.csm-table th, .csm-table td { padding: 0.5rem; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="csm-container">
|
||||
<h3>{{ if eq .Page.Language.Lang "de" }}Kinderschutzgesetze weltweit{{ else }}Child Protection Laws Worldwide{{ end }}</h3>
|
||||
<p class="csm-subtitle">{{ if eq .Page.Language.Lang "de" }}Klicken Sie auf ein Land für Details{{ else }}Click a country for details{{ end }}</p>
|
||||
<h3>{{ if eq $lang "de" }}Kinderschutzgesetze weltweit{{ else }}Child Protection Laws Worldwide{{ end }}</h3>
|
||||
<p class="csm-subtitle">{{ if eq $lang "de" }}Stand: 2026{{ else }}As of 2026{{ end }}</p>
|
||||
|
||||
<div class="csm-map-wrapper" id="csm-map">
|
||||
<div class="csm-tooltip" id="csm-tooltip">
|
||||
<div class="csm-tt-title" id="csm-tt-title"></div>
|
||||
<div class="csm-tt-status" id="csm-tt-status"></div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="csm-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ if eq $lang "de" }}Land{{ else }}Country{{ end }}</th>
|
||||
<th>{{ if eq $lang "de" }}Gesetz{{ else }}Law{{ end }}</th>
|
||||
<th>{{ if eq $lang "de" }}Status{{ else }}Status{{ end }}</th>
|
||||
<th>{{ if eq $lang "de" }}Details{{ else }}Details{{ end }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ if eq $lang "de" }}
|
||||
<tr><td>🇦🇺 Australien</td><td>Social Media Minimum Age Act 2024</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Social-Media-Verbot für unter 16-Jährige. Bußgelder bis 49,5 Mio. AUD.</td></tr>
|
||||
<tr><td>🇬🇧 Vereinigtes Königreich</td><td>Online Safety Act 2023</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Umfassendes Online-Sicherheitsregime. Altersverifikation erforderlich.</td></tr>
|
||||
<tr><td>🇩🇪 Deutschland</td><td>Jugendschutzgesetz (JuSchG)</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Auf Online-Plattformen ausgeweitet. BzKJ überwacht aktiv die Einhaltung.</td></tr>
|
||||
<tr><td>🇨🇳 China</td><td>Minderjährigenschutzgesetz</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>1 Std./Tag Gaming für Minderjährige. Echtnamen-Verifizierung verpflichtend.</td></tr>
|
||||
<tr><td>🇰🇷 Südkorea</td><td>Jugendschutzgesetz</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Langjähriger Jugendschutzrahmen. Echtnamen-Verifizierung für Online-Dienste.</td></tr>
|
||||
<tr><td>🇮🇪 Irland</td><td>Online Safety and Media Regulation Act</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Coimisiún na Meán reguliert Online-Sicherheit mit verbindlichen Kodizes.</td></tr>
|
||||
<tr><td>🇳🇱 Niederlande</td><td>DSA + Kinderkodex</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Datenschutzbehörde setzt Kinderdatenschutz aktiv durch.</td></tr>
|
||||
<tr><td>🇸🇪 Schweden</td><td>DSA + Nationale Jugendrichtlinien</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>EU-DSA-Rahmen plus nationale Jugendschutzrichtlinien.</td></tr>
|
||||
<tr><td>🇫🇷 Frankreich</td><td>Loi SREN</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Altersverifikation für Erwachseneninhalte. Social Media ab 15.</td></tr>
|
||||
<tr><td>🇧🇷 Brasilien</td><td>ECA Digital</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Lootbox-Verbot für Minderjährige. Altersgerechtes Design.</td></tr>
|
||||
<tr><td>🇮🇳 Indien</td><td>DPDP Act 2023</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Verifizierbare elterliche Einwilligung für unter 18-Jährige.</td></tr>
|
||||
<tr><td>🇮🇹 Italien</td><td>DSA + Einwilligungsgesetz</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Digitales Einwilligungsalter auf 14 festgelegt.</td></tr>
|
||||
<tr><td>🇪🇸 Spanien</td><td>Organisches Kinderschutzgesetz</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Umfassendes digitales Kinderschutzgesetz.</td></tr>
|
||||
<tr><td>🇳🇴 Norwegen</td><td>Social-Media-Altersgrenze</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Geplante Altersgrenze von 15 Jahren.</td></tr>
|
||||
<tr><td>🇺🇸 Vereinigte Staaten</td><td>KOSA + COPPA-Update</td><td><span class="csm-status csm-progress">In Bearbeitung</span></td><td>KOSA im Senat angenommen. COPPA-Update bis Apr. 2026.</td></tr>
|
||||
<tr><td>🇨🇦 Kanada</td><td>Online Harms Act (C-63)</td><td><span class="csm-status csm-progress">In Bearbeitung</span></td><td>Sorgfaltspflicht für Plattformen in Prüfung.</td></tr>
|
||||
<tr><td>🇯🇵 Japan</td><td>Regulierung der Kontaktaufnahme</td><td><span class="csm-status csm-guidelines">Richtlinien</span></td><td>Selbstregulierung der Plattformen empfohlen.</td></tr>
|
||||
{{ else }}
|
||||
<tr><td>🇦🇺 Australia</td><td>Social Media Minimum Age Act 2024</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Social media ban for under-16s. Fines up to AUD 49.5M.</td></tr>
|
||||
<tr><td>🇬🇧 United Kingdom</td><td>Online Safety Act 2023</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Comprehensive online safety regime. Age verification required.</td></tr>
|
||||
<tr><td>🇩🇪 Germany</td><td>Jugendschutzgesetz (JuSchG)</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Youth Protection Act extended to online platforms. BzKJ monitoring.</td></tr>
|
||||
<tr><td>🇨🇳 China</td><td>Minor Protection Law</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>1hr/day gaming for minors. Real-name verification mandatory.</td></tr>
|
||||
<tr><td>🇰🇷 South Korea</td><td>Youth Protection Act</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Long-standing youth protection framework. Real-name verification.</td></tr>
|
||||
<tr><td>🇮🇪 Ireland</td><td>Online Safety and Media Regulation Act</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Coimisiún na Meán regulates online safety with binding codes.</td></tr>
|
||||
<tr><td>🇳🇱 Netherlands</td><td>DSA + Children's Code</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Dutch DPA actively enforcing children's data protection.</td></tr>
|
||||
<tr><td>🇸🇪 Sweden</td><td>DSA + National Youth Guidelines</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>EU DSA framework plus national youth protection guidelines.</td></tr>
|
||||
<tr><td>🇫🇷 France</td><td>Loi SREN (Digital Majority Act)</td><td><span class="csm-status csm-passed">Passed</span></td><td>Age verification mandate. Social media age 15 with consent.</td></tr>
|
||||
<tr><td>🇧🇷 Brazil</td><td>ECA Digital</td><td><span class="csm-status csm-passed">Passed</span></td><td>Loot box ban for minors. Age-appropriate design requirements.</td></tr>
|
||||
<tr><td>🇮🇳 India</td><td>DPDP Act 2023</td><td><span class="csm-status csm-passed">Passed</span></td><td>Verifiable parental consent for under-18s.</td></tr>
|
||||
<tr><td>🇮🇹 Italy</td><td>DSA + Parental Consent Law</td><td><span class="csm-status csm-passed">Passed</span></td><td>Digital age of consent set to 14.</td></tr>
|
||||
<tr><td>🇪🇸 Spain</td><td>Child Protection in Digital Environments</td><td><span class="csm-status csm-passed">Passed</span></td><td>Comprehensive child digital protection law.</td></tr>
|
||||
<tr><td>🇳🇴 Norway</td><td>Social Media Age Limit</td><td><span class="csm-status csm-passed">Passed</span></td><td>Proposed social media age limit of 15.</td></tr>
|
||||
<tr><td>🇺🇸 United States</td><td>KOSA + COPPA Update</td><td><span class="csm-status csm-progress">In Progress</span></td><td>KOSA passed Senate 91-3. COPPA update by Apr 2026.</td></tr>
|
||||
<tr><td>🇨🇦 Canada</td><td>Online Harms Act (C-63)</td><td><span class="csm-status csm-progress">In Progress</span></td><td>Proposed duty of care for platforms.</td></tr>
|
||||
<tr><td>🇯🇵 Japan</td><td>Act on Regulation of Soliciting Children</td><td><span class="csm-status csm-guidelines">Guidelines</span></td><td>Platform self-regulation encouraged.</td></tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="csm-legend">
|
||||
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#1e40af"></div>{{ if eq .Page.Language.Lang "de" }}Gesetz in Kraft{{ else }}Law Enforced{{ end }}</div>
|
||||
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#3b82f6"></div>{{ if eq .Page.Language.Lang "de" }}Gesetzgebung verabschiedet{{ else }}Legislation Passed{{ end }}</div>
|
||||
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#93c5fd"></div>{{ if eq .Page.Language.Lang "de" }}In Bearbeitung{{ else }}In Progress{{ end }}</div>
|
||||
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#dbeafe"></div>{{ if eq .Page.Language.Lang "de" }}Richtlinien / Selbstregulierung{{ else }}Guidelines / Self-Regulation{{ end }}</div>
|
||||
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#e2e8f0"></div>{{ if eq .Page.Language.Lang "de" }}Keine spezifische Gesetzgebung{{ else }}No Specific Legislation{{ end }}</div>
|
||||
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#1e40af"></div>{{ if eq $lang "de" }}Gesetz in Kraft{{ else }}Law Enforced{{ end }}</div>
|
||||
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#3b82f6"></div>{{ if eq $lang "de" }}Verabschiedet{{ else }}Passed{{ end }}</div>
|
||||
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#93c5fd"></div>{{ if eq $lang "de" }}In Bearbeitung{{ else }}In Progress{{ end }}</div>
|
||||
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#dbeafe"></div>{{ if eq $lang "de" }}Richtlinien{{ else }}Guidelines{{ end }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var lang = {{ .Page.Language.Lang | jsonify }};
|
||||
|
||||
// Country data: status, law name, details
|
||||
var data = {
|
||||
"AU": {
|
||||
status: "enforced",
|
||||
en: { name: "Australia", law: "Social Media Minimum Age Act 2024", detail: "Social media ban for under-16s. Enforced Dec 2025. Fines up to AUD 49.5M." },
|
||||
de: { name: "Australien", law: "Social Media Minimum Age Act 2024", detail: "Social-Media-Verbot für unter 16-Jährige. In Kraft seit Dez. 2025. Bußgelder bis 49,5 Mio. AUD." }
|
||||
},
|
||||
"US": {
|
||||
status: "in_progress",
|
||||
en: { name: "United States", law: "KOSA + COPPA Update", detail: "KOSA passed Senate 91-3, in House committee. COPPA update requires compliance by Apr 2026." },
|
||||
de: { name: "Vereinigte Staaten", law: "KOSA + COPPA-Update", detail: "KOSA im Senat mit 91-3 angenommen, im Ausschuss des Repräsentantenhauses. COPPA-Update erfordert Konformität bis Apr. 2026." }
|
||||
},
|
||||
"GB": {
|
||||
status: "enforced",
|
||||
en: { name: "United Kingdom", law: "Online Safety Act 2023 + Age Appropriate Design Code", detail: "Comprehensive online safety regime. Age verification required. Ofcom enforcement active." },
|
||||
de: { name: "Vereinigtes Königreich", law: "Online Safety Act 2023 + Age Appropriate Design Code", detail: "Umfassendes Online-Sicherheitsregime. Altersverifikation erforderlich. Ofcom-Durchsetzung aktiv." }
|
||||
},
|
||||
"DE": {
|
||||
status: "enforced",
|
||||
en: { name: "Germany", law: "Jugendschutzgesetz (JuSchG)", detail: "Youth Protection Act extended to online platforms. BzKJ actively monitoring compliance." },
|
||||
de: { name: "Deutschland", law: "Jugendschutzgesetz (JuSchG)", detail: "Jugendschutzgesetz auf Online-Plattformen ausgeweitet. BzKJ überwacht aktiv die Einhaltung." }
|
||||
},
|
||||
"FR": {
|
||||
status: "passed",
|
||||
en: { name: "France", law: "Digital Majority Act (Loi SREN)", detail: "Age verification mandate for adult content. Social media age 15 with parental consent." },
|
||||
de: { name: "Frankreich", law: "Loi SREN (Digitale Volljährigkeit)", detail: "Altersverifikation für Erwachseneninhalte. Social Media ab 15 mit elterlicher Zustimmung." }
|
||||
},
|
||||
"IE": {
|
||||
status: "enforced",
|
||||
en: { name: "Ireland", law: "Online Safety and Media Regulation Act", detail: "Coimisiún na Meán regulates online safety. Binding online safety codes for platforms." },
|
||||
de: { name: "Irland", law: "Online Safety and Media Regulation Act", detail: "Coimisiún na Meán reguliert Online-Sicherheit. Verbindliche Kodizes für Plattformen." }
|
||||
},
|
||||
"BR": {
|
||||
status: "passed",
|
||||
en: { name: "Brazil", law: "ECA Digital (Digital Child Statute)", detail: "Loot box ban for minors. Age-appropriate design requirements. Enhanced child data protection." },
|
||||
de: { name: "Brasilien", law: "ECA Digital", detail: "Lootbox-Verbot für Minderjährige. Altersgerechtes Design. Verstärkter Datenschutz für Kinder." }
|
||||
},
|
||||
"IN": {
|
||||
status: "passed",
|
||||
en: { name: "India", law: "DPDP Act 2023", detail: "Digital Personal Data Protection Act. Verifiable parental consent for under-18s." },
|
||||
de: { name: "Indien", law: "DPDP Act 2023", detail: "Gesetz zum Schutz personenbezogener Daten. Verifizierbare elterliche Einwilligung für unter 18-Jährige." }
|
||||
},
|
||||
"KR": {
|
||||
status: "enforced",
|
||||
en: { name: "South Korea", law: "Youth Protection Act + Game Shutdown Law", detail: "Long-standing youth protection framework. Real-name verification for online services." },
|
||||
de: { name: "Südkorea", law: "Jugendschutzgesetz + Game Shutdown Law", detail: "Langjähriger Jugendschutzrahmen. Echtnamen-Verifizierung für Online-Dienste." }
|
||||
},
|
||||
"JP": {
|
||||
status: "guidelines",
|
||||
en: { name: "Japan", law: "Act on Regulation of Soliciting Children", detail: "Platform self-regulation encouraged. Industry guidelines for age-appropriate services." },
|
||||
de: { name: "Japan", law: "Gesetz zur Regulierung der Kontaktaufnahme mit Kindern", detail: "Selbstregulierung der Plattformen empfohlen. Branchenrichtlinien für altersgerechte Dienste." }
|
||||
},
|
||||
"CN": {
|
||||
status: "enforced",
|
||||
en: { name: "China", law: "Minor Protection Law + Gaming Restrictions", detail: "Strict limits: 1hr/day gaming for minors. Real-name verification. Content filtering mandatory." },
|
||||
de: { name: "China", law: "Minderjährigenschutzgesetz + Gaming-Beschränkungen", detail: "Strenge Grenzen: 1 Std./Tag Gaming für Minderjährige. Echtnamen-Verifizierung. Inhaltsfilterung verpflichtend." }
|
||||
},
|
||||
"CA": {
|
||||
status: "in_progress",
|
||||
en: { name: "Canada", law: "Online Harms Act (Bill C-63)", detail: "Proposed duty of care for platforms. Age verification requirements under consideration." },
|
||||
de: { name: "Kanada", law: "Online Harms Act (Bill C-63)", detail: "Vorgeschlagene Sorgfaltspflicht für Plattformen. Altersverifikation in Prüfung." }
|
||||
},
|
||||
"NL": {
|
||||
status: "enforced",
|
||||
en: { name: "Netherlands", law: "DSA + Children's Code (AP)", detail: "Dutch DPA actively enforcing children's data protection. TikTok fined EUR 750K." },
|
||||
de: { name: "Niederlande", law: "DSA + Kinderkodex (AP)", detail: "Niederländische Datenschutzbehörde setzt Kinderdatenschutz aktiv durch. TikTok mit 750.000 EUR bestraft." }
|
||||
},
|
||||
"IT": {
|
||||
status: "passed",
|
||||
en: { name: "Italy", law: "DSA + Parental Consent Law", detail: "Digital age of consent set to 14. Garante actively enforcing children's privacy rights." },
|
||||
de: { name: "Italien", law: "DSA + Einwilligungsgesetz", detail: "Digitales Einwilligungsalter auf 14 festgelegt. Garante setzt Kinderdatenschutz aktiv durch." }
|
||||
},
|
||||
"ES": {
|
||||
status: "passed",
|
||||
en: { name: "Spain", law: "Organic Law on Child Protection in Digital Environments", detail: "Comprehensive child digital protection law. Age verification and content moderation required." },
|
||||
de: { name: "Spanien", law: "Organisches Gesetz zum Kinderschutz in digitalen Umgebungen", detail: "Umfassendes digitales Kinderschutzgesetz. Altersverifikation und Inhaltsmoderation erforderlich." }
|
||||
},
|
||||
"SE": {
|
||||
status: "enforced",
|
||||
en: { name: "Sweden", law: "DSA + National Board for Youth Affairs", detail: "EU DSA framework plus national youth protection guidelines. Active enforcement." },
|
||||
de: { name: "Schweden", law: "DSA + Nationale Jugendbehörde", detail: "EU-DSA-Rahmen plus nationale Jugendschutzrichtlinien. Aktive Durchsetzung." }
|
||||
},
|
||||
"NO": {
|
||||
status: "passed",
|
||||
en: { name: "Norway", law: "Social Media Age Limit (proposed 15)", detail: "Proposed social media age limit of 15. Following Australia's model." },
|
||||
de: { name: "Norwegen", law: "Social-Media-Altersgrenze (geplant: 15)", detail: "Geplante Social-Media-Altersgrenze von 15 Jahren. Folgt Australiens Modell." }
|
||||
}
|
||||
};
|
||||
|
||||
var colors = {
|
||||
enforced: "#1e40af",
|
||||
passed: "#3b82f6",
|
||||
in_progress: "#93c5fd",
|
||||
guidelines: "#dbeafe",
|
||||
none: "#e2e8f0"
|
||||
};
|
||||
|
||||
// Fetch a lightweight world TopoJSON and render via inline SVG
|
||||
// Using Natural Earth 110m simplified for fast loading
|
||||
var mapEl = document.getElementById("csm-map");
|
||||
var tooltip = document.getElementById("csm-tooltip");
|
||||
var ttTitle = document.getElementById("csm-tt-title");
|
||||
var ttStatus = document.getElementById("csm-tt-status");
|
||||
|
||||
// Load world GeoJSON (tiny, ~50KB)
|
||||
fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json")
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(topo) {
|
||||
// We need topojson-client to convert
|
||||
var script = document.createElement("script");
|
||||
script.src = "https://cdn.jsdelivr.net/npm/topojson-client@3/dist/topojson-client.min.js";
|
||||
script.onload = function() {
|
||||
renderMap(topo);
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
})
|
||||
.catch(function() {
|
||||
mapEl.innerHTML += '<p style="text-align:center;color:#999;padding:2rem;">Map could not be loaded. Please check your internet connection.</p>';
|
||||
});
|
||||
|
||||
// ISO 3166-1 numeric to alpha-2 mapping (key countries)
|
||||
var numToAlpha = {
|
||||
"36":"AU","76":"BR","124":"CA","156":"CN","250":"FR","276":"DE","356":"IN",
|
||||
"372":"IE","380":"IT","392":"JP","410":"KR","528":"NL","578":"NO","724":"ES",
|
||||
"752":"SE","826":"GB","840":"US"
|
||||
};
|
||||
|
||||
function renderMap(topo) {
|
||||
var countries = topojson.feature(topo, topo.objects.countries);
|
||||
// Simple equirectangular projection
|
||||
var w = 960, h = 480;
|
||||
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
svg.setAttribute("viewBox", "0 0 " + w + " " + h);
|
||||
svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
||||
|
||||
countries.features.forEach(function(f) {
|
||||
var id = f.id;
|
||||
var alpha2 = numToAlpha[id] || "";
|
||||
var info = data[alpha2];
|
||||
var color = info ? colors[info.status] : colors.none;
|
||||
|
||||
var paths = geoToPath(f.geometry, w, h);
|
||||
paths.forEach(function(d) {
|
||||
var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||||
path.setAttribute("d", d);
|
||||
path.setAttribute("fill", color);
|
||||
path.setAttribute("class", "country");
|
||||
path.setAttribute("data-id", alpha2);
|
||||
|
||||
if (info) {
|
||||
path.addEventListener("mouseenter", function(e) {
|
||||
var loc = info[lang] || info.en;
|
||||
ttTitle.textContent = loc.name + " — " + loc.law;
|
||||
ttStatus.textContent = loc.detail;
|
||||
tooltip.style.display = "block";
|
||||
});
|
||||
path.addEventListener("mousemove", function(e) {
|
||||
var rect = mapEl.getBoundingClientRect();
|
||||
var x = e.clientX - rect.left + 10;
|
||||
var y = e.clientY - rect.top - 10;
|
||||
if (x + 280 > rect.width) x = x - 300;
|
||||
tooltip.style.left = x + "px";
|
||||
tooltip.style.top = y + "px";
|
||||
});
|
||||
path.addEventListener("mouseleave", function() {
|
||||
tooltip.style.display = "none";
|
||||
});
|
||||
}
|
||||
svg.appendChild(path);
|
||||
});
|
||||
});
|
||||
|
||||
mapEl.insertBefore(svg, tooltip);
|
||||
}
|
||||
|
||||
// Minimal equirectangular geo→SVG path converter
|
||||
function geoToPath(geom, w, h) {
|
||||
var paths = [];
|
||||
var coords = [];
|
||||
if (geom.type === "Polygon") coords = [geom.coordinates];
|
||||
else if (geom.type === "MultiPolygon") coords = geom.coordinates;
|
||||
|
||||
coords.forEach(function(poly) {
|
||||
poly.forEach(function(ring) {
|
||||
var d = "";
|
||||
ring.forEach(function(pt, i) {
|
||||
var x = (pt[0] + 180) / 360 * w;
|
||||
var y = (90 - pt[1]) / 180 * h;
|
||||
d += (i === 0 ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1);
|
||||
});
|
||||
d += "Z";
|
||||
paths.push(d);
|
||||
});
|
||||
});
|
||||
return paths;
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user