xref: /webtrees/resources/views/admin/location-edit.phtml (revision 3c82483b6a98e1c59a16de018ef2ddd02872d16a)
1<?php
2
3use Fisharebest\Webtrees\I18N;
4use Fisharebest\Webtrees\View;
5
6?>
7
8<?= view('components/breadcrumbs', ['links' => $breadcrumbs]) ?>
9
10<h1><?= $title ?></h1>
11
12<div class="form-group row">
13    <div class="col-sm-12">
14        <div id="osm-map" class="wt-ajax-load col-sm-12 osm-admin-map" dir="ltr"></div>
15    </div>
16</div>
17
18<form method="post">
19    <?= csrf_field() ?>
20    <input type="hidden" name="place_id" value="<?= e($place_id) ?>">
21
22    <div class="form-group row">
23        <label class="col-form-label col-sm-1" for="new_place_name">
24            <?= I18N::translate('Place') ?>
25        </label>
26        <div class="col-sm-3">
27            <input type="text" id="new_place_name" name="new_place_name" value="<?= e($location->locationName()) ?>" class="form-control" required>
28        </div>
29
30        <input type="hidden" name="icon" id="icon" class="form-control" value="<?= e($location->icon()) ?>">
31    </div>
32
33    <div class="form-group row">
34        <label class="col-form-label col-sm-1" for="new_place_lati">
35            <?= I18N::translate('Latitude') ?>
36        </label>
37        <div class="col-sm-3">
38            <div class="input-group">
39                <input type="text" dir="ltr" id="new_place_lati" class="editable form-control" name="new_place_lati" required placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($location->latitude()) ?>"
40                >
41            </div>
42        </div>
43    </div>
44
45    <div class="form-group row">
46        <label class="col-form-label col-sm-1" for="new_place_long">
47            <?= I18N::translate('Longitude') ?>
48        </label>
49        <div class="col-sm-3">
50            <div class="input-group">
51                <input type="text" dir="ltr" id="new_place_long" class="editable form-control" name="new_place_long" required placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($location->longitude()) ?>"
52                >
53            </div>
54        </div>
55
56        <input type="hidden" id="new_zoom_factor" name="new_zoom_factor" value="<?= e($location->zoom()) ?>" class="form-control">
57    </div>
58
59    <div class="form-group row">
60        <div class="col-sm-10 offset-sm-1">
61            <button class="btn btn-primary" type="submit">
62                <?= /* I18N: A button label. */
63                I18N::translate('save')
64                ?>
65            </button>
66            <a class="btn btn-secondary" href="<?= e(route('map-data', ['parent_id' => $parent_id])) ?>">
67                <?= I18N::translate('cancel') ?>
68            </a>
69        </div>
70    </div>
71</form>
72
73<?php View::push('styles') ?>
74<style>
75    .osm-admin-map {
76        height: 55vh;
77        border: 1px solid darkGrey
78    }
79</style>
80<?php View::endpush() ?>
81
82<?php View::push('javascript') ?>
83<script>
84    'use strict';
85
86    window.WT_OSM_ADMIN = (function () {
87        const minZoom = 2;
88
89        let provider = <?= json_encode($provider) ?>;
90        let map = null;
91        let add_place = <?= json_encode($place_id === 0) ?>;
92
93        // map components
94
95        // postcss_image_inliner breaks the autodetection of image paths.
96        L.Icon.Default.imagePath = <?= json_encode(asset('css/images/')) ?>;
97
98        // draggable marker
99        let marker = L.marker(<?= json_encode([$location->latitude(), $location->longitude()]) ?>, {
100            draggable: true,
101        })
102            .on('dragend', function (e) {
103                let coords = marker.getLatLng();
104                map.panTo(coords);
105                $('#new_place_lati').val(Number(coords.lat).toFixed(5));
106                $('#new_place_long').val(Number(coords.lng).toFixed(5));
107                $('#new_zoom_factor').val(Number(map.getZoom()));
108            });
109
110        //reset map to initial state
111        let resetControl = L.Control.extend({
112            options: {
113                position: 'topleft'
114            },
115            onAdd: function (map) {
116                let container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom');
117                container.onclick = function () {
118                    map.fitBounds(<?= json_encode($location->boundingRectangle()) ?>);
119                    marker.setLatLng(<?= json_encode([$location->latitude(), $location->longitude()]) ?>);
120                    $('form').trigger('reset');
121                    return false;
122                };
123                let reset = <?= json_encode(I18N::translate('Reset to initial map state')) ?>;
124                let anchor = L.DomUtil.create('a', 'leaflet-control-reset', container);
125                anchor.setAttribute('aria-label', reset);
126                anchor.href = '#';
127                anchor.title = reset;
128                anchor.role = 'button';
129                let image = L.DomUtil.create('i', 'fas fa-redo', anchor);
130                image.alt = reset;
131
132                return container;
133            }
134        });
135
136        // zoom control with localised text
137        let zoomCtl = new L.control.zoom({
138            zoomInTitle:  <?= json_encode(I18N::translate('Zoom in')) ?>,
139            zoomOutTitle: <?= json_encode(I18N::translate('Zoom out')) ?>,
140        });
141
142        // Geocoder (place lookup)
143        let geocoder = new L.Control.geocoder({
144            defaultMarkGeocode: false,
145            expand: 'click',
146            showResultIcons: true,
147            query: '<?= e($location->locationName()) ?>',
148            placeholder: <?= json_encode(I18N::translate('Place')) ?>,
149            errorMessage: <?= json_encode(I18N::translate('Nothing found.')) ?>,
150            iconLabel: <?= json_encode(I18N::translate('Search')) ?>
151        })
152            .on('markgeocode', function (result) {
153                let coords = result.geocode.center;
154                let place = result.geocode.name.split(',', 1);
155                marker.setLatLng(coords);
156                map.panTo(coords);
157                if (add_place) {
158                    $('#new_place_name').val(place.shift());
159                }
160                $('#new_place_lati').val(Number(coords.lat).toFixed(5));
161                $('#new_place_long').val(Number(coords.lng).toFixed(5));
162                $('#new_zoom_factor').val(Number(map.getZoom()));
163            });
164
165        /**
166         *
167         * @private
168         */
169        $(function () {
170            // geocoder button tooltip
171            $('.leaflet-control-geocoder-icon')
172                .attr('title', <?= json_encode(I18N::translate('Search')) ?>);
173
174            $('.editable').on('change', function (e) {
175                let lat = $('#new_place_lati').val();
176                let lng = $('#new_place_long').val();
177                marker.setLatLng([lat, lng]);
178                map.panTo([lat, lng]);
179            });
180        });
181
182        // Create the map with all controls and layers
183        map = L.map('osm-map', {
184            minZoom: minZoom, // maxZoom set by leaflet-providers.js
185            zoomControl: false,   // remove default
186        })
187            .addControl(new resetControl())
188            .addControl(zoomCtl)
189            .addControl(geocoder)
190            .addLayer(marker)
191            .addLayer(L.tileLayer(provider.url, provider.options))
192            .fitBounds(<?= json_encode($location->boundingRectangle()) ?>)
193            .on('zoomend', function (e) {
194                $('#new_zoom_factor').val(map.getZoom());
195                map.panTo(marker.getLatLng());
196            });
197
198        return 'Leaflet map interface for webtrees-2';
199    })();
200</script>
201<?php View::endpush() ?>
202