Das Projekt verwendet drei verschiedene interaktive Leaflet-Karten, die jeweils unterschiedliche Daten visualisieren. Alle Karten folgen einem ähnlichen Architekturmuster, sind aber auf unterschiedlichen Seiten eingebunden, um ID-Konflikte zu vermeiden.
- Seite:
docs/variation/map_countries.md - JavaScript:
docs/assets/javascripts/map_countries.js - Daten (JSON):
docs/assets/maps/countries.json - CSS:
docs/assets/stylesheets/overrides.css(Scope:[data-map="variation"])
<div id="map-container" data-map="variation">
<button id="fullscreen-btn" onclick="toggleFullscreenVariation()">
<span class="material-icons">fullscreen</span>
</button>
<div id="mapid"></div>
</div>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="/assets/javascripts/map_countries.js"></script>// DOMContentLoaded Event Listener
document.addEventListener('DOMContentLoaded', () => {
// Prüft, ob #mapid existiert
if (document.getElementById('mapid')) {
const variationMap = L.map('mapid');
// ... Karteninitialisierung
window.variationMap = variationMap;
}
});
// Vollbild-Toggle (global verfügbar)
function toggleFullscreenVariation() {
const container = document.getElementById('map-container');
const btn = document.getElementById('fullscreen-btn');
// ...
}[
{
"Land": "Mexiko",
"Hauptstadt": "Mexiko-Stadt",
"Koordinaten": [19.4326, -99.1332],
"GDN": 124781373,
"Anteil_GDN": 25.1
}
]- Responsive Ansicht (Mobile: Lateinamerika-fokussiert, Desktop: Atlantik-Übersicht)
- CircleMarker mit dynamischer Größe basierend auf GDN (Anzahl Sprecher:innen)
- Farbintensität basierend auf Anteil an Hispanophonie
- Hover-Tooltips mit Land, Hauptstadt, Sprecherzahl, Anteil
- Vollbildmodus
- Seite:
docs/herkunftssprachen.md - JavaScript:
docs/assets/javascripts/map.js - Daten (JSON):
docs/assets/maps/herkunftssprachen.json - CSS:
docs/assets/stylesheets/overrides.css(Standard-Styles)
<div id="map-container" data-map="herkunft">
<button id="fullscreen-btn" onclick="toggleFullscreen()">
<span class="material-icons">fullscreen</span>
</button>
<div id="mapid"></div>
</div>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">Wichtig: Das Script map.js wird NICHT in der Markdown-Datei eingebunden, sondern global in mkdocs.yml!
// KEIN DOMContentLoaded! Code läuft sofort
const herkunftContainer = document.querySelector('[data-map="herkunft"]');
if (herkunftContainer) {
function toggleFullscreen() {
const container = herkunftContainer;
const btn = container.querySelector('#fullscreen-btn');
// ...
}
window.toggleFullscreen = toggleFullscreen;
const mapEl = herkunftContainer.querySelector('#mapid');
if (mapEl) {
const map = L.map(mapEl).setView([45, 15], 3);
window.herkunftMap = map;
// ...
}
}[
{
"sprache": "Türkisch",
"sprachfamilie": "Turksprachen",
"herkunft": ["Türkei"],
"koordinaten": [[39.9334, 32.8597]],
"farbe": "#e74c3c"
}
]- Mehrere Koordinaten pro Sprache möglich
- Farbcodierung nach Sprachfamilie
- Popups mit Sprache, Sprachfamilie, Herkunft
- Vollbildmodus
- Seite:
docs/variation/variation_grammatik.md - JavaScript:
docs/assets/javascripts/map_variation_tempora.js - Daten (JSON):
docs/assets/maps/variation_tempora.json - CSS:
docs/assets/stylesheets/overrides.css(Scope:[data-map="variation_tempora"])
<div id="map-container" data-map="variation_tempora">
<button id="fullscreen-btn" onclick="toggleFullscreenTempora()">
<span class="material-icons">fullscreen</span>
</button>
<div id="mapid"></div>
</div>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="/assets/javascripts/map_variation_tempora.js"></script>// DOMContentLoaded Event Listener (wie map.js, aber mit DOMContentLoaded)
document.addEventListener('DOMContentLoaded', () => {
const temporaContainer = document.querySelector('[data-map="variation_tempora"]');
if (!temporaContainer) return;
function toggleFullscreenTempora() {
const container = temporaContainer;
const btn = container.querySelector('#fullscreen-btn');
// ...
}
window.toggleFullscreenTempora = toggleFullscreenTempora;
const mapEl = temporaContainer.querySelector('#mapid');
if (mapEl) {
const map = L.map(mapEl);
window.temporaMap = map;
// ...
}
});[
{
"Land": "Spanien (Zentrum)",
"Hauptstadt": "Madrid",
"Koordinaten": [40.416775, -3.70379],
"Perfecto compuesto": "häufig bei Jetztbezug (hoy, esta mañana)",
"Perfecto simple": "für abgeschlossene Vergangenheit",
"Verwendung der Tempora": "Prototypischer Wert"
}
]- Responsive Ansicht (Mobile: Lateinamerika-fokussiert, Desktop: Atlantik-Übersicht)
- Einheitliche Marker-Größe (keine Skalierung nach Daten)
- Farbcodierung nach Verwendungsmuster (optional, vorbereitet)
- Popups zeigen nur gefüllte Felder an
- Vollbildmodus
extra_css:
- assets/stylesheets/overrides.css
- https://unpkg.com/leaflet/dist/leaflet.css
extra_javascript:
- https://unpkg.com/leaflet/dist/leaflet.js
- assets/javascripts/map.js # Nur für Herkunftssprachen-Karte!Wichtig:
- Leaflet.js wird global geladen
map.js(Herkunftssprachen) wird global geladenmap_countries.jsundmap_variation_tempora.jswerden in den jeweiligen Markdown-Dateien eingebunden
Alle Karten verwenden die gleichen generischen IDs (map-container, fullscreen-btn, mapid), aber:
- Sie sind auf verschiedenen Seiten → kein Konflikt, da nur eine Seite gleichzeitig geladen ist
- Jeder Container hat ein eindeutiges
data-mapAttribut zur CSS-Isolierung:data-map="variation"für Hispanophoniedata-map="herkunft"für Herkunftssprachendata-map="variation_tempora"für Tempora-Variation
Es gibt zwei Muster:
Pattern 1: DOMContentLoaded mit getElementById (map_countries.js)
document.addEventListener('DOMContentLoaded', () => {
if (document.getElementById('mapid')) {
const map = L.map('mapid');
// ...
}
});Pattern 2: querySelector auf Container (map.js, map_variation_tempora.js)
document.addEventListener('DOMContentLoaded', () => {
const container = document.querySelector('[data-map="xyz"]');
if (!container) return;
const mapEl = container.querySelector('#mapid');
if (mapEl) {
const map = L.map(mapEl);
// ...
}
});Pattern 2 ist robuster, da es:
- Gezielt nach dem Container mit
data-mapAttribut sucht - Innerhalb des Containers nach Elementen sucht (kein globales getElementById)
- Keine Konflikte verursacht, selbst wenn mehrere Karten auf einer Seite wären
Styles sind über das data-map Attribut isoliert:
/* Nur für Hispanophonie-Karte */
#map-container[data-map="variation"] {
height: 650px;
}
/* Nur für Tempora-Karte */
#map-container[data-map="variation_tempora"] {
height: 500px;
}Jede Karte hat ihre eigene global verfügbare Toggle-Funktion:
toggleFullscreenVariation()für HispanophonietoggleFullscreen()für HerkunftssprachentoggleFullscreenTempora()für Tempora
Diese sind global, damit sie von onclick Attributen aufgerufen werden können.
Jede Karte speichert ihre Instanz global:
window.variationMapfür Hispanophoniewindow.herkunftMapfür Herkunftssprachenwindow.temporaMapfür Tempora
Wird für invalidateSize() beim Fullscreen-Toggle benötigt.
Alle Karten verwenden Hover-Tooltips mit Click-Toggle:
marker.bindPopup(popupHtml, {
autoPan: true,
keepInView: true,
offset: [0, -radius],
maxWidth: 300
});
marker.on('mouseover', function() { this.openPopup(); });
marker.on('mouseout', function() { this.closePopup(); });
marker.on('click', function() {
if (this.isPopupOpen()) this.closePopup();
else this.openPopup();
});<div class="popup-sprachenkarte">
<div class="popup-title">Land/Region</div>
<div class="popup-hauptstadt">Hauptstadt</div>
<div class="popup-line">
<span class="popup-label">Label:</span>
<span class="popup-value">Wert</span>
</div>
</div>Wichtig: Nur gefüllte Felder werden angezeigt (bedingte Template-Logik mit ${field ? ... : ''}).
Ursache: Leaflet.js noch nicht geladen
Lösung: Code in DOMContentLoaded Event-Listener wrappen
Ursache: Mehrere Elemente mit gleicher ID auf verschiedenen Seiten
Lösung: Verwende querySelector auf Container mit data-map Attribut
Checks:
- Ist der Container vorhanden? (
document.querySelector('[data-map="xyz"]')) - Ist Leaflet.js geladen? (vor dem eigenen Script in mkdocs.yml)
- Hat der Container eine Höhe? (CSS prüfen)
- Console-Fehler prüfen
Info: Harmlose Warnung von Leaflet CDN, kann ignoriert werden Optional: Leaflet lokal hosten statt CDN
- JSON-Datei erstellen in
docs/assets/maps/ - JavaScript-Datei erstellen in
docs/assets/javascripts/- Pattern 2 verwenden (querySelector auf Container)
- Eindeutigen
data-mapWert wählen - Eindeutigen Toggle-Funktionsnamen wählen
- Eindeutige window.mapName Instanz wählen
- CSS hinzufügen in
overrides.cssmit[data-map="xyz"]Scope - Markdown einbinden:
<div id="map-container" data-map="xyz"> <button id="fullscreen-btn" onclick="toggleFullscreenXyz()"> <span class="material-icons">fullscreen</span> </button> <div id="mapid"></div> </div> <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" /> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <script src="/assets/javascripts/map_xyz.js"></script>
docs/
├── assets/
│ ├── javascripts/
│ │ ├── map.js # Herkunftssprachen (global in mkdocs.yml)
│ │ ├── map_countries.js # Hispanophonie (lokal in MD)
│ │ └── map_variation_tempora.js # Tempora (lokal in MD)
│ ├── maps/
│ │ ├── countries.json # Hispanophonie-Daten
│ │ ├── herkunftssprachen.json # Herkunftssprachen-Daten
│ │ └── variation_tempora.json # Tempora-Daten
│ └── stylesheets/
│ └── overrides.css # Alle Karten-Styles
├── variation/
│ ├── map_countries.md # Hispanophonie-Seite
│ └── variation_grammatik.md # Tempora-Seite (Karte integriert)
└── herkunftssprachen.md # Herkunftssprachen-Seite
mkdocs.yml # Globale Leaflet-Einbindung
Stand: 16.12.2025
Autor: Felix Tacke