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 8*c9c6f2ecSGreg 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 Roachwindow.WT_OSM = (function () { 39*c9c6f2ecSGreg Roach const config = <?= json_encode($leaflet_config) ?>; 4098579324SDavid Drury const minZoom = 2; 413dcc812bSGreg Roach 423dcc812bSGreg Roach let map = null; 433dcc812bSGreg Roach let zoom = null; 440d123f04SDavid Drury let sidebar = $('.osm-sidebar'); 4598579324SDavid Drury 4698579324SDavid Drury// Map components 473dcc812bSGreg Roach let markers = L.markerClusterGroup({ 4829eb5762SGreg Roach showCoverageOnHover: false, 493dcc812bSGreg Roach }); 503dcc812bSGreg Roach 513dcc812bSGreg Roach let resetControl = L.Control.extend({ 523dcc812bSGreg Roach options: { 5329eb5762SGreg Roach position: 'topleft', 543dcc812bSGreg Roach }, 553dcc812bSGreg Roach onAdd: function (map) { 563dcc812bSGreg Roach let container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom'); 573dcc812bSGreg Roach container.onclick = function () { 583dcc812bSGreg Roach if (zoom) { 593dcc812bSGreg Roach map.flyTo(markers.getBounds().getCenter(), zoom); 603dcc812bSGreg Roach } else { 613dcc812bSGreg Roach map.flyToBounds(markers.getBounds().pad(0.2)); 623dcc812bSGreg Roach } 6329eb5762SGreg Roach sidebar.scrollTo(sidebar.children(':first')); 6436409e74SGreg Roach 653dcc812bSGreg Roach return false; 663dcc812bSGreg Roach }; 67*c9c6f2ecSGreg Roach let reset = config.i18n.reset; 683dcc812bSGreg Roach let anchor = L.DomUtil.create('a', 'leaflet-control-reset', container); 6998579324SDavid Drury anchor.setAttribute('aria-label', reset); 703dcc812bSGreg Roach anchor.href = '#'; 71a4321966SGreg Roach anchor.title = reset; 723dcc812bSGreg Roach anchor.role = 'button'; 733dcc812bSGreg Roach let image = L.DomUtil.create('i', 'fas fa-redo', anchor); 74a4321966SGreg Roach image.alt = reset; 753dcc812bSGreg Roach 763dcc812bSGreg Roach return container; 7729eb5762SGreg Roach }, 7898579324SDavid Drury }); 7998579324SDavid Drury 803dcc812bSGreg Roach /** 813dcc812bSGreg Roach * @private 823dcc812bSGreg Roach */ 833dcc812bSGreg Roach let _drawMap = function() { 84*c9c6f2ecSGreg Roach map = webtrees.buildLeafletJsMap('osm-map', config) 85*c9c6f2ecSGreg Roach .addControl(new resetControl()); 863dcc812bSGreg Roach }; 873dcc812bSGreg Roach 883dcc812bSGreg Roach /** 893dcc812bSGreg Roach * @private 903dcc812bSGreg Roach */ 9198579324SDavid Drury let _buildMapData = function () { 920d123f04SDavid Drury let sidebar_content = ''; 9398579324SDavid Drury let geoJson_data = <?= json_encode($data) ?>; 943dcc812bSGreg Roach 9598579324SDavid Drury if (geoJson_data.features.length === 0) { 9698579324SDavid Drury map.fitWorld(); 9798579324SDavid Drury sidebar_content += '<div class="bg-info text-white text-center">' + <?= json_encode(I18N::translate('Nothing to show')) ?> +'</div>'; 9898579324SDavid Drury } else { 9998579324SDavid Drury if (geoJson_data.features.length === 1) { 10098579324SDavid Drury //fudge factor - maps zooms to maximum permitted otherwise 10198579324SDavid Drury zoom = geoJson_data.features[0].properties.zoom; 1023dcc812bSGreg Roach } 10398579324SDavid Drury let geoJsonLayer = L.geoJson(geoJson_data, { 1043dcc812bSGreg Roach pointToLayer: function (feature, latlng) { 1053dcc812bSGreg Roach return new L.Marker(latlng, { 1063dcc812bSGreg Roach icon: L.BeautifyIcon.icon({ 1073130efd4SGreg Roach icon: 'bullseye fas', 1083dcc812bSGreg Roach borderColor: 'transparent', 1093130efd4SGreg Roach backgroundColor: feature.properties.iconcolor, 1103dcc812bSGreg Roach iconShape: 'marker', 1113130efd4SGreg Roach textColor: 'white', 1123dcc812bSGreg Roach }), 1133dcc812bSGreg Roach title: feature.properties.tooltip, 1143dcc812bSGreg Roach alt: feature.properties.tooltip, 11529eb5762SGreg Roach id: feature.id, 1163dcc812bSGreg Roach }) 1173dcc812bSGreg Roach .on('popupopen', function (e) { 11829eb5762SGreg Roach let item = sidebar.children('.gchart[data-id=' + e.target.feature.id + ']'); 1193dcc812bSGreg Roach item.addClass('messagebox'); 1203dcc812bSGreg Roach sidebar.scrollTo(item); 1213dcc812bSGreg Roach }) 1223dcc812bSGreg Roach .on('popupclose', function () { 12329eb5762SGreg Roach sidebar.children('.gchart').removeClass('messagebox'); 1243dcc812bSGreg Roach }); 1253dcc812bSGreg Roach }, 1263dcc812bSGreg Roach onEachFeature: function (feature, layer) { 1273dcc812bSGreg Roach if (feature.properties.polyline) { 1283dcc812bSGreg Roach let pline = L.polyline(feature.properties.polyline.points, feature.properties.polyline.options); 1293dcc812bSGreg Roach markers.addLayer(pline); 1303dcc812bSGreg Roach } 1313dcc812bSGreg Roach layer.bindPopup(feature.properties.summary); 1320d123f04SDavid Drury sidebar_content += `<li class="gchart px-md-2" data-id=${feature.id}>${feature.properties.summary}</li>`; 13329eb5762SGreg Roach }, 1343dcc812bSGreg Roach }); 1353dcc812bSGreg Roach markers.addLayer(geoJsonLayer); 13698579324SDavid Drury map.addLayer(markers); 1373dcc812bSGreg Roach if (zoom) { 1383dcc812bSGreg Roach map.setView(markers.getBounds().getCenter(), zoom); 13998579324SDavid Drury } else { 14045e60b72SGreg Roach map.fitBounds(markers.getBounds(), {padding: [50, 30]}); 1413dcc812bSGreg Roach } 1423dcc812bSGreg Roach } 14398579324SDavid Drury sidebar.append(sidebar_content); 1443dcc812bSGreg Roach }; 1453dcc812bSGreg Roach 1463dcc812bSGreg Roach /** 1473dcc812bSGreg Roach * @param elem 1483dcc812bSGreg Roach * @returns {$} 1493dcc812bSGreg Roach */ 1503dcc812bSGreg Roach $.fn.scrollTo = function (elem) { 1513dcc812bSGreg Roach let _this = $(this); 1523dcc812bSGreg Roach _this.animate({ 15329eb5762SGreg Roach scrollTop: elem.offset().top - _this.offset().top + _this.scrollTop(), 1543dcc812bSGreg Roach }); 1553dcc812bSGreg Roach return this; 1563dcc812bSGreg Roach }; 1573dcc812bSGreg Roach 1583dcc812bSGreg Roach// Activate marker popup when sidebar entry clicked 1593dcc812bSGreg Roach $(function () { 1600d123f04SDavid Drury sidebar 1613dcc812bSGreg Roach // open marker popup if sidebar event is clicked 1623dcc812bSGreg Roach .on('click', '.gchart', function (e) { 1633dcc812bSGreg Roach // first close any existing 1643dcc812bSGreg Roach map.closePopup(); 1653dcc812bSGreg Roach let eventId = $(this).data('id'); 1663dcc812bSGreg Roach //find the marker corresponding to the clicked event 1673dcc812bSGreg Roach let mkrLayer = markers.getLayers().filter(function (v) { 1683dcc812bSGreg Roach return typeof (v.feature) !== 'undefined' && v.feature.id === eventId; 1693dcc812bSGreg Roach }); 1703dcc812bSGreg Roach let mkr = mkrLayer.pop(); 1713dcc812bSGreg Roach // Unfortunately zoomToShowLayer zooms to maxZoom 1723dcc812bSGreg Roach // when all marker in a cluster have exactly the 1733dcc812bSGreg Roach // same co-ordinates 1743dcc812bSGreg Roach markers.zoomToShowLayer(mkr, function (e) { 1753dcc812bSGreg Roach mkr.openPopup(); 1763dcc812bSGreg Roach }); 17798579324SDavid Drury 1783dcc812bSGreg Roach return false; 1793dcc812bSGreg Roach }) 1803dcc812bSGreg Roach .on('click', 'a', function (e) { // stop click on a person also opening the popup 1813dcc812bSGreg Roach e.stopPropagation(); 1823dcc812bSGreg Roach }); 1833dcc812bSGreg Roach }); 1843dcc812bSGreg Roach 1853dcc812bSGreg Roach _drawMap(); 18698579324SDavid Drury _buildMapData(); 1873dcc812bSGreg Roach 18829eb5762SGreg Roach return 'Leaflet map interface for webtrees-2'; 1893dcc812bSGreg Roach})(); 1903dcc812bSGreg Roach</script> 1913dcc812bSGreg Roach<?php View::endpush() ?> 192