19ec21bfdSGreg Roach<?php 2d70512abSGreg Roach 39ec21bfdSGreg Roachuse Fisharebest\Webtrees\I18N; 49ec21bfdSGreg Roachuse Fisharebest\Webtrees\View; 59ec21bfdSGreg Roach 69ec21bfdSGreg Roach/** 7dc270d8cSGreg Roach * @var array<mixed> $data 8c9c6f2ecSGreg Roach * @var object $leaflet_config 99ec21bfdSGreg Roach */ 109ec21bfdSGreg Roach?> 119ec21bfdSGreg Roach 123dcc812bSGreg Roach<div class="py-4"> 133dcc812bSGreg Roach <div class="row gchart osm-wrapper"> 14a2e602dbSGreg Roach <div id="osm-map" class="col-sm-9 wt-ajax-load osm-user-map" dir="ltr"></div> 150d123f04SDavid Drury <ul class="col-sm-3 osm-sidebar wt-page-options-value list-unstyled px-md-1"></ul> 163dcc812bSGreg Roach </div> 173dcc812bSGreg Roach</div> 183dcc812bSGreg Roach 193dcc812bSGreg Roach<?php View::push('styles') ?> 203dcc812bSGreg Roach<style> 213dcc812bSGreg Roach .osm-wrapper, .osm-user-map { 220d123f04SDavid Drury height: 70vh 233dcc812bSGreg Roach } 243dcc812bSGreg Roach 253dcc812bSGreg Roach .osm-sidebar { 263dcc812bSGreg Roach height: 100%; 273dcc812bSGreg Roach overflow-y: auto; 283dcc812bSGreg Roach font-size: small; 293dcc812bSGreg Roach } 303dcc812bSGreg Roach 313dcc812bSGreg Roach</style> 323dcc812bSGreg Roach<?php View::endpush() ?> 333dcc812bSGreg Roach 343dcc812bSGreg Roach<?php View::push('javascript') ?> 3529eb5762SGreg Roach<script> 3629eb5762SGreg Roach 'use strict'; 373dcc812bSGreg Roach 383dcc812bSGreg Roach window.WT_OSM = (function () { 39c9c6f2ecSGreg Roach const config = <?= json_encode($leaflet_config) ?>; 4098579324SDavid Drury const minZoom = 2; 413dcc812bSGreg Roach 423dcc812bSGreg Roach let map = null; 430d123f04SDavid Drury let sidebar = $('.osm-sidebar'); 4498579324SDavid Drury 4598579324SDavid Drury// Map components 463dcc812bSGreg Roach let markers = L.markerClusterGroup({ 4729eb5762SGreg Roach showCoverageOnHover: false, 483dcc812bSGreg Roach }); 493dcc812bSGreg Roach 503dcc812bSGreg Roach let resetControl = L.Control.extend({ 513dcc812bSGreg Roach options: { 5229eb5762SGreg Roach position: 'topleft', 533dcc812bSGreg Roach }, 543dcc812bSGreg Roach onAdd: function (map) { 553dcc812bSGreg Roach let container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom'); 563dcc812bSGreg Roach container.onclick = function () { 57*c68bbde3SGreg Roach map.flyToBounds(markers.getBounds(), { padding: [50, 30], maxZoom: 15 }); 5829eb5762SGreg Roach sidebar.scrollTo(sidebar.children(':first')); 5936409e74SGreg Roach 603dcc812bSGreg Roach return false; 613dcc812bSGreg Roach }; 62c9c6f2ecSGreg Roach let reset = config.i18n.reset; 633dcc812bSGreg Roach let anchor = L.DomUtil.create('a', 'leaflet-control-reset', container); 6498579324SDavid Drury anchor.setAttribute('aria-label', reset); 653dcc812bSGreg Roach anchor.href = '#'; 66a4321966SGreg Roach anchor.title = reset; 673dcc812bSGreg Roach anchor.role = 'button'; 683dcc812bSGreg Roach let image = L.DomUtil.create('i', 'fas fa-redo', anchor); 69a4321966SGreg Roach image.alt = reset; 703dcc812bSGreg Roach 713dcc812bSGreg Roach return container; 7229eb5762SGreg Roach }, 7398579324SDavid Drury }); 7498579324SDavid Drury 753dcc812bSGreg Roach /** 763dcc812bSGreg Roach * @private 773dcc812bSGreg Roach */ 783dcc812bSGreg Roach let _drawMap = function () { 79c9c6f2ecSGreg Roach map = webtrees.buildLeafletJsMap('osm-map', config) 80c9c6f2ecSGreg Roach .addControl(new resetControl()); 813dcc812bSGreg Roach }; 823dcc812bSGreg Roach 833dcc812bSGreg Roach /** 843dcc812bSGreg Roach * @private 853dcc812bSGreg Roach */ 8698579324SDavid Drury let _buildMapData = function () { 870d123f04SDavid Drury let sidebar_content = ''; 8898579324SDavid Drury let geoJson_data = <?= json_encode($data) ?>; 893dcc812bSGreg Roach 9098579324SDavid Drury if (geoJson_data.features.length === 0) { 9198579324SDavid Drury map.fitWorld(); 9298579324SDavid Drury sidebar_content += '<div class="bg-info text-white text-center">' + <?= json_encode(I18N::translate('Nothing to show')) ?> + '</div>'; 9398579324SDavid Drury } else { 9498579324SDavid Drury let geoJsonLayer = L.geoJson(geoJson_data, { 953dcc812bSGreg Roach pointToLayer: function (feature, latlng) { 963dcc812bSGreg Roach return new L.Marker(latlng, { 973dcc812bSGreg Roach icon: L.BeautifyIcon.icon({ 983130efd4SGreg Roach icon: 'bullseye fas', 993dcc812bSGreg Roach borderColor: 'transparent', 1003130efd4SGreg Roach backgroundColor: feature.properties.iconcolor, 1013dcc812bSGreg Roach iconShape: 'marker', 1023130efd4SGreg Roach textColor: 'white', 1033dcc812bSGreg Roach }), 1043dcc812bSGreg Roach title: feature.properties.tooltip, 1053dcc812bSGreg Roach alt: feature.properties.tooltip, 10629eb5762SGreg Roach id: feature.id, 1073dcc812bSGreg Roach }) 1083dcc812bSGreg Roach .on('popupopen', function (e) { 10929eb5762SGreg Roach let item = sidebar.children('.gchart[data-id=' + e.target.feature.id + ']'); 1103dcc812bSGreg Roach item.addClass('messagebox'); 1113dcc812bSGreg Roach sidebar.scrollTo(item); 1123dcc812bSGreg Roach }) 1133dcc812bSGreg Roach .on('popupclose', function () { 11429eb5762SGreg Roach sidebar.children('.gchart').removeClass('messagebox'); 1153dcc812bSGreg Roach }); 1163dcc812bSGreg Roach }, 1173dcc812bSGreg Roach onEachFeature: function (feature, layer) { 1183dcc812bSGreg Roach if (feature.properties.polyline) { 1193dcc812bSGreg Roach let pline = L.polyline(feature.properties.polyline.points, feature.properties.polyline.options); 1203dcc812bSGreg Roach markers.addLayer(pline); 1213dcc812bSGreg Roach } 1223dcc812bSGreg Roach layer.bindPopup(feature.properties.summary); 1230d123f04SDavid Drury sidebar_content += `<li class="gchart px-md-2" data-id=${feature.id}>${feature.properties.summary}</li>`; 12429eb5762SGreg Roach }, 1253dcc812bSGreg Roach }); 1263dcc812bSGreg Roach markers.addLayer(geoJsonLayer); 12798579324SDavid Drury map.addLayer(markers); 128*c68bbde3SGreg Roach map.flyToBounds(markers.getBounds(), { padding: [50, 30], maxZoom: 15 }); 1293dcc812bSGreg Roach } 13098579324SDavid Drury sidebar.append(sidebar_content); 1313dcc812bSGreg Roach }; 1323dcc812bSGreg Roach 1333dcc812bSGreg Roach /** 1343dcc812bSGreg Roach * @param elem 1353dcc812bSGreg Roach * @returns {$} 1363dcc812bSGreg Roach */ 1373dcc812bSGreg Roach $.fn.scrollTo = function (elem) { 1383dcc812bSGreg Roach let _this = $(this); 1393dcc812bSGreg Roach _this.animate({ 14029eb5762SGreg Roach scrollTop: elem.offset().top - _this.offset().top + _this.scrollTop(), 1413dcc812bSGreg Roach }); 1423dcc812bSGreg Roach return this; 1433dcc812bSGreg Roach }; 1443dcc812bSGreg Roach 1453dcc812bSGreg Roach // Activate marker popup when sidebar entry clicked 1463dcc812bSGreg Roach $(function () { 1470d123f04SDavid Drury sidebar 1483dcc812bSGreg Roach // open marker popup if sidebar event is clicked 1493dcc812bSGreg Roach .on('click', '.gchart', function (e) { 1503dcc812bSGreg Roach // first close any existing 1513dcc812bSGreg Roach map.closePopup(); 1523dcc812bSGreg Roach let eventId = $(this).data('id'); 1533dcc812bSGreg Roach //find the marker corresponding to the clicked event 1543dcc812bSGreg Roach let mkrLayer = markers.getLayers().filter(function (v) { 1553dcc812bSGreg Roach return typeof (v.feature) !== 'undefined' && v.feature.id === eventId; 1563dcc812bSGreg Roach }); 1573dcc812bSGreg Roach let mkr = mkrLayer.pop(); 1583dcc812bSGreg Roach // Unfortunately zoomToShowLayer zooms to maxZoom 1593dcc812bSGreg Roach // when all marker in a cluster have exactly the 1603dcc812bSGreg Roach // same co-ordinates 1613dcc812bSGreg Roach markers.zoomToShowLayer(mkr, function (e) { 1623dcc812bSGreg Roach mkr.openPopup(); 1633dcc812bSGreg Roach }); 16498579324SDavid Drury 1653dcc812bSGreg Roach return false; 1663dcc812bSGreg Roach }) 1673dcc812bSGreg Roach .on('click', 'a', function (e) { // stop click on a person also opening the popup 1683dcc812bSGreg Roach e.stopPropagation(); 1693dcc812bSGreg Roach }); 1703dcc812bSGreg Roach }); 1713dcc812bSGreg Roach 1723dcc812bSGreg Roach _drawMap(); 17398579324SDavid Drury _buildMapData(); 1743dcc812bSGreg Roach 17529eb5762SGreg Roach return 'Leaflet map interface for webtrees-2'; 1763dcc812bSGreg Roach })(); 1773dcc812bSGreg Roach</script> 1783dcc812bSGreg Roach<?php View::endpush() ?> 179