1d70512abSGreg Roach<?php 2d70512abSGreg Roach 394e35917SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\MapDataList; 490949315SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\MapDataSave; 5d70512abSGreg Roachuse Fisharebest\Webtrees\I18N; 69a9dfcf7SGreg Roachuse Fisharebest\Webtrees\PlaceLocation; 7d70512abSGreg Roachuse Fisharebest\Webtrees\View; 8d70512abSGreg Roach 99a9dfcf7SGreg Roach/** 109a9dfcf7SGreg Roach * @var array<string,string> $breadcrumbs 119a9dfcf7SGreg Roach * @var string $latitude 12c9c6f2ecSGreg Roach * @var object $leaflet_config 139a9dfcf7SGreg Roach * @var string $longitude 149a9dfcf7SGreg Roach * @var PlaceLocation $location 159a9dfcf7SGreg Roach * @var array<array<float>> $map_bounds 1690949315SGreg Roach * @var array<float> $marker_position 179a9dfcf7SGreg Roach * @var PlaceLocation $parent 189a9dfcf7SGreg Roach * @var string $title 199a9dfcf7SGreg Roach */ 209a9dfcf7SGreg Roach 21d70512abSGreg Roach?> 22dd6b2bfcSGreg Roach 23dd6b2bfcSGreg Roach<?= view('components/breadcrumbs', ['links' => $breadcrumbs]) ?> 24dd6b2bfcSGreg Roach 25dd6b2bfcSGreg Roach<h1><?= $title ?></h1> 26dd6b2bfcSGreg Roach 27*afc2d190SGreg Roach<div class="row form-group mb-3"> 28e340fe65SGreg Roach <div class="col-sm-12"> 290b4092edSGreg Roach <div id="osm-map" class="wt-ajax-load col-sm-12 osm-admin-map" dir="ltr"></div> 30dd6b2bfcSGreg Roach </div> 31dd6b2bfcSGreg Roach</div> 32dd6b2bfcSGreg Roach 332a93faa6SGreg Roach<form method="post" action="<?= e(route(MapDataSave::class)) ?>"> 34dd6b2bfcSGreg Roach <?= csrf_field() ?> 352a93faa6SGreg Roach <input type="hidden" name="parent_id" value="<?= e($parent->id()) ?>"> 362a93faa6SGreg Roach <input type="hidden" name="place_id" value="<?= e($location->id()) ?>"> 37dd6b2bfcSGreg Roach 38*afc2d190SGreg Roach <div class="row form-group mb-3"> 39dd6b2bfcSGreg Roach <label class="col-form-label col-sm-1" for="new_place_name"> 40dd6b2bfcSGreg Roach <?= I18N::translate('Place') ?> 41dd6b2bfcSGreg Roach </label> 42e340fe65SGreg Roach <div class="col-sm-3"> 437dca5265SGreg Roach <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"> 44dd6b2bfcSGreg Roach </div> 45dd6b2bfcSGreg Roach </div> 46dd6b2bfcSGreg Roach 47*afc2d190SGreg Roach <div class="row form-group mb-3"> 4856a34df1SGreg Roach <label class="col-form-label col-sm-1" for="new_place_lati"> 49dd6b2bfcSGreg Roach <?= I18N::translate('Latitude') ?> 50dd6b2bfcSGreg Roach </label> 51dd6b2bfcSGreg Roach <div class="col-sm-3"> 52dd6b2bfcSGreg Roach <div class="input-group"> 5390949315SGreg Roach <input type="text" dir="ltr" id="new_place_lati" class="editable form-control" name="new_place_lati" placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($latitude) ?>"> 54dd6b2bfcSGreg Roach </div> 55dd6b2bfcSGreg Roach </div> 56e340fe65SGreg Roach </div> 57dd6b2bfcSGreg Roach 58*afc2d190SGreg Roach <div class="row form-group mb-3"> 5956a34df1SGreg Roach <label class="col-form-label col-sm-1" for="new_place_long"> 60dd6b2bfcSGreg Roach <?= I18N::translate('Longitude') ?> 61dd6b2bfcSGreg Roach </label> 62dd6b2bfcSGreg Roach <div class="col-sm-3"> 63dd6b2bfcSGreg Roach <div class="input-group"> 6490949315SGreg Roach <input type="text" dir="ltr" id="new_place_long" class="editable form-control" name="new_place_long" placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($longitude) ?>"> 65dd6b2bfcSGreg Roach </div> 66dd6b2bfcSGreg Roach </div> 67dd6b2bfcSGreg Roach </div> 68dd6b2bfcSGreg Roach 69*afc2d190SGreg Roach <div class="row form-group mb-3"> 70dd6b2bfcSGreg Roach <div class="col-sm-10 offset-sm-1"> 71dd6b2bfcSGreg Roach <button class="btn btn-primary" type="submit"> 72dd6b2bfcSGreg Roach <?= /* I18N: A button label. */ 73dd6b2bfcSGreg Roach I18N::translate('save') 74dd6b2bfcSGreg Roach ?> 75dd6b2bfcSGreg Roach </button> 7694e35917SGreg Roach <a class="btn btn-secondary" href="<?= e(route(MapDataList::class, ['parent_id' => $parent->id()])) ?>"> 77dd6b2bfcSGreg Roach <?= I18N::translate('cancel') ?> 78dd6b2bfcSGreg Roach </a> 79dd6b2bfcSGreg Roach </div> 80dd6b2bfcSGreg Roach </div> 81dd6b2bfcSGreg Roach</form> 82dd6b2bfcSGreg Roach 83dd6b2bfcSGreg Roach<?php View::push('styles') ?> 84dd6b2bfcSGreg Roach<style> 85dd6b2bfcSGreg Roach .osm-admin-map { 86dd6b2bfcSGreg Roach height: 55vh; 87dd6b2bfcSGreg Roach border: 1px solid darkGrey 88dd6b2bfcSGreg Roach } 89dd6b2bfcSGreg Roach</style> 90dd6b2bfcSGreg Roach<?php View::endpush() ?> 91dd6b2bfcSGreg Roach 92dd6b2bfcSGreg Roach<?php View::push('javascript') ?> 9374b9ba3fSGreg Roach<script> 94caa53803SDavid Drury 'use strict'; 95dd6b2bfcSGreg Roach 96dd6b2bfcSGreg Roach window.WT_OSM_ADMIN = (function () { 97728c8c27SGreg Roach const config = <?= json_encode($leaflet_config, JSON_THROW_ON_ERROR) ?>; 98728c8c27SGreg Roach const add_place = <?= json_encode($location->id() === null, JSON_THROW_ON_ERROR) ?>; 992cbb0620SDavid Drury 10075e7614aSGreg Roach // postcss_image_inliner breaks the autodetection of image paths. 101728c8c27SGreg Roach L.Icon.Default.imagePath = <?= json_encode(asset('css/images/'), JSON_THROW_ON_ERROR) ?>; 10275e7614aSGreg Roach 103caa53803SDavid Drury // draggable marker 104728c8c27SGreg Roach let marker = L.marker(<?= json_encode($marker_position, JSON_THROW_ON_ERROR) ?>, { 105caa53803SDavid Drury draggable: true, 106caa53803SDavid Drury }) 1079a9dfcf7SGreg Roach .on('dragend', function () { 108dd6b2bfcSGreg Roach let coords = marker.getLatLng(); 109dd6b2bfcSGreg Roach map.panTo(coords); 11062be603fSGreg Roach $('#new_place_lati').val(Number(coords.lat).toFixed(5)); 11162be603fSGreg Roach $('#new_place_long').val(Number(coords.lng).toFixed(5)); 112dd6b2bfcSGreg Roach }); 113dd6b2bfcSGreg Roach 114caa53803SDavid Drury //reset map to initial state 115caa53803SDavid Drury let resetControl = L.Control.extend({ 116caa53803SDavid Drury options: { 117caa53803SDavid Drury position: 'topleft' 118caa53803SDavid Drury }, 119caa53803SDavid Drury onAdd: function (map) { 120caa53803SDavid Drury let container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom'); 121caa53803SDavid Drury container.onclick = function () { 122728c8c27SGreg Roach map.fitBounds(<?= json_encode($map_bounds, JSON_THROW_ON_ERROR) ?>, {padding: [50, 30]}); 123728c8c27SGreg Roach marker.setLatLng(<?= json_encode([$location->latitude(), $location->longitude()], JSON_THROW_ON_ERROR) ?>); 124caa53803SDavid Drury $('form').trigger('reset'); 125caa53803SDavid Drury return false; 126caa53803SDavid Drury }; 127c9c6f2ecSGreg Roach let reset = config.i18n.reset; 128caa53803SDavid Drury let anchor = L.DomUtil.create('a', 'leaflet-control-reset', container); 129caa53803SDavid Drury anchor.setAttribute('aria-label', reset); 130caa53803SDavid Drury anchor.href = '#'; 131caa53803SDavid Drury anchor.title = reset; 132caa53803SDavid Drury anchor.role = 'button'; 133caa53803SDavid Drury let image = L.DomUtil.create('i', 'fas fa-redo', anchor); 134caa53803SDavid Drury image.alt = reset; 135dd6b2bfcSGreg Roach 136caa53803SDavid Drury return container; 137caa53803SDavid Drury } 138caa53803SDavid Drury }); 139dd6b2bfcSGreg Roach 140caa53803SDavid Drury // Geocoder (place lookup) 141caa53803SDavid Drury let geocoder = new L.Control.geocoder({ 142c9c6f2ecSGreg Roach position: 'bottomleft', 143caa53803SDavid Drury defaultMarkGeocode: false, 14422b076ddSGreg Roach expand: 'click', 145caa53803SDavid Drury showResultIcons: true, 146728c8c27SGreg Roach query: <?= json_encode($location->locationName(), JSON_THROW_ON_ERROR) ?>, 147728c8c27SGreg Roach placeholder: <?= json_encode(I18N::translate('Place'), JSON_THROW_ON_ERROR) ?>, 148728c8c27SGreg Roach errorMessage: <?= json_encode(I18N::translate('Nothing found.'), JSON_THROW_ON_ERROR) ?>, 149728c8c27SGreg Roach iconLabel: <?= json_encode(I18N::translate('Search'), JSON_THROW_ON_ERROR) ?> 150caa53803SDavid Drury }) 151caa53803SDavid Drury .on('markgeocode', function (result) { 152caa53803SDavid Drury let coords = result.geocode.center; 153164ab4fbSDavid Drury let place = result.geocode.name.split(',', 1).toString(); 154caa53803SDavid Drury marker.setLatLng(coords); 155caa53803SDavid Drury map.panTo(coords); 15662be603fSGreg Roach if (add_place) { 157164ab4fbSDavid Drury $('#new_place_name').val(place); 158caa53803SDavid Drury } 15962be603fSGreg Roach $('#new_place_lati').val(Number(coords.lat).toFixed(5)); 16062be603fSGreg Roach $('#new_place_long').val(Number(coords.lng).toFixed(5)); 16162be603fSGreg Roach }); 162caa53803SDavid Drury 163caa53803SDavid Drury /** 164caa53803SDavid Drury * @private 165caa53803SDavid Drury */ 166dd6b2bfcSGreg Roach $(function () { 167caa53803SDavid Drury // geocoder button tooltip 168caa53803SDavid Drury $('.leaflet-control-geocoder-icon') 169728c8c27SGreg Roach .attr('title', <?= json_encode(I18N::translate('Search'), JSON_THROW_ON_ERROR) ?>); 170caa53803SDavid Drury 1719a9dfcf7SGreg Roach $('.editable').on('change', function () { 172caa53803SDavid Drury let lat = $('#new_place_lati').val(); 173caa53803SDavid Drury let lng = $('#new_place_long').val(); 174dd6b2bfcSGreg Roach marker.setLatLng([lat, lng]); 175dd6b2bfcSGreg Roach map.panTo([lat, lng]); 176dd6b2bfcSGreg Roach }); 177dd6b2bfcSGreg Roach }); 178dd6b2bfcSGreg Roach 179c9c6f2ecSGreg Roach const map = webtrees.buildLeafletJsMap('osm-map', config) 180caa53803SDavid Drury .addControl(new resetControl()) 181caa53803SDavid Drury .addControl(geocoder) 182caa53803SDavid Drury .addLayer(marker) 183728c8c27SGreg Roach .fitBounds(<?= json_encode($map_bounds, JSON_THROW_ON_ERROR) ?>, {padding: [50, 30]}) 1849a9dfcf7SGreg Roach .on('zoomend', function () { 185d3a6a36aSGreg Roach if (!map.getBounds().contains(marker.getLatLng())) { 186d3a6a36aSGreg Roach map.panTo(marker.getLatLng()); 187d3a6a36aSGreg Roach } 188caa53803SDavid Drury }); 189dd6b2bfcSGreg Roach 190caa53803SDavid Drury return 'Leaflet map interface for webtrees-2'; 191dd6b2bfcSGreg Roach })(); 192dd6b2bfcSGreg Roach</script> 193dd6b2bfcSGreg Roach<?php View::endpush() ?> 194