Overpass Monitor

Overpass QL
Query presets
Status
Ready.
/* ================= CONFIG ================= */ const DEFAULT_ENDPOINT = "http://192.168.222.66/api/interpreter"; endpoint.value = DEFAULT_ENDPOINT; /* ================= MAP ================= */ const map = L.map("map").setView([-37.8136, 144.9631], 12); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { maxZoom: 19, attribution: "© OpenStreetMap contributors" }).addTo(map); const markerLayer = L.layerGroup().addTo(map); /* ================= UTIL ================= */ const presets = { brunswick: { center: [-37.767, 144.961], zoom: 15, query: () => businessQuery( "-37.79,144.93,-37.74,144.99" // Brunswick approx bbox ) }, cafes: { query: () => `[out:json][timeout:60]; ( node["amenity"="cafe"](${boundsToBBox(map.getBounds())}); way["amenity"="cafe"](${boundsToBBox(map.getBounds())}); relation["amenity"="cafe"](${boundsToBBox(map.getBounds())}); ); out tags center;` }, fuel: { query: () => `[out:json][timeout:60]; ( node["amenity"="fuel"](${boundsToBBox(map.getBounds())}); way["amenity"="fuel"](${boundsToBBox(map.getBounds())}); relation["amenity"="fuel"](${boundsToBBox(map.getBounds())}); ); out tags center;` } }; function log(msg) { status.textContent = `[${new Date().toLocaleTimeString()}] ${msg}\n` + status.textContent; } function boundsToBBox(bounds) { const sw = bounds.getSouthWest(); const ne = bounds.getNorthEast(); return `${sw.lat},${sw.lng},${ne.lat},${ne.lng}`; } function esc(s) { return String(s ?? "").replace(/[&<>"']/g, m => ({ "&":"&","<":"<",">":">",'"':""","'":"'" }[m]) ); } function address(tags) { const a = []; if (tags["addr:housenumber"]) a.push(tags["addr:housenumber"]); if (tags["addr:street"]) a.push(tags["addr:street"]); const l1 = a.join(" "); const l2 = [tags["addr:suburb"], tags["addr:postcode"]].filter(Boolean).join(" "); return [l1, l2].filter(Boolean).join(", "); } /* ================= QUERY BUILDER ================= */ function businessQuery(bbox) { return `[out:json][timeout:90]; ( node["shop"](${bbox}); way["shop"](${bbox}); relation["shop"](${bbox}); node["amenity"](${bbox}); way["amenity"](${bbox}); relation["amenity"](${bbox}); node["office"](${bbox}); way["office"](${bbox}); relation["office"](${bbox}); node["craft"](${bbox}); way["craft"](${bbox}); relation["craft"](${bbox}); node["tourism"](${bbox}); way["tourism"](${bbox}); relation["tourism"](${bbox}); node["leisure"](${bbox}); way["leisure"](${bbox}); relation["leisure"](${bbox}); ); out tags center;`; } /* ================= RUN QUERY ================= */ async function runQuery() { markerLayer.clearLayers(); const q = queryBox.value.trim(); if (!q) return log("Query empty"); log("Sending query…"); const body = new URLSearchParams(); body.set("data", q); const res = await fetch(endpoint.value, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body }); if (!res.ok) { log(`HTTP ${res.status}`); return; } const data = await res.json(); log(`Received ${data.elements.length} elements`); const pts = []; data.elements.forEach(el => { const lat = el.lat ?? el.center?.lat; const lon = el.lon ?? el.center?.lon; if (!lat || !lon) return; const t = el.tags || {}; const name = t.name || t.brand || t.operator || "Unnamed"; const type = t.shop ? `Shop: ${t.shop}` : t.amenity ? `Amenity: ${t.amenity}` : t.office ? `Office: ${t.office}` : t.craft ? `Craft: ${t.craft}` : t.tourism ? `Tourism: ${t.tourism}` : t.leisure ? `Leisure: ${t.leisure}` : ""; const popup = ` ${esc(name)}
${esc(type)}
${address(t)}
${t.phone || t["contact:phone"] || ""}
${t.opening_hours || ""}
OpenStreetMap
All tags
${esc(JSON.stringify(t, null, 2))}
`; L.marker([lat, lon]).addTo(markerLayer).bindPopup(popup); pts.push([lat, lon]); }); if (pts.length) map.fitBounds(pts, { maxZoom: 17 }); } /* ================= BUTTONS ================= */ searchArea.onclick = () => { if (map.getZoom() < 14) { log("Zoom in further before searching businesses"); return; } const bbox = boundsToBBox(map.getBounds()); queryBox.value = businessQuery(bbox); runQuery(); }; brunswick.onclick = () => { map.setView([-37.767, 144.961], 15); log("Centered on Brunswick. Pan/zoom then click ‘Search this area’."); }; loadPreset.onclick = () => { const key = queryPreset.value; if (!key || !presets[key]) return; const p = presets[key]; if (p.center && p.zoom) { map.setView(p.center, p.zoom); } queryBox.value = typeof p.query === "function" ? p.query() : p.query; log(`Loaded preset: ${key}`); }; /* ================= DEFAULT ================= */ queryBox.value = "// Pan/zoom the map, then click ‘Search this area’";