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