| 
									
										
										
										
											2025-09-02 15:17:45 +02:00
										 |  |  | // === CONFIG ===
 | 
					
						
							|  |  |  | const WIKI_API = 'https://wiki.arenos.danielnagel.at/api.php'; // dein Wiki-Host (mit index.php)
 | 
					
						
							|  |  |  | const CATEGORY_TITLE = 'Kategorie:Orte';                          // Hauptkategorie
 | 
					
						
							|  |  |  | const MAX_PAGES = 500;                                            // genug Luft
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Hilfsfunktion: MediaWiki API-URL bauen
 | 
					
						
							|  |  |  | function apiURL(params) { | 
					
						
							|  |  |  |   const u = new URL(WIKI_API); | 
					
						
							|  |  |  |   u.search = new URLSearchParams({ ...params, format: 'json', origin: '*' }).toString(); | 
					
						
							|  |  |  |   return u.toString(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 1) Alle Mitglieder einer Kategorie holen
 | 
					
						
							|  |  |  | async function fetchCategoryMembers(categoryTitle) { | 
					
						
							|  |  |  |   const url = apiURL({ | 
					
						
							|  |  |  |     action: 'query', | 
					
						
							|  |  |  |     list: 'categorymembers', | 
					
						
							|  |  |  |     cmtitle: categoryTitle, | 
					
						
							|  |  |  |     cmlimit: String(MAX_PAGES) | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   const res = await fetch(url); | 
					
						
							|  |  |  |   if (!res.ok) throw new Error(`categorymembers failed: ${res.status}`); | 
					
						
							|  |  |  |   const data = await res.json(); | 
					
						
							|  |  |  |   return data?.query?.categorymembers || []; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 2) Gerendertes HTML einer Seite holen (damit <div class="place-data"> drin ist)
 | 
					
						
							|  |  |  | async function fetchPageHTML(title) { | 
					
						
							|  |  |  |   const url = apiURL({ | 
					
						
							|  |  |  |     action: 'parse', | 
					
						
							|  |  |  |     page: title, | 
					
						
							|  |  |  |     prop: 'text' | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   const res = await fetch(url); | 
					
						
							|  |  |  |   if (!res.ok) throw new Error(`parse failed for ${title}: ${res.status}`); | 
					
						
							|  |  |  |   const data = await res.json(); | 
					
						
							|  |  |  |   const html = data?.parse?.text?.['*'] || ''; | 
					
						
							|  |  |  |   const div = document.createElement('div'); | 
					
						
							|  |  |  |   div.innerHTML = html; | 
					
						
							|  |  |  |   return div; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 3) Daten aus dem versteckten Div extrahieren
 | 
					
						
							|  |  |  | function extractPlaceData(container) { | 
					
						
							|  |  |  |   const node = container.querySelector('.place-data'); | 
					
						
							|  |  |  |   if (!node) return null; | 
					
						
							|  |  |  |   const name = node.getAttribute('data-name') || ''; | 
					
						
							|  |  |  |   const xStr = node.getAttribute('data-x') || ''; | 
					
						
							|  |  |  |   const yStr = node.getAttribute('data-y') || ''; | 
					
						
							|  |  |  |   const desc = node.getAttribute('data-description') || ''; | 
					
						
							|  |  |  |   const link = node.getAttribute('data-link') || ''; | 
					
						
							|  |  |  |   const x = parseFloat(xStr); | 
					
						
							|  |  |  |   const y = parseFloat(yStr); | 
					
						
							|  |  |  |   if (Number.isNaN(x) || Number.isNaN(y)) return null; | 
					
						
							|  |  |  |   return { name, x, y, desc, link }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 4) Marker laden + hinzufügen
 | 
					
						
							|  |  |  | async function loadWikiMarkers(map) { | 
					
						
							|  |  |  |   try { | 
					
						
							|  |  |  |     const pages = await fetchCategoryMembers(CATEGORY_TITLE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Optionales Bounding, falls du später auto-fit willst
 | 
					
						
							|  |  |  |     const layers = []; | 
					
						
							|  |  |  |     for (const p of pages) { | 
					
						
							|  |  |  |       try { | 
					
						
							|  |  |  |         const html = await fetchPageHTML(p.title); | 
					
						
							|  |  |  |         const d = extractPlaceData(html); | 
					
						
							|  |  |  |         if (!d) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Leaflet: Bei CRS.Simple = [y, x]
 | 
					
						
							|  |  |  |         const m = L.marker([d.y, d.x]).addTo(map); | 
					
						
							|  |  |  |         const wikiLink = d.link || `https://wiki.arenos.danielnagel.at/index.php/${encodeURIComponent(p.title)}`; | 
					
						
							|  |  |  |         const popup = `
 | 
					
						
							|  |  |  |           <b>${d.name || p.title}</b><br> | 
					
						
							|  |  |  |           ${d.desc ? `${d.desc}<br>` : ''} | 
					
						
							|  |  |  |           <a href="${wikiLink}" target="_blank" rel="noopener">Open in Wiki</a> | 
					
						
							|  |  |  |         `;
 | 
					
						
							|  |  |  |         m.bindPopup(popup); | 
					
						
							|  |  |  |         layers.push(m); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       } catch (e) { | 
					
						
							|  |  |  |         console.warn('skip page due to parse error:', p.title, e); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   } catch (e) { | 
					
						
							|  |  |  |     console.error('Failed to load wiki markers:', e); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |