xref: /webtrees/resources/views/modules/pedigree-map/chart.phtml (revision fe18b1170b60ae6b04cc492983ad345e8206b16d)
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-md-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 minZoom = 2;
24
25    const sidebar = document.querySelector('.wt-pedigree-map-sidebar');
26
27    const scrollOptions = {
28      behavior: "smooth",
29      block: "start",
30      inline: "start"
31    };
32
33    let map = null;
34
35    // Map components
36    let markers = L.markerClusterGroup({
37      showCoverageOnHover: false,
38    });
39
40    /**
41     * Passed to resetControl to
42     * perform necessary reset actions on map
43     */
44     let resetCallback = function () {
45      map.flyToBounds(markers.getBounds(), {padding: [50, 30], maxZoom: 15 });
46      sidebar.firstElementChild.scrollIntoView(scrollOptions);
47    }
48
49    /**
50     *
51     * @private
52     */
53    let _drawMap = function () {
54      map = webtrees.buildLeafletJsMap('wt-map', config, resetCallback);
55    };
56
57    /**
58     *
59     * @private
60     */
61    let _buildMapData = function () {
62      let geoJson_data = <?= json_encode($data, JSON_THROW_ON_ERROR) ?>;
63
64      if (geoJson_data.features.length === 0) {
65        map.fitWorld();
66        sidebar.innerHTML = '<div class="bg-info text-white text-center">' + <?= json_encode(I18N::translate('Nothing to show'), JSON_THROW_ON_ERROR) ?> + '</div>';
67      } else {
68        sidebar.innerHTML = '';
69        let geoJsonLayer = L.geoJson(geoJson_data, {
70          pointToLayer: function (feature, latlng) {
71            return new L.Marker(latlng, {
72              icon: L.BeautifyIcon.icon({
73                icon: 'bullseye fas',
74                borderColor: 'transparent',
75                backgroundColor: feature.properties.iconcolor,
76                iconShape: 'marker',
77                textColor: 'white',
78              }),
79              title: feature.properties.tooltip,
80              alt: feature.properties.tooltip,
81              id: feature.id,
82            })
83              .on('popupopen', function (e) {
84                let item = document.querySelector('.gchart[data-wt-feature-id="' + e.target.feature.id + '"]');
85                item.classList.add('messagebox');
86                item.scrollIntoView(scrollOptions);
87              })
88              .on('popupclose', function () {
89                sidebar.childNodes.forEach(e => e.classList.remove('messagebox'));
90                sidebar.firstElementChild.scrollIntoView(scrollOptions);
91              });
92          },
93          onEachFeature: function (feature, layer) {
94            if (feature.properties.polyline) {
95              let pline = L.polyline(feature.properties.polyline.points, feature.properties.polyline.options);
96              markers.addLayer(pline);
97            }
98            layer.bindPopup(feature.properties.summary);
99            sidebar.innerHTML += `<li class="gchart px-md-2" data-wt-feature-id=${feature.id}>${feature.properties.summary}</li>`;
100          },
101        });
102        markers.addLayer(geoJsonLayer);
103        map.addLayer(markers);
104        map.fitBounds(markers.getBounds(), { padding: [50, 30], maxZoom: 15 });
105      }
106    };
107
108    window.onload = function() {
109    // Activate marker popup when sidebar entry clicked
110      sidebar.querySelectorAll('.gchart').forEach((element) => {
111        var eventId = parseInt(element.dataset.wtFeatureId);
112
113        element.addEventListener('click', () => {
114          // first close any existing
115          map.closePopup();
116          //find the marker corresponding to the clicked event
117          let mkrLayer = markers.getLayers().filter(function (v) {
118            return v.feature !== undefined && v.feature.id === eventId;
119          });
120
121          let mkr = mkrLayer.pop();
122
123          markers.zoomToShowLayer(mkr, function (e) {
124            mkr.openPopup();
125          });
126
127          return false;
128        });
129
130        // stop click on a person also opening the popup
131        element.querySelectorAll('a').forEach((el) => {
132          el.addEventListener('click', (e) => {
133            e.stopPropagation();
134          });
135        });
136      });
137    }
138
139    _drawMap();
140    _buildMapData();
141  })();
142</script>
143<?php View::endpush() ?>
144