xref: /webtrees/resources/views/admin/location-edit.phtml (revision 3430c0bab1304f028145cca3ec085308fb0390b5)
1<?php
2
3use Fisharebest\Webtrees\Http\RequestHandlers\MapDataList;
4use Fisharebest\Webtrees\Http\RequestHandlers\MapDataSave;
5use Fisharebest\Webtrees\I18N;
6use Fisharebest\Webtrees\PlaceLocation;
7use Fisharebest\Webtrees\View;
8
9/**
10 * @var array<string,string> $breadcrumbs
11 * @var string               $latitude
12 * @var object               $leaflet_config
13 * @var string               $longitude
14 * @var PlaceLocation        $location
15 * @var array<array<float>>  $map_bounds
16 * @var array<float>         $marker_position
17 * @var PlaceLocation        $parent
18 * @var string               $title
19 */
20
21?>
22
23<?= view('components/breadcrumbs', ['links' => $breadcrumbs]) ?>
24
25<h1><?= $title ?></h1>
26
27<div id="wt-map" class="wt-ajax-load mb-3 border wt-location-edit-map" dir="ltr"></div>
28
29<form method="post" action="<?= e(route(MapDataSave::class)) ?>">
30    <input type="hidden" name="parent_id" value="<?= e($parent->id()) ?>">
31    <input type="hidden" name="place_id" value="<?= e($location->id()) ?>">
32
33    <div class="row mb-3">
34        <label class="col-form-label col-sm-1" for="new_place_name">
35            <?= I18N::translate('Place') ?>
36        </label>
37        <div class="col-sm-3">
38            <input type="text" id="new_place_name" name="new_place_name" value="<?= e($location->locationName()) ?>" class="form-control" required="required" maxlength="120" pattern="[^,]+" dir="auto">
39        </div>
40    </div>
41
42    <div class="row mb-3">
43        <label class="col-form-label col-sm-1" for="new_place_lati">
44            <?= I18N::translate('Latitude') ?>
45        </label>
46        <div class="col-sm-3">
47            <div class="input-group">
48                <input type="text" dir="ltr" id="new_place_lati" class="editable form-control" name="new_place_lati" placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($latitude) ?>">
49            </div>
50        </div>
51    </div>
52
53    <div class="row mb-3">
54        <label class="col-form-label col-sm-1" for="new_place_long">
55            <?= I18N::translate('Longitude') ?>
56        </label>
57        <div class="col-sm-3">
58            <div class="input-group">
59                <input type="text" dir="ltr" id="new_place_long" class="editable form-control" name="new_place_long" placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($longitude) ?>">
60            </div>
61        </div>
62    </div>
63
64    <div class="row mb-3">
65        <div class="col-sm-10 offset-sm-1">
66            <button class="btn btn-primary" type="submit">
67                <?= /* I18N: A button label. */
68                I18N::translate('save')
69                ?>
70            </button>
71            <a class="btn btn-secondary" href="<?= e(route(MapDataList::class, ['parent_id' => $parent->id()])) ?>">
72                <?= I18N::translate('cancel') ?>
73            </a>
74        </div>
75    </div>
76
77    <?= csrf_field() ?>
78</form>
79
80<?php View::push('javascript') ?>
81<script>
82  'use strict';
83
84  (function () {
85    const config = <?= json_encode($leaflet_config, JSON_THROW_ON_ERROR) ?>;
86    const add_place = <?= json_encode($location->id() === null, JSON_THROW_ON_ERROR) ?>;
87
88    let new_place_lati = document.getElementById('new_place_lati');
89    let new_place_long = document.getElementById('new_place_long');
90
91    // postcss_image_inliner breaks the autodetection of image paths.
92    L.Icon.Default.imagePath = <?= json_encode(asset('css/images/'), JSON_THROW_ON_ERROR) ?>;
93
94    // draggable marker
95    let marker = L.marker(<?= json_encode($marker_position, JSON_THROW_ON_ERROR) ?>, {
96      draggable: true,
97    })
98    .on('dragend', function () {
99      let coords = marker.getLatLng();
100      map.panTo(coords);
101      new_place_lati.value = Number(coords.lat).toFixed(5);
102      new_place_long.value = Number(coords.lng).toFixed(5);
103    });
104
105    /**
106     * Passed to resetControl to
107     * perform necessary reset actions on map
108     */
109     let resetCallback = function () {
110      map.fitBounds(<?= json_encode($map_bounds, JSON_THROW_ON_ERROR) ?>, {padding: [50, 30]});
111      marker.setLatLng(<?= json_encode($marker_position, JSON_THROW_ON_ERROR) ?>);
112      document.querySelector('form').reset();
113    }
114
115    // Geocoder (place lookup)
116    let geocoder = new L.Control.geocoder({
117      position: 'bottomleft',
118      defaultMarkGeocode: false,
119      expand: 'click',
120      showResultIcons: true,
121      query: <?= json_encode($location->locationName(), JSON_THROW_ON_ERROR) ?>,
122      placeholder: <?= json_encode(I18N::translate('Place'), JSON_THROW_ON_ERROR) ?>,
123      errorMessage: <?= json_encode(I18N::translate('Nothing found.'), JSON_THROW_ON_ERROR) ?>,
124      iconLabel: <?= json_encode(I18N::translate('Search'), JSON_THROW_ON_ERROR) ?>
125    })
126    .on('markgeocode', function (result) {
127      let coords = result.geocode.center;
128      let place = result.geocode.name.split(',', 1).toString();
129      marker.setLatLng(coords);
130      map.panTo(coords);
131      if (add_place) {
132        document.getElementById('new_place_name').value = place
133      }
134      new_place_lati.value = Number(coords.lat).toFixed(5);
135      new_place_long.value = Number(coords.lng).toFixed(5);
136    });
137
138    const map = webtrees.buildLeafletJsMap('wt-map', config, resetCallback)
139      .addControl(geocoder)
140      .addLayer(marker)
141      .fitBounds(<?= json_encode($map_bounds, JSON_THROW_ON_ERROR) ?>, {padding: [50, 30]})
142      .on('zoomend', function () {
143        if (!map.getBounds().contains(marker.getLatLng())) {
144          map.panTo(marker.getLatLng());
145        }
146    });
147
148    document.querySelectorAll('.editable').forEach((element) => {
149      element.addEventListener('change', () => {
150        let lat = new_place_lati.value;
151        let lng = new_place_long.value;
152        marker.setLatLng([lat, lng]);
153        map.panTo([lat, lng]);
154      });
155    });
156
157    window.onload = function() {
158      let icon = document.querySelector('.leaflet-control-geocoder-icon');
159      icon.setAttribute('title', <?= json_encode(I18N::translate('Search'), JSON_THROW_ON_ERROR) ?>);
160    }
161  })();
162</script>
163<?php View::endpush() ?>
164