13dcc812bSGreg Roach<?php use Fisharebest\Webtrees\I18N; ?> 23dcc812bSGreg Roach<?php use Fisharebest\Webtrees\View; ?> 33dcc812bSGreg Roach 43dcc812bSGreg Roach<div class="py-4"> 53dcc812bSGreg Roach <div class="row gchart osm-wrapper"> 6a2e602dbSGreg Roach <div id="osm-map" class="col-sm-9 wt-ajax-load osm-user-map" dir="ltr"></div> 78fca99e0SGreg Roach <ul class="col-sm-3 osm-sidebar wt-page-options-value list-unstyled p-0"></ul> 83dcc812bSGreg Roach </div> 93dcc812bSGreg Roach</div> 103dcc812bSGreg Roach 113dcc812bSGreg Roach<?php View::push('styles') ?> 123dcc812bSGreg Roach<style> 133dcc812bSGreg Roach .osm-wrapper, .osm-user-map { 148fca99e0SGreg Roach height: 75vh 153dcc812bSGreg Roach } 163dcc812bSGreg Roach 173dcc812bSGreg Roach .osm-sidebar { 183dcc812bSGreg Roach height: 100%; 193dcc812bSGreg Roach overflow-y: auto; 203dcc812bSGreg Roach padding: 0; 213dcc812bSGreg Roach margin: 0; 223dcc812bSGreg Roach border: 0; 233dcc812bSGreg Roach display: none; 243dcc812bSGreg Roach font-size: small; 253dcc812bSGreg Roach } 263dcc812bSGreg Roach 273dcc812bSGreg Roach .osm-sidebar .gchart { 283dcc812bSGreg Roach margin: 1px; 293dcc812bSGreg Roach padding: 2px 303dcc812bSGreg Roach } 313dcc812bSGreg Roach 323dcc812bSGreg Roach .osm-sidebar .gchart img { 333dcc812bSGreg Roach height: 15px; 343dcc812bSGreg Roach width: 25px 353dcc812bSGreg Roach } 363dcc812bSGreg Roach 373dcc812bSGreg Roach .osm-sidebar .border-danger:hover { 383dcc812bSGreg Roach cursor: not-allowed 393dcc812bSGreg Roach } 403dcc812bSGreg Roach</style> 413dcc812bSGreg Roach<?php View::endpush() ?> 423dcc812bSGreg Roach 433dcc812bSGreg Roach<?php View::push('javascript') ?> 443dcc812bSGreg Roach<script type="application/javascript"> 453dcc812bSGreg Roach "use strict"; 463dcc812bSGreg Roach 473dcc812bSGreg Roach window.WT_OSM = (function() { 483dcc812bSGreg Roach let baseData = { 493dcc812bSGreg Roach minZoom: 2, 503dcc812bSGreg Roach providerName: "OpenStreetMap.Mapnik", 513dcc812bSGreg Roach providerOptions: [], 523dcc812bSGreg Roach I18N: { 533dcc812bSGreg Roach zoomInTitle: <?= json_encode(I18N::translate('Zoom in')) ?>, 543dcc812bSGreg Roach zoomOutTitle: <?= json_encode(I18N::translate('Zoom out')) ?>, 553dcc812bSGreg Roach reset: <?= json_encode(I18N::translate('Reset to initial map state')) ?>, 563dcc812bSGreg Roach noData: <?= json_encode(I18N::translate('No mappable items')) ?>, 573dcc812bSGreg Roach error: <?= json_encode(I18N::translate('An unknown error occurred')) ?> 583dcc812bSGreg Roach } 593dcc812bSGreg Roach }; 603dcc812bSGreg Roach 613dcc812bSGreg Roach let map = null; 623dcc812bSGreg Roach let zoom = null; 633dcc812bSGreg Roach let markers = L.markerClusterGroup({ 643dcc812bSGreg Roach showCoverageOnHover: false 653dcc812bSGreg Roach }); 663dcc812bSGreg Roach 673dcc812bSGreg Roach let resetControl = L.Control.extend({ 683dcc812bSGreg Roach options: { 693dcc812bSGreg Roach position: 'topleft' 703dcc812bSGreg Roach }, 713dcc812bSGreg Roach 723dcc812bSGreg Roach onAdd: function (map) { 733dcc812bSGreg Roach let container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom'); 743dcc812bSGreg Roach container.onclick = function () { 753dcc812bSGreg Roach if (zoom) { 763dcc812bSGreg Roach map.flyTo(markers.getBounds().getCenter(), zoom); 773dcc812bSGreg Roach } else { 783dcc812bSGreg Roach map.flyToBounds(markers.getBounds().pad(0.2)); 793dcc812bSGreg Roach } 803dcc812bSGreg Roach return false; 813dcc812bSGreg Roach }; 823dcc812bSGreg Roach let anchor = L.DomUtil.create('a', 'leaflet-control-reset', container); 833dcc812bSGreg Roach anchor.href = '#'; 843dcc812bSGreg Roach anchor.title = baseData.I18N.reset; 853dcc812bSGreg Roach anchor.role = 'button'; 863dcc812bSGreg Roach $(anchor).attr('aria-label', 'reset'); 873dcc812bSGreg Roach let image = L.DomUtil.create('i', 'fas fa-redo', anchor); 883dcc812bSGreg Roach image.alt = baseData.I18N.reset; 893dcc812bSGreg Roach 903dcc812bSGreg Roach return container; 913dcc812bSGreg Roach }, 923dcc812bSGreg Roach }); 933dcc812bSGreg Roach 943dcc812bSGreg Roach /** 953dcc812bSGreg Roach * 963dcc812bSGreg Roach * @private 973dcc812bSGreg Roach */ 983dcc812bSGreg Roach let _drawMap = function () { 993dcc812bSGreg Roach map = L.map('osm-map', { 1003dcc812bSGreg Roach center : [0, 0], 1013dcc812bSGreg Roach minZoom : baseData.minZoom, // maxZoom set by leaflet-providers.js 1023dcc812bSGreg Roach zoomControl: false, // remove default 1033dcc812bSGreg Roach }); 1043dcc812bSGreg Roach L.tileLayer.provider(baseData.providerName, baseData.providerOptions).addTo(map); 1053dcc812bSGreg Roach L.control.zoom({ // Add zoom with localised text 1063dcc812bSGreg Roach zoomInTitle : baseData.I18N.zoomInTitle, 1073dcc812bSGreg Roach zoomOutTitle: baseData.I18N.zoomOutTitle, 1083dcc812bSGreg Roach }).addTo(map); 1093dcc812bSGreg Roach }; 1103dcc812bSGreg Roach 1113dcc812bSGreg Roach /** 1123dcc812bSGreg Roach * 1133dcc812bSGreg Roach * @param reference 1143dcc812bSGreg Roach * @param mapType 1153dcc812bSGreg Roach * @param Generations 1163dcc812bSGreg Roach * @private 1173dcc812bSGreg Roach */ 1183dcc812bSGreg Roach let _addLayer = function (reference, mapType, Generations) { 1193dcc812bSGreg Roach let geoJsonLayer; 1203dcc812bSGreg Roach let domObj = '.osm-sidebar'; 1213dcc812bSGreg Roach let sidebar = ''; 1223dcc812bSGreg Roach 1233dcc812bSGreg Roach $.getJSON("index.php", { 1243dcc812bSGreg Roach route: "module", 1253dcc812bSGreg Roach module: "pedigree-map", 1263dcc812bSGreg Roach action: "MapData", 1273dcc812bSGreg Roach reference: reference, 1283dcc812bSGreg Roach type: mapType, 1293dcc812bSGreg Roach generations: Generations, 130*71378461SGreg Roach ged: <?= json_encode($individual->tree()->name()) ?> 1313dcc812bSGreg Roach }) 1323dcc812bSGreg Roach .done(function (data, textStatus, jqXHR) { 1333dcc812bSGreg Roach if (jqXHR.status === 200 && data.features.length === 1) { 1343dcc812bSGreg Roach zoom = data.features[0].properties.zoom; 1353dcc812bSGreg Roach } 1363dcc812bSGreg Roach geoJsonLayer = L.geoJson(data, { 1373dcc812bSGreg Roach pointToLayer : function (feature, latlng) { 1383dcc812bSGreg Roach return new L.Marker(latlng, { 1393dcc812bSGreg Roach icon : L.BeautifyIcon.icon({ 1403dcc812bSGreg Roach icon : feature.properties.icon['name'], 1413dcc812bSGreg Roach borderColor : 'transparent', 1423dcc812bSGreg Roach backgroundColor: feature.valid ? feature.properties.icon['color'] : 'transparent', 1433dcc812bSGreg Roach iconShape : 'marker', 1443dcc812bSGreg Roach textColor : feature.valid ? 'white' : 'transparent', 1453dcc812bSGreg Roach }), 1463dcc812bSGreg Roach title: feature.properties.tooltip, 1473dcc812bSGreg Roach alt : feature.properties.tooltip, 1483dcc812bSGreg Roach id : feature.id 1493dcc812bSGreg Roach }) 1503dcc812bSGreg Roach .on('popupopen', function (e) { 1513dcc812bSGreg Roach let sidebar = $('.osm-sidebar'); 1523dcc812bSGreg Roach let item = sidebar.children(".gchart[data-id=" + e.target.feature.id + "]"); 1533dcc812bSGreg Roach item.addClass('messagebox'); 1543dcc812bSGreg Roach sidebar.scrollTo(item); 1553dcc812bSGreg Roach }) 1563dcc812bSGreg Roach .on('popupclose', function () { 1573dcc812bSGreg Roach $('.osm-sidebar').children(".gchart") 1583dcc812bSGreg Roach .removeClass('messagebox'); 1593dcc812bSGreg Roach }); 1603dcc812bSGreg Roach }, 1613dcc812bSGreg Roach onEachFeature: function (feature, layer) { 1623dcc812bSGreg Roach if (feature.properties.polyline) { 1633dcc812bSGreg Roach let pline = L.polyline(feature.properties.polyline.points, feature.properties.polyline.options); 1643dcc812bSGreg Roach markers.addLayer(pline); 1653dcc812bSGreg Roach } 1663dcc812bSGreg Roach layer.bindPopup(feature.properties.summary); 1673dcc812bSGreg Roach let myclass = feature.valid ? 'gchart' : 'border border-danger'; 1683dcc812bSGreg Roach sidebar += `<li class="${myclass}" data-id=${feature.id}>${feature.properties.summary}</li>`; 1693dcc812bSGreg Roach }, 1703dcc812bSGreg Roach }); 1713dcc812bSGreg Roach }) 1723dcc812bSGreg Roach .fail(function (jqXHR, textStatus, errorThrown) { 1733dcc812bSGreg Roach console.log(jqXHR, textStatus, errorThrown); 1743dcc812bSGreg Roach }) 1753dcc812bSGreg Roach .always(function (data_jqXHR, textStatus, jqXHR_errorThrown) { 1763dcc812bSGreg Roach switch (jqXHR_errorThrown.status) { 1773dcc812bSGreg Roach case 200: // Success 1783dcc812bSGreg Roach $(domObj).append(sidebar); 1793dcc812bSGreg Roach markers.addLayer(geoJsonLayer); 1803dcc812bSGreg Roach map 1813dcc812bSGreg Roach .addControl(new resetControl()) 1823dcc812bSGreg Roach .addLayer(markers) 1833dcc812bSGreg Roach .fitBounds(markers.getBounds().pad(0.2)); 1843dcc812bSGreg Roach if (zoom) { 1853dcc812bSGreg Roach map.setView(markers.getBounds().getCenter(), zoom); 1863dcc812bSGreg Roach } 1873dcc812bSGreg Roach break; 1883dcc812bSGreg Roach case 204: // No data 1893dcc812bSGreg Roach map.fitWorld(); 1903dcc812bSGreg Roach $(domObj).append('<div class="bg-info text-white">' + baseData.I18N.noData + '</div>'); 1913dcc812bSGreg Roach break; 1923dcc812bSGreg Roach default: // Anything else 1933dcc812bSGreg Roach map.fitWorld(); 1943dcc812bSGreg Roach $(domObj).append('<div class="bg-danger text-white">' + baseData.I18N.error + '</div>'); 1953dcc812bSGreg Roach } 1963dcc812bSGreg Roach $(domObj).slideDown(300); 1973dcc812bSGreg Roach }); 1983dcc812bSGreg Roach }; 1993dcc812bSGreg Roach 2003dcc812bSGreg Roach /** 2013dcc812bSGreg Roach * 2023dcc812bSGreg Roach * @param elem 2033dcc812bSGreg Roach * @returns {$} 2043dcc812bSGreg Roach */ 2053dcc812bSGreg Roach 2063dcc812bSGreg Roach $.fn.scrollTo = function (elem) { 2073dcc812bSGreg Roach let _this = $(this); 2083dcc812bSGreg Roach _this.animate({ 2093dcc812bSGreg Roach scrollTop: elem.offset().top - _this.offset().top + _this.scrollTop() 2103dcc812bSGreg Roach }); 2113dcc812bSGreg Roach return this; 2123dcc812bSGreg Roach }; 2133dcc812bSGreg Roach 2143dcc812bSGreg Roach /** 2153dcc812bSGreg Roach * 2163dcc812bSGreg Roach * @param reference string 2173dcc812bSGreg Roach * @param mapType string 2183dcc812bSGreg Roach * @param generations integer 2193dcc812bSGreg Roach * @private 2203dcc812bSGreg Roach */ 2213dcc812bSGreg Roach let _initialize = function (reference, mapType, generations) { 2223dcc812bSGreg Roach // Activate marker popup when sidebar entry clicked 2233dcc812bSGreg Roach $(function () { 2243dcc812bSGreg Roach $('.osm-sidebar') 2253dcc812bSGreg Roach // open marker popup if sidebar event is clicked 2263dcc812bSGreg Roach .on('click', '.gchart', function (e) { 2273dcc812bSGreg Roach // first close any existing 2283dcc812bSGreg Roach map.closePopup(); 2293dcc812bSGreg Roach let eventId = $(this).data('id'); 2303dcc812bSGreg Roach //find the marker corresponding to the clicked event 2313dcc812bSGreg Roach let mkrLayer = markers.getLayers().filter(function (v) { 2323dcc812bSGreg Roach return typeof(v.feature) !== 'undefined' && v.feature.id === eventId; 2333dcc812bSGreg Roach }); 2343dcc812bSGreg Roach let mkr = mkrLayer.pop(); 2353dcc812bSGreg Roach // Unfortunately zoomToShowLayer zooms to maxZoom 2363dcc812bSGreg Roach // when all marker in a cluster have exactly the 2373dcc812bSGreg Roach // same co-ordinates 2383dcc812bSGreg Roach markers.zoomToShowLayer(mkr, function (e) { 2393dcc812bSGreg Roach mkr.openPopup(); 2403dcc812bSGreg Roach }); 2413dcc812bSGreg Roach return false; 2423dcc812bSGreg Roach }) 2433dcc812bSGreg Roach .on('click', 'a', function (e) { // stop click on a person also opening the popup 2443dcc812bSGreg Roach e.stopPropagation(); 2453dcc812bSGreg Roach }); 2463dcc812bSGreg Roach }); 2473dcc812bSGreg Roach 2483dcc812bSGreg Roach _drawMap(); 2493dcc812bSGreg Roach _addLayer(reference, mapType, generations); 2503dcc812bSGreg Roach }; 2513dcc812bSGreg Roach 2523dcc812bSGreg Roach return { 2533dcc812bSGreg Roach /** 2543dcc812bSGreg Roach * 2553dcc812bSGreg Roach * @param reference string 2563dcc812bSGreg Roach * @param mapType string 2573dcc812bSGreg Roach * @param generations integer 2583dcc812bSGreg Roach */ 2593dcc812bSGreg Roach drawMap: function (reference, mapType, generations) { 2603dcc812bSGreg Roach mapType = typeof mapType !== 'undefined' ? mapType : 'individual'; 2613dcc812bSGreg Roach generations = typeof generations !== 'undefined' ? generations : null; 2623dcc812bSGreg Roach _initialize(reference, mapType, generations); 2633dcc812bSGreg Roach } 2643dcc812bSGreg Roach }; 2653dcc812bSGreg Roach })(); 2663dcc812bSGreg Roach 267*71378461SGreg Roach WT_OSM.drawMap(<?= json_encode($individual->xref()) ?>, <?= json_encode($type) ?>, <?= json_encode($generations ?? null) ?>); 2683dcc812bSGreg Roach</script> 2693dcc812bSGreg Roach<?php View::endpush() ?> 270