1<?php 2 3use Fisharebest\Webtrees\View; 4 5/** 6 * @var array<mixed> $data 7 * @var object $leaflet_config 8 */ 9 10?> 11 12<div class="row gchart wt-place-hierarchy-wrapper"> 13 <div id="wt-map" class="col-sm-9 wt-ajax-load wt-map wt-place-hierarchy-map" dir="ltr"></div> 14 <ul class="col-sm-3 wt-place-hierarchy-sidebar wt-page-options-value list-unstyled px-md-1"></ul> 15</div> 16 17<?php View::push('javascript') ?> 18<script> 19 'use strict'; 20 21 (function () { 22 const config = <?= json_encode($leaflet_config, JSON_THROW_ON_ERROR) ?>; 23 24 let map = null; 25 const sidebar = document.querySelector('.wt-place-hierarchy-sidebar'); 26 27 const scrollOptions = { 28 behavior: "smooth", 29 block: "start", 30 inline: "start" 31 }; 32 33 // Map components 34 let markers = L.markerClusterGroup({ 35 showCoverageOnHover: false, 36 }); 37 38 /** 39 * Passed to resetControl to 40 * perform necessary reset actions on map 41 */ 42 let resetCallback = function () { 43 map.flyToBounds(markers.getBounds(), {padding: [50, 30], maxZoom: 15 }); 44 sidebar.firstElementChild.scrollIntoView(scrollOptions); 45 } 46 47 /** 48 * @private 49 */ 50 let _drawMap = function () { 51 map = webtrees.buildLeafletJsMap('wt-map', config, resetCallback); 52 }; 53 54 /** 55 * @private 56 */ 57 let _buildMapData = function () { 58 let data = <?= json_encode($data['markers'], JSON_THROW_ON_ERROR) ?>; 59 60 let geoJsonLayer = L.geoJson(data, { 61 pointToLayer: function (feature, latlng) { 62 return new L.Marker(latlng, { 63 icon: L.BeautifyIcon.icon({ 64 icon: 'bullseye fas', 65 borderColor: 'transparent', 66 backgroundColor: '#1e90ff', 67 iconShape: 'marker', 68 textColor: 'white', 69 }), 70 title: feature.properties.tooltip, 71 alt: feature.properties.tooltip, 72 id: feature.id, 73 }) 74 .on('popupopen', function (e) { 75 let item = document.querySelector('.mapped[data-wt-feature-id="' + e.target.feature.id + '"]'); 76 item.classList.add('messagebox'); 77 item.scrollIntoView(scrollOptions); 78 }) 79 .on('popupclose', function () { 80 sidebar.querySelectorAll('.mapped').forEach(e => e.classList.remove('messagebox')); 81 sidebar.firstElementChild.scrollIntoView(scrollOptions); 82 }); 83 }, 84 onEachFeature: function (feature, layer) { 85 layer.bindPopup(feature.properties.popup); 86 }, 87 }); 88 89 if (data.features.length > 0) { 90 markers.addLayer(geoJsonLayer); 91 map.addLayer(markers); 92 } 93 94 map.fitBounds(<?= json_encode($data['bounds'], JSON_THROW_ON_ERROR) ?>, { padding: [50, 30] }); 95 sidebar.innerHTML = <?= json_encode($data['sidebar'], JSON_THROW_ON_ERROR) ?>; 96 }; 97 98 window.onload = function() { 99 // Activate marker popup when sidebar entry clicked 100 sidebar.querySelectorAll('.mapped').forEach((element) => { 101 var eventId = parseInt(element.dataset.wtFeatureId); 102 103 element.addEventListener('click', () => { 104 // first close any existing 105 map.closePopup(); 106 //find the marker corresponding to the clicked event 107 let mkrLayer = markers.getLayers().filter(function (v) { 108 return v.feature !== undefined && v.feature.id === eventId; 109 }); 110 111 let mkr = mkrLayer.pop(); 112 113 markers.zoomToShowLayer(mkr, function (e) { 114 mkr.openPopup(); 115 }); 116 117 return false; 118 }); 119 120 // stop clicking on a person also opening the popup 121 element.querySelectorAll('a').forEach((el) => { 122 el.addEventListener('click', (e) => { 123 e.stopPropagation(); 124 }); 125 }); 126 }); 127 } 128 129 _drawMap(); 130 _buildMapData(); 131 })(); 132</script> 133<?php View::endpush() ?> 134