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