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