[GIS] Dynamic map sidebar with info from marker upon click

csshtmljavascriptleafletleaflet-plugins

I am new to Leaflet, HTML, CSS and Java. I am using leaflets maps and I want to create a sidebar that is active when a marker is clicked or active when a clicked in the sidebar, so far I have had no luck at all. I have tried to do similar to this but I want defined markers lat and long http://jsfiddle.net/BPuQ9/8/ but have had no luck

I have a JSfiddle file here: https://jsfiddle.net/Niall2110/yphxqzu2/1/

<!DOCTYPE html>
<html>
<head>

    <title>Quick Start - Leaflet</title>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>
    <script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js" integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og==" crossorigin=""></script>

<style>
    html, body, #map {
    width:100%;
    height:100%;
    margin:0;
    margin-left:10%;
    padding:0;
}
#overlay {
    position:absolute;
    width:30%;
    height:100%;
    left:0;
    top:0;
    background-color:rgba(255, 255, 255, 0.8);
}


</style>

</head>
<body>
<div id = "map"></div>
<div id="overlay"></div>

<script>


var map = L.map('map', {
    center: [48,14],
    zoom: 7,
   animate: true, duration: 1
});

L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
   maxZoom: 18,
   attribution: 'Map data &copy; <a 
href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
    '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
    'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox.streets'
}).addTo(map);

L.marker([49, 14]).addTo(map)
    .bindPopup("<b><font size='6'>Headline</font></b><br />info<br //> <img src=''> <a href= '' target='_blank'><button>Source</button></a> ").openPopup();
$('#overlay').append(
        '<div class="item" id="' + marker._leaflet_id + '">marker ' + marker._leaflet_id + ' - <a href="#" class="remove" id="' + marker._leaflet_id + '">remove</a></div>');



</script>


</body>
</html>

Best Answer

Solution below is not complete solution with all the required bells and whistles (specially CSS styles are lame), it's just a first step in the right direction.

There is simple function createMarker for creating markers with all the desired properties (position, title, text, image, source link). Function creates marker in markerLayer with the following properties:

  • Basic info text (title, text, link) is created. It's the same for popup and sidebar.
  • Popup is created with info text.
  • Mouse click event handler is created for marker. This handler upon mouse click adds HTML element to the sidebar, again with two clickable elements. One is info text, which upon click puts corresponding marker to the center of the map and bounces it (Leaflet.SmoothMarkerBouncing plugin). The other is Remove element which upon click removes the whole element from the sidebar.

Working JSFiddle is available at https://jsfiddle.net/TomazicM/ox43cbth/5/

The code:

<!DOCTYPE html>
<html>

<head>
  <title>Quick Start - Leaflet</title>
  <meta charset="utf-8" />
  <meta content="width=device-width, initial-scale=1.0" name="viewport">
  <link crossorigin="" href="lib/leaflet/leaflet.css"rel="stylesheet" />
  <script src="lib/leaflet/leaflet.js"></script>
  <script src="lib/Leaflet.SmoothMarkerBouncing/leaflet.smoothmarkerbouncing.js"></script>
  <style>
    html, body, #map {
      width: 100%;
      height: 100%;
      margin: 0;
      margin-left: 10%;
      padding:0;
    }
    #sidebar {
      position: absolute;
      width: 30%;
      height: 100%;
      left: 0;
      top: 0;
      background-color: rgba(255, 255, 255, 0.8);
    }
    .sidebarElement {
      padding: 6px;
      display: table;
      width: 95%;
    }
    .infoSidebarElement {
      display: table-cell;
      cursor: pointer;
      width: 90%;
    }
    .removeSidebarElement {    
      display: table-cell;
      text-align: right;
      cursor: pointer;
    }  //closing bracket was missing (had to add some more letters, otherwise unable to submit)
  </style>
</head>

<body>
<div id="sidebar"></div>
<div id="map"></div>

<script>
  var map = L.map('map', {
      center: [48,14],
      zoom: 7,
     animate: true, duration: 1
  });
  
  L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
     maxZoom: 18,
     attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
      '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
      'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
    id: 'mapbox.streets'
  }).addTo(map);

  markerLayer = L.layerGroup([]).addTo(map);
   
  function createMarker(coords, title, info, image, source) {
    var marker, content;
  
    content = '<b><font size="6">' + title + '</font></b><br/>' + info + '<br> <img src="' + image + '"><a href="' + source + '" target="_blank"><button>Source</button></a>'
    marker = L.marker(coords).addTo(markerLayer);
    marker.bindPopup(content);
    
    marker.on('click', function(evt) {
      var id = L.Util.stamp(evt.target);
      if (document.getElementById(id) != null) return; 
      var sidebarElement, infoPart, removePart;
      sidebarElement = L.DomUtil.create('div', 'sidebarElement', document.getElementById('sidebar'));
      sidebarElement.id = id;
      infoPart = L.DomUtil.create('div', 'infoSidebarElement', sidebarElement);
      infoPart.innerHTML = content;
      L.DomEvent.on(infoPart, 'click', function(evt) {
        var marker = markerLayer.getLayer(this.id);
        marker.closePopup();
        map.panTo(marker.getLatLng());
        marker.bounce(3);
      }, sidebarElement);
      removePart = L.DomUtil.create('div', 'removeSidebarElement', sidebarElement);
      removePart.innerHTML = 'Remove';
      L.DomEvent.on(removePart, 'click', function(evt) {
        markerLayer.getLayer(this.id).closePopup();
        this.parentNode.removeChild(this);
      }, sidebarElement);
    });
  }
  
  createMarker([49, 14], 'Title 1', 'Info 1', '', ''); 
  createMarker([47, 12], 'Title 2', 'Info 2', '', ''); 
</script>
</body>
</html>