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