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