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