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"> 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"></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: "start", 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 sidebar.firstElementChild.scrollIntoView(scrollOptions); 50 } 51 52 /** 53 * 54 * @private 55 */ 56 let _drawMap = function () { 57 map = webtrees.buildLeafletJsMap('wt-map', config, resetCallback); 58 }; 59 60 /** 61 * 62 * @private 63 */ 64 let _buildMapData = function () { 65 let geoJson_data = <?= json_encode($data, JSON_THROW_ON_ERROR) ?>; 66 67 if (geoJson_data.features.length === 0) { 68 map.fitWorld(); 69 sidebar.innerHTML = '<div class="bg-info text-white text-center">' + <?= json_encode(I18N::translate('Nothing to show'), JSON_THROW_ON_ERROR) ?> + '</div>'; 70 } else { 71 sidebar.innerHTML = ''; 72 let geoJsonLayer = L.geoJson(geoJson_data, { 73 pointToLayer: function (feature, latlng) { 74 return new L.Marker(latlng, { 75 icon: L.BeautifyIcon.icon({ 76 icon: 'bullseye fas', 77 borderColor: 'transparent', 78 backgroundColor: feature.properties.iconcolor, 79 iconShape: 'marker', 80 textColor: 'white', 81 }), 82 title: feature.properties.tooltip, 83 id: feature.id, 84 }) 85 .on('popupopen', function (e) { 86 let item = document.querySelector('[data-wt-feature-id="' + e.target.feature.id + '"]'); 87 item.classList.add('messagebox'); 88 item.scrollIntoView(scrollOptions); 89 }) 90 .on('popupclose', function () { 91 sidebar.childNodes.forEach(e => e.classList.remove('messagebox')); 92 sidebar.firstElementChild.scrollIntoView(scrollOptions); 93 }); 94 }, 95 onEachFeature: function (feature, layer) { 96 if (feature.properties.polyline) { 97 let pline = L.polyline(feature.properties.polyline.points, feature.properties.polyline.options); 98 markers.addLayer(pline); 99 } 100 101 layer.bindPopup(feature.properties.summary); 102 sidebar.innerHTML += `<li class="gchart my-1" data-wt-feature-id=${feature.id}>${feature.properties.summary}</li>`; 103 }, 104 }); 105 markers.addLayer(geoJsonLayer); 106 map.addLayer(markers); 107 map.fitBounds(markers.getBounds(), { padding: [50, 30], maxZoom: 15 }); 108 } 109 }; 110 111 window.onload = function() { 112 // Activate marker popup when sidebar entry clicked 113 sidebar.addEventListener('click', (e) => { 114 if (e.target.matches('[data-wt-sosa]')) { 115 map.closePopup(); 116 117 let marker = markers.getLayers().filter(function (v) { 118 return v.feature !== undefined && v.feature.id === parseInt(e.target.dataset.wtSosa); 119 }).pop(); 120 121 markers.zoomToShowLayer(marker, () => marker.openPopup()); 122 123 return false; 124 } 125 }); 126 } 127 128 _drawMap(); 129 _buildMapData(); 130 })(); 131</script> 132<?php View::endpush() ?> 133