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