1dd6b2bfcSGreg Roach<?php use Fisharebest\Webtrees\I18N; ?> 2dd6b2bfcSGreg Roach 3dd6b2bfcSGreg Roach<div class="py-4"> 4dd6b2bfcSGreg Roach <div class="row gchart osm-wrapper"> 5d21f0b10SGreg Roach <div id="osm-map" class="col-sm-9 wt-ajax-load osm-user-map" dir="ltr"></div> 68fca99e0SGreg Roach <ul class="col-sm-3 osm-sidebar wt-page-options-value list-unstyled p-0"></ul> 7dd6b2bfcSGreg Roach </div> 8dd6b2bfcSGreg Roach</div> 9dd6b2bfcSGreg Roach 10dd6b2bfcSGreg Roach<style> 11dd6b2bfcSGreg Roach .osm-wrapper, .osm-user-map { 128fca99e0SGreg Roach height: 75vh 13dd6b2bfcSGreg Roach } 14dd6b2bfcSGreg Roach 15dd6b2bfcSGreg Roach .osm-sidebar { 16dd6b2bfcSGreg Roach height: 100%; 17dd6b2bfcSGreg Roach overflow-y: auto; 18dd6b2bfcSGreg Roach padding: 0; 19dd6b2bfcSGreg Roach margin: 0; 20dd6b2bfcSGreg Roach border: 0; 21dd6b2bfcSGreg Roach display: none; 22dd6b2bfcSGreg Roach font-size: small; 23dd6b2bfcSGreg Roach } 24dd6b2bfcSGreg Roach 25dd6b2bfcSGreg Roach .osm-sidebar .gchart { 26dd6b2bfcSGreg Roach margin: 1px; 27dd6b2bfcSGreg Roach padding: 2px 28dd6b2bfcSGreg Roach } 29dd6b2bfcSGreg Roach 30dd6b2bfcSGreg Roach .osm-sidebar .gchart img { 31dd6b2bfcSGreg Roach height: 15px; 32dd6b2bfcSGreg Roach width: 25px 33dd6b2bfcSGreg Roach } 34dd6b2bfcSGreg Roach</style> 35dd6b2bfcSGreg Roach 36dd6b2bfcSGreg Roach<script type="application/javascript"> 37dd6b2bfcSGreg Roach "use strict"; 38dd6b2bfcSGreg Roach 39dd6b2bfcSGreg Roach window.WT_OSM = (function () { 40dd6b2bfcSGreg Roach let baseData = { 41dd6b2bfcSGreg Roach minZoom: 2, 42dd6b2bfcSGreg Roach providerName: "OpenStreetMap.Mapnik", 43dd6b2bfcSGreg Roach providerOptions: [], 44dd6b2bfcSGreg Roach }; 45dd6b2bfcSGreg Roach 46dd6b2bfcSGreg Roach let map = null; 47dd6b2bfcSGreg Roach let zoom = null; 48dd6b2bfcSGreg Roach let markers = L.markerClusterGroup({ 49dd6b2bfcSGreg Roach showCoverageOnHover: false, 50dd6b2bfcSGreg Roach }); 51dd6b2bfcSGreg Roach 52dd6b2bfcSGreg Roach let resetControl = L.Control.extend({ 53dd6b2bfcSGreg Roach options: { 54dd6b2bfcSGreg Roach position: "topleft", 55dd6b2bfcSGreg Roach }, 56dd6b2bfcSGreg Roach 57dd6b2bfcSGreg Roach onAdd: function (map) { 58dd6b2bfcSGreg Roach let container = L.DomUtil.create("div", "leaflet-bar leaflet-control leaflet-control-custom"); 59dd6b2bfcSGreg Roach container.onclick = function () { 60dd6b2bfcSGreg Roach if (zoom) { 61dd6b2bfcSGreg Roach map.flyTo(markers.getBounds().getCenter(), zoom); 62dd6b2bfcSGreg Roach } else { 63dd6b2bfcSGreg Roach map.flyToBounds(markers.getBounds().pad(0.2)); 64dd6b2bfcSGreg Roach } 654125a3e1SGreg Roach let sidebar = $(".osm-sidebar"); 664125a3e1SGreg Roach sidebar.scrollTo(sidebar.children(":first")); 674125a3e1SGreg Roach 68dd6b2bfcSGreg Roach return false; 69dd6b2bfcSGreg Roach }; 70dd6b2bfcSGreg Roach let anchor = L.DomUtil.create("a", "leaflet-control-reset", container); 71*57862dd5SDavid Drury let reset = <?= json_encode(I18N::translate('Reset to initial map state')) ?>; 72dd6b2bfcSGreg Roach anchor.href = "#"; 73*57862dd5SDavid Drury anchor.title = reset; 74dd6b2bfcSGreg Roach anchor.role = "button"; 75dd6b2bfcSGreg Roach $(anchor).attr("aria-label", "reset"); 76dd6b2bfcSGreg Roach let image = L.DomUtil.create("i", "fas fa-redo", anchor); 77*57862dd5SDavid Drury image.alt = reset; 78dd6b2bfcSGreg Roach 79dd6b2bfcSGreg Roach return container; 80dd6b2bfcSGreg Roach }, 81dd6b2bfcSGreg Roach }); 82dd6b2bfcSGreg Roach 83dd6b2bfcSGreg Roach /** 84dd6b2bfcSGreg Roach * 85dd6b2bfcSGreg Roach * @private 86dd6b2bfcSGreg Roach */ 87dd6b2bfcSGreg Roach let _drawMap = function () { 88dd6b2bfcSGreg Roach map = L.map("osm-map", { 89dd6b2bfcSGreg Roach center: [0, 0], 90dd6b2bfcSGreg Roach minZoom: baseData.minZoom, // maxZoom set by leaflet-providers.js 91dd6b2bfcSGreg Roach zoomControl: false, // remove default 92dd6b2bfcSGreg Roach }); 93dd6b2bfcSGreg Roach L.tileLayer.provider(baseData.providerName, baseData.providerOptions).addTo(map); 94dd6b2bfcSGreg Roach L.control.zoom({ // Add zoom with localised text 95*57862dd5SDavid Drury zoomInTitle: <?= json_encode(I18N::translate('Zoom in')) ?>, 96*57862dd5SDavid Drury zoomOutTitle: <?= json_encode(I18N::translate('Zoom out')) ?>, 97dd6b2bfcSGreg Roach }).addTo(map); 98dd6b2bfcSGreg Roach }; 99dd6b2bfcSGreg Roach 100dd6b2bfcSGreg Roach let _addLayer = function () { 101dd6b2bfcSGreg Roach let geoJsonLayer; 102dd6b2bfcSGreg Roach let domObj = ".osm-sidebar"; 103dd6b2bfcSGreg Roach let sidebar = ""; 104dd6b2bfcSGreg Roach 105dd6b2bfcSGreg Roach let data = <?= json_encode($data) ?>; 106dd6b2bfcSGreg Roach 107dd6b2bfcSGreg Roach geoJsonLayer = L.geoJson(data, { 108dd6b2bfcSGreg Roach pointToLayer: function (feature, latlng) { 109dd6b2bfcSGreg Roach return new L.Marker(latlng, { 110dd6b2bfcSGreg Roach icon: L.BeautifyIcon.icon({ 111dd6b2bfcSGreg Roach icon: feature.properties.icon["name"], 112dd6b2bfcSGreg Roach borderColor: "transparent", 11380993423SGreg Roach backgroundColor: feature.properties.icon["color"], 114dd6b2bfcSGreg Roach iconShape: "marker", 11580993423SGreg Roach textColor: "white", 116dd6b2bfcSGreg Roach }), 117dd6b2bfcSGreg Roach title: feature.properties.tooltip, 118dd6b2bfcSGreg Roach alt: feature.properties.tooltip, 119dd6b2bfcSGreg Roach id: feature.id, 120dd6b2bfcSGreg Roach }) 121dd6b2bfcSGreg Roach .on("popupopen", function (e) { 122dd6b2bfcSGreg Roach let sidebar = $(".osm-sidebar"); 123dd6b2bfcSGreg Roach let item = sidebar.children(".gchart[data-id=" + e.target.feature.id + "]"); 124dd6b2bfcSGreg Roach item.addClass("messagebox"); 125dd6b2bfcSGreg Roach sidebar.scrollTo(item); 126dd6b2bfcSGreg Roach }) 127dd6b2bfcSGreg Roach .on("popupclose", function () { 128dd6b2bfcSGreg Roach $(".osm-sidebar").children(".gchart") 129dd6b2bfcSGreg Roach .removeClass("messagebox"); 130dd6b2bfcSGreg Roach }); 131dd6b2bfcSGreg Roach }, 132dd6b2bfcSGreg Roach onEachFeature: function (feature, layer) { 133dd6b2bfcSGreg Roach layer.bindPopup(feature.properties.summary); 134*57862dd5SDavid Drury sidebar += `<li class="gchart" data-id=${feature.id}>${feature.properties.summary}</li>`; 135dd6b2bfcSGreg Roach }, 136dd6b2bfcSGreg Roach }); 137dd6b2bfcSGreg Roach 138dd6b2bfcSGreg Roach if (data.features.length > 0) { 139dd6b2bfcSGreg Roach $(domObj).append(sidebar); 140dd6b2bfcSGreg Roach markers.addLayer(geoJsonLayer); 141dd6b2bfcSGreg Roach map 142dd6b2bfcSGreg Roach .addControl(new resetControl()) 143dd6b2bfcSGreg Roach .addLayer(markers); 144dd6b2bfcSGreg Roach 145dd6b2bfcSGreg Roach if (data.features.length === 1) { 146dd6b2bfcSGreg Roach map.setView(markers.getBounds().getCenter(), data.features[0].properties.zoom); 147dd6b2bfcSGreg Roach } else { 148dd6b2bfcSGreg Roach map.fitBounds(markers.getBounds().pad(0.2)) 149dd6b2bfcSGreg Roach } 150dd6b2bfcSGreg Roach } else { 151dd6b2bfcSGreg Roach map.fitWorld(); 152*57862dd5SDavid Drury $(domObj).append("<div class='bg-info text-white'>" + <?= json_encode(I18N::translate('No mappable items')) ?> + "</div>"); 153dd6b2bfcSGreg Roach } 154dd6b2bfcSGreg Roach 155dd6b2bfcSGreg Roach $(domObj).slideDown(300); 156dd6b2bfcSGreg Roach }; 157dd6b2bfcSGreg Roach 158dd6b2bfcSGreg Roach /** 159dd6b2bfcSGreg Roach * 160dd6b2bfcSGreg Roach * @param elem 161dd6b2bfcSGreg Roach * @returns {$} 162dd6b2bfcSGreg Roach */ 163dd6b2bfcSGreg Roach 164dd6b2bfcSGreg Roach $.fn.scrollTo = function (elem) { 165dd6b2bfcSGreg Roach let _this = $(this); 166dd6b2bfcSGreg Roach _this.animate({ 167dd6b2bfcSGreg Roach scrollTop: elem.offset().top - _this.offset().top + _this.scrollTop(), 168dd6b2bfcSGreg Roach }); 169dd6b2bfcSGreg Roach return this; 170dd6b2bfcSGreg Roach }; 171dd6b2bfcSGreg Roach 172dd6b2bfcSGreg Roach return { 173dd6b2bfcSGreg Roach drawMap: function () { 174dd6b2bfcSGreg Roach _drawMap(); 175dd6b2bfcSGreg Roach _addLayer(); 176dd6b2bfcSGreg Roach 177dd6b2bfcSGreg Roach // Activate marker popup when sidebar entry clicked 178dd6b2bfcSGreg Roach $(".osm-sidebar") 179dd6b2bfcSGreg Roach .on("click", ".gchart", function (e) { 180dd6b2bfcSGreg Roach // first close any existing 181dd6b2bfcSGreg Roach map.closePopup(); 182dd6b2bfcSGreg Roach let eventId = $(this).data("id"); 183dd6b2bfcSGreg Roach //find the marker corresponding to the clicked event 184dd6b2bfcSGreg Roach let mkrLayer = markers.getLayers().filter(function (v) { 185dd6b2bfcSGreg Roach return typeof(v.feature) !== "undefined" && v.feature.id === eventId; 186dd6b2bfcSGreg Roach }); 187dd6b2bfcSGreg Roach let mkr = mkrLayer.pop(); 188dd6b2bfcSGreg Roach // Unfortunately zoomToShowLayer zooms to maxZoom 189dd6b2bfcSGreg Roach // when all marker in a cluster have exactly the 190dd6b2bfcSGreg Roach // same co-ordinates 191dd6b2bfcSGreg Roach markers.zoomToShowLayer(mkr, function (e) { 192dd6b2bfcSGreg Roach mkr.openPopup(); 193dd6b2bfcSGreg Roach }); 194dd6b2bfcSGreg Roach return false; 195dd6b2bfcSGreg Roach }) 196dd6b2bfcSGreg Roach .on("click", "a", function (e) { // stop click on a person also opening the popup 197dd6b2bfcSGreg Roach e.stopPropagation(); 198dd6b2bfcSGreg Roach }); 199dd6b2bfcSGreg Roach }, 200dd6b2bfcSGreg Roach }; 201dd6b2bfcSGreg Roach })(); 202dd6b2bfcSGreg Roach 203dd6b2bfcSGreg Roach WT_OSM.drawMap(); 204dd6b2bfcSGreg Roach</script> 205