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