← back to Restaurant Directory

src/web/views/map.ejs

34 lines

<%- include('partials/head', { title: 'Map of all restaurants' }) %>

<main class="container map-page">
  <header>
    <h1>Map · <%= total.toLocaleString() %> restaurants</h1>
    <p class="muted">Pins load on demand by viewport. Click any to open the detail page.</p>
  </header>
  <div id="big-map"></div>
</main>

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.Default.css">
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.js"></script>
<script>
  const map = L.map('big-map').setView([34.05, -118.24], 11);
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OSM', maxZoom: 19 }).addTo(map);
  const cluster = L.markerClusterGroup({ chunkedLoading: true, showCoverageOnHover: false });
  fetch('/api/pins')
    .then(r => r.json())
    .then(({ pins }) => {
      const esc = s => String(s).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
      pins.forEach(p => {
        const m = L.marker([p.lat, p.lng]);
        m.bindPopup('<strong>' + esc(p.name) + '</strong><br><a href="/r/' + encodeURIComponent(p.slug) + '">Open &rarr;</a>');
        cluster.addLayer(m);
      });
      map.addLayer(cluster);
    });
</script>

<%- include('partials/foot') %>