Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fcb52a289e | |||
| 6adb83b12b | |||
| 796960bdaf | |||
| 1093b41260 | |||
| 8631452475 | |||
| 1e37b4c2a3 | |||
| 959c78b62d | |||
| 0a84ef4614 | |||
| d8aa1544e8 | |||
| 1ac73eda82 | |||
| 3cc7dbe797 | |||
| 7b2445f704 | |||
| bf5c508db6 | |||
| 82700c4689 | |||
| 3e5c8d26a8 | |||
| 7658a12669 | |||
| fd3df826bc | |||
| da2c3c631d | |||
| b01adad0e0 | |||
| 53100c1f2a | |||
| 6e376b4f13 | |||
| 3c94a65913 | |||
| 8697d32d7b | |||
| 8e936c3fb8 | |||
| 0716ca3d9f | |||
| 69ce35e03e | |||
| d974cf4abe | |||
| 6c5cc0d57b |
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -10,8 +10,7 @@
|
|||
html,body,#map {height:100%;margin:0}
|
||||
.coords{position:absolute;left:6px;bottom:6px;z-index:1000;background:rgba(255,255,255,.85);
|
||||
padding:3px 6px;font-size:12px;border-radius:4px;font-family:system-ui,Segoe UI,Arial}
|
||||
.center-dot{position:absolute;top:50%;left:50%;width:10px;height:10px;background:red;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 2px rgba(255,255,255,.95),0 0 6px rgba(0,0,0,.35);pointer-events:none;z-index:1001}
|
||||
.center-dot{position:absolute;top:50%;left:50%;width:10px;height:10px;background:red;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 2px rgba(255,255,255,.95),0 0 6px rgba(0,0,0,.35);pointer-events:none;z-index:1001}
|
||||
.center-dot{position:absolute;top:50%;left:50%;width:5px;height:5px;background:red;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 2px rgba(255,255,255,.95),0 0 2px rgba(0,0,0,.35);pointer-events:none;z-index:1001}
|
||||
.copy-btn{position:absolute;left:6px;bottom:36px;z-index:1000;background:#ef4444;color:#fff;border:0;border-radius:6px;padding:6px 10px;font:600 12px/1 system-ui,Segoe UI,Arial;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.25)}
|
||||
.copy-btn:active{transform:translateY(1px)}
|
||||
</style>
|
||||
|
|
@ -180,7 +179,8 @@ if (hash.length >= 2) {
|
|||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
<script src="markers.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
115
markers.js
115
markers.js
|
|
@ -1,91 +1,40 @@
|
|||
// === 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
|
||||
let Data_api = "/webhook/data";
|
||||
let freight = null;
|
||||
let testing = true;
|
||||
|
||||
// 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();
|
||||
}
|
||||
let ReqData = { Places: "Stadte"}
|
||||
|
||||
// 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 || [];
|
||||
}
|
||||
// Post to n8n Server to get Data from Grist in JSON format.
|
||||
async function GetMarkerData() {
|
||||
|
||||
// 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);
|
||||
const res = await axios.post(Data_api, ReqData);
|
||||
console.log (res.data);
|
||||
RenderMarkers(res.data);
|
||||
|
||||
// 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);
|
||||
} catch (err) {
|
||||
console.error (err);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Render Map Markers with the Position from Grist Database
|
||||
function RenderMarkers(rows){
|
||||
if (!Array.isArray(rows)) {
|
||||
console.error('Erwarte ein Array, bekam:', rows);
|
||||
return;
|
||||
}
|
||||
|
||||
rows.forEach((row) => {
|
||||
const x = Number(row.X);
|
||||
const y = Number(row.Y);
|
||||
if (!Number.isFinite(x) || !Number.isFinite(y)) return;
|
||||
|
||||
L.marker([y, x]) // [lat, lng] -> [Y, X]
|
||||
.addTo(map)
|
||||
.bindPopup(`<b>${row.Name ?? ''}</b>`);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
GetMarkerData();
|
||||
Loading…
Reference in New Issue
Block a user