Widget:LeafletSMWMap: Unterschied zwischen den Versionen
Aus Altes Köln
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
| Zeile 1: | Zeile 1: | ||
<div id="smwmap" style="width:100%; height:500px;"></div> | <div id="smwmap" style="width:100%; height:500px;"></div> | ||
<link rel="stylesheet" | <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> | ||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> | <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> | ||
<script> | <script> | ||
(async function () { | (async function () { | ||
// Pflichtparameter | |||
const jsonUrl = '{{{json}}}'; | |||
const posProp = '{{{position|Position}}}'; | |||
const typeProp = '{{{type|Schultyp}}}'; | |||
// const | // Optionale Parameter | ||
const iconSpec = '{{{iconMap|}}}'; // "Gymnasium=Marker 13 rot.png;Grundschule=Marker 11 rot.png" | |||
const | const defIcon = '{{{defaultIcon|Marker 11 rot.png}}}'; | ||
// Icon-Mapping "Typ=Dateiname;Typ2=Dateiname2" | |||
// Icon-Mapping "Typ= | |||
const iconMap = {}; | const iconMap = {}; | ||
iconSpec.split(';').forEach(pair => { | if (iconSpec && iconSpec.trim().length) { | ||
iconSpec.split(';').forEach(pair => { | |||
const parts = pair.split('='); | |||
if (parts.length >= 2) { | |||
const k = parts[0].trim(); | |||
} | const v = parts.slice(1).join('=').trim(); // falls Dateiname '=' enthält | ||
} | if (k && v) { | ||
const defaultIcon = | iconMap[k] = '/wiki/Spezial:Dateipfad/' + encodeURIComponent(v); | ||
} | |||
} | |||
}); | |||
} | |||
const defaultIcon = '/wiki/Spezial:Dateipfad/' + encodeURIComponent(defIcon); | |||
// JSON laden (defensiv: erst text, dann parse für bessere Diagnose) | |||
const resp = await fetch(jsonUrl, { credentials: 'same-origin' }); | |||
if (!resp.ok) { | |||
throw new Error('SMW JSON nicht erreichbar: ' + resp.status + ' ' + resp.statusText); | |||
} | |||
const text = await resp.text(); | |||
let data; | |||
try { | |||
data = JSON.parse(text); | |||
} catch (e) { | |||
console.log('JSON-URL:', jsonUrl); | |||
console.log('RAW RESPONSE (erste 500 Zeichen):', text.slice(0, 500)); | |||
throw e; | |||
} | |||
// | // Leaflet initialisieren | ||
const | const map = L.map('smwmap'); | ||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | |||
maxZoom: 19, | |||
attribution: '© OpenStreetMap' | |||
}).addTo(map); | |||
const bounds = []; | |||
const data | // Ergebnisse (SMW ask API) | ||
const results = data && data.query && data.query.results ? data.query.results : {}; | |||
for (const key in results) { | |||
const r = results[key]; | |||
const po = r.printouts || {}; | |||
// Position holen (Array mit {lat, lon}) | |||
if (!Array.isArray(po[posProp]) || !po[posProp].length) continue; | |||
const pos = po[posProp][0]; | |||
if (!pos || typeof pos.lat !== 'number' || typeof pos.lon !== 'number') continue; | |||
// Typ holen | |||
const type = | |||
Array.isArray(po[typeProp]) && po[typeProp].length | |||
? String(po[typeProp][0]) | |||
: ''; | |||
// Icon wählen | |||
const iconUrl = iconMap[type] || defaultIcon; | const iconUrl = iconMap[type] || defaultIcon; | ||
const icon = L.icon({ | const icon = L.icon({ | ||
iconUrl, iconSize:[24,24], iconAnchor:[12,24] | iconUrl: iconUrl, | ||
iconSize: [24, 24], | |||
iconAnchor: [12, 24] | |||
}); | }); | ||
// Popup | |||
const title = r.fulltext || key; | |||
const url = r.fullurl || ('/wiki/' + encodeURIComponent(title)); | |||
L.marker([pos.lat, pos.lon], { icon }) | L.marker([pos.lat, pos.lon], { icon }) | ||
.addTo(map) | .addTo(map) | ||
.bindPopup( | .bindPopup( | ||
`<a href="${ | `<a href="${url}">${title}</a><br><b>${typeProp}:</b> ${type || '-'}` | ||
); | ); | ||
| Zeile 79: | Zeile 95: | ||
} | } | ||
bounds.length | // Zoom/Extent | ||
if (bounds.length) { | |||
map.fitBounds(bounds, { padding: [20, 20] }); | |||
} else { | |||
// Fallback: Köln grob | |||
map.setView([50.94, 6.96], 12); | |||
} | |||
})(); | })(); | ||
</script> | </script> | ||
Version vom 17. Dezember 2025, 19:53 Uhr
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script> (async function () {
// Pflichtparameter
const jsonUrl = '{{{json}}}';
const posProp = 'Position';
const typeProp = 'Schultyp';
// Optionale Parameter const iconSpec = ; // "Gymnasium=Marker 13 rot.png;Grundschule=Marker 11 rot.png" const defIcon = 'Marker 11 rot.png';
// Icon-Mapping "Typ=Dateiname;Typ2=Dateiname2"
const iconMap = {};
if (iconSpec && iconSpec.trim().length) {
iconSpec.split(';').forEach(pair => {
const parts = pair.split('=');
if (parts.length >= 2) {
const k = parts[0].trim();
const v = parts.slice(1).join('=').trim(); // falls Dateiname '=' enthält
if (k && v) {
iconMap[k] = '/wiki/Spezial:Dateipfad/' + encodeURIComponent(v);
}
}
});
}
const defaultIcon = '/wiki/Spezial:Dateipfad/' + encodeURIComponent(defIcon);
// JSON laden (defensiv: erst text, dann parse für bessere Diagnose)
const resp = await fetch(jsonUrl, { credentials: 'same-origin' });
if (!resp.ok) {
throw new Error('SMW JSON nicht erreichbar: ' + resp.status + ' ' + resp.statusText);
}
const text = await resp.text();
let data;
try {
data = JSON.parse(text);
} catch (e) {
console.log('JSON-URL:', jsonUrl);
console.log('RAW RESPONSE (erste 500 Zeichen):', text.slice(0, 500));
throw e;
}
// Leaflet initialisieren
const map = L.map('smwmap');
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
const bounds = [];
// Ergebnisse (SMW ask API)
const results = data && data.query && data.query.results ? data.query.results : {};
for (const key in results) {
const r = results[key];
const po = r.printouts || {};
// Position holen (Array mit {lat, lon})
if (!Array.isArray(po[posProp]) || !po[posProp].length) continue;
const pos = po[posProp][0]; if (!pos || typeof pos.lat !== 'number' || typeof pos.lon !== 'number') continue;
// Typ holen
const type =
Array.isArray(po[typeProp]) && po[typeProp].length
? String(po[typeProp][0])
: ;
// Icon wählen
const iconUrl = iconMap[type] || defaultIcon;
const icon = L.icon({
iconUrl: iconUrl,
iconSize: [24, 24],
iconAnchor: [12, 24]
});
// Popup
const title = r.fulltext || key;
const url = r.fullurl || ('/wiki/' + encodeURIComponent(title));
L.marker([pos.lat, pos.lon], { icon })
.addTo(map)
.bindPopup(
`<a href="${url}">${title}</a>
${typeProp}: ${type || '-'}`
);
bounds.push([pos.lat, pos.lon]); }
// Zoom/Extent
if (bounds.length) {
map.fitBounds(bounds, { padding: [20, 20] });
} else {
// Fallback: Köln grob
map.setView([50.94, 6.96], 12);
}
})(); </script>
