Updated backend/frontend
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
function geocode(query, callback) {
|
||||
fetch('https://nominatim.openstreetmap.org/search?format=json&q=' + encodeURIComponent(query))
|
||||
fetch('/geocode?format=json&q=' + encodeURIComponent(query))
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data && data.length > 0) {
|
||||
@@ -16,7 +16,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
navigator.geolocation.getCurrentPosition(function(position) {
|
||||
var lat = position.coords.latitude;
|
||||
var lon = position.coords.longitude;
|
||||
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lon}`)
|
||||
fetch(`/reverse?format=json&lat=${lat}&lon=${lon}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById(inputId).value = data.display_name || `${lat},${lon}`;
|
||||
@@ -54,7 +54,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
suggestionsBox.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
fetch('https://nominatim.openstreetmap.org/search?format=json&addressdetails=1&q=' + encodeURIComponent(value))
|
||||
fetch('/geocode?format=json&addressdetails=1&q=' + encodeURIComponent(value))
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
suggestionsBox.innerHTML = '';
|
||||
|
||||
@@ -1,171 +1,171 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>FreeMoto Navigation</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
|
||||
<style>
|
||||
html, body, #map {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#map {
|
||||
min-height: 100vh;
|
||||
min-width: 100vw;
|
||||
z-index: 1;
|
||||
}
|
||||
.nav-panel {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
max-width: 100vw;
|
||||
z-index: 1001;
|
||||
background: rgba(255,255,255,0.98);
|
||||
border-radius: 18px 18px 0 0;
|
||||
box-shadow: 0 -2px 16px rgba(0,0,0,0.18);
|
||||
padding: 12px 8px 8px 8px;
|
||||
overflow-y: auto;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
.nav-panel {
|
||||
left: 24px;
|
||||
width: 370px;
|
||||
max-width: 420px;
|
||||
border-radius: 18px;
|
||||
top: 24px;
|
||||
bottom: auto;
|
||||
box-shadow: 0 2px 16px rgba(0,0,0,0.18);
|
||||
}
|
||||
}
|
||||
#routeInfoCard {
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
#sourceSuggestions,
|
||||
#destSuggestions {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
z-index: 2000;
|
||||
width: 100%;
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
border-radius: 0 0 0.5rem 0.5rem;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
}
|
||||
.section-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-top: 1rem;
|
||||
color: #495057;
|
||||
}
|
||||
.card-icon {
|
||||
font-size: 2rem;
|
||||
margin-right: 0.5rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.btn-lg, .form-control {
|
||||
font-size: 1.2rem;
|
||||
padding: 0.7rem 1rem;
|
||||
}
|
||||
.form-check-label {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.input-group-text svg,
|
||||
.btn svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<div class="nav-panel shadow-lg">
|
||||
<div class="text-center mb-2">
|
||||
<span class="card-icon">🏍️</span>
|
||||
<span class="fs-4 fw-bold text-primary">FreeMoto</span>
|
||||
</div>
|
||||
<div id="routeInfoCard" class="alert alert-info d-none" role="alert"></div>
|
||||
<div class="mb-2">
|
||||
<div class="section-title">Route</div>
|
||||
<div class="input-group mb-2 position-relative">
|
||||
<span class="input-group-text" title="Start">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#0d6efd" class="bi bi-geo-alt" viewBox="0 0 16 16"><path d="M8 16s6-5.686 6-10A6 6 0 1 0 2 6c0 4.314 6 10 6 10zm0-7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></svg>
|
||||
</span>
|
||||
<input type="text" class="form-control" id="sourceInput" placeholder="Start address" autocomplete="off">
|
||||
<button class="btn btn-outline-secondary" type="button" id="useCurrentSource" title="Use current location">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#198754" class="bi bi-crosshair" viewBox="0 0 16 16"><path d="M8 15V1a7 7 0 1 1 0 14zm0-1a6 6 0 1 0 0-12 6 6 0 0 0 0 12z"/><path d="M8 8.5a.5.5 0 0 1-.5-.5V2.707l-2.146 2.147a.5.5 0 1 1-.708-.708l3-3a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V8a.5.5 0 0 1-.5.5z"/></svg>
|
||||
</button>
|
||||
<div id="sourceSuggestions" class="list-group position-absolute w-100" style="z-index: 2000;"></div>
|
||||
</div>
|
||||
<div class="input-group mb-2 position-relative">
|
||||
<span class="input-group-text" title="Destination">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#dc3545" class="bi bi-flag" viewBox="0 0 16 16"><path d="M14.778 2.222a.5.5 0 0 1 0 .707l-2.5 2.5a.5.5 0 0 1-.707 0l-2.5-2.5a.5.5 0 0 1 .707-.707L12 3.793l2.071-2.071a.5.5 0 0 1 .707 0z"/><path d="M2.5 15a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5z"/></svg>
|
||||
</span>
|
||||
<input type="text" class="form-control" id="destInput" placeholder="Destination address" autocomplete="off">
|
||||
<button class="btn btn-outline-secondary" type="button" id="useCurrentDest" title="Use current location">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#198754" class="bi bi-crosshair" viewBox="0 0 16 16"><path d="M8 15V1a7 7 0 1 1 0 14zm0-1a6 6 0 1 0 0-12 6 6 0 0 0 0 12z"/><path d="M8 8.5a.5.5 0 0 1-.5-.5V2.707l-2.146 2.147a.5.5 0 1 1-.708-.708l3-3a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V8a.5.5 0 0 1-.5.5z"/></svg>
|
||||
</button>
|
||||
<div id="destSuggestions" class="list-group position-absolute w-100" style="z-index: 2000;"></div>
|
||||
</div>
|
||||
<div class="d-grid gap-2 mb-2">
|
||||
<button type="button" id="plotRouteBtn" class="btn btn-success btn-lg">Plot Route</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-title">Route Options</div>
|
||||
<form>
|
||||
<div class="row g-2">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="avoidHighways">
|
||||
<label class="form-check-label" for="avoidHighways">Avoid freeways</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="useShortest">
|
||||
<label class="form-check-label" for="useShortest">Shortest route</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="avoidTollRoads">
|
||||
<label class="form-check-label" for="avoidTollRoads">Avoid tolls</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="avoidFerries">
|
||||
<label class="form-check-label" for="avoidFerries">Avoid ferries</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="avoidUnpaved">
|
||||
<label class="form-check-label" for="avoidUnpaved">Avoid unpaved</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="d-flex justify-content-between mt-3 mb-2">
|
||||
<button onclick="resetMarkers()" class="btn btn-primary btn-lg flex-fill me-2">Reset Points</button>
|
||||
<div class="btn-group flex-fill" role="group" aria-label="Zoom controls">
|
||||
<button type="button" class="btn btn-outline-secondary btn-lg" id="zoomInBtn" title="Zoom in">+</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-lg" id="zoomOutBtn" title="Zoom out">−</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-grid gap-2 mb-2">
|
||||
<button type="button" id="exportGpxBtn" class="btn btn-warning btn-lg">Export GPX</button>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
||||
<script src="/main.js"></script>
|
||||
<script src="/route.js"></script>
|
||||
<script src="/geolocate.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>FreeMoto Navigation</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
|
||||
<style>
|
||||
html, body, #map {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#map {
|
||||
min-height: 100vh;
|
||||
min-width: 100vw;
|
||||
z-index: 1;
|
||||
}
|
||||
.nav-panel {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
max-width: 100vw;
|
||||
z-index: 1001;
|
||||
background: rgba(255,255,255,0.98);
|
||||
border-radius: 18px 18px 0 0;
|
||||
box-shadow: 0 -2px 16px rgba(0,0,0,0.18);
|
||||
padding: 12px 8px 8px 8px;
|
||||
overflow-y: auto;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
.nav-panel {
|
||||
left: 24px;
|
||||
width: 370px;
|
||||
max-width: 420px;
|
||||
border-radius: 18px;
|
||||
top: 24px;
|
||||
bottom: auto;
|
||||
box-shadow: 0 2px 16px rgba(0,0,0,0.18);
|
||||
}
|
||||
}
|
||||
#routeInfoCard {
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
#sourceSuggestions,
|
||||
#destSuggestions {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
z-index: 2000;
|
||||
width: 100%;
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
border-radius: 0 0 0.5rem 0.5rem;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
}
|
||||
.section-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-top: 1rem;
|
||||
color: #495057;
|
||||
}
|
||||
.card-icon {
|
||||
font-size: 2rem;
|
||||
margin-right: 0.5rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.btn-lg, .form-control {
|
||||
font-size: 1.2rem;
|
||||
padding: 0.7rem 1rem;
|
||||
}
|
||||
.form-check-label {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.input-group-text svg,
|
||||
.btn svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<div class="nav-panel shadow-lg">
|
||||
<div class="text-center mb-2">
|
||||
<span class="card-icon">🏍️</span>
|
||||
<span class="fs-4 fw-bold text-primary">FreeMoto</span>
|
||||
</div>
|
||||
<div id="routeInfoCard" class="alert alert-info d-none" role="alert"></div>
|
||||
<div class="mb-2">
|
||||
<div class="section-title">Route</div>
|
||||
<div class="input-group mb-2 position-relative">
|
||||
<span class="input-group-text" title="Start">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#0d6efd" class="bi bi-geo-alt" viewBox="0 0 16 16"><path d="M8 16s6-5.686 6-10A6 6 0 1 0 2 6c0 4.314 6 10 6 10zm0-7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></svg>
|
||||
</span>
|
||||
<input type="text" class="form-control" id="sourceInput" placeholder="Start address" autocomplete="off">
|
||||
<button class="btn btn-outline-secondary" type="button" id="useCurrentSource" title="Use current location">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#198754" class="bi bi-crosshair" viewBox="0 0 16 16"><path d="M8 15V1a7 7 0 1 1 0 14zm0-1a6 6 0 1 0 0-12 6 6 0 0 0 0 12z"/><path d="M8 8.5a.5.5 0 0 1-.5-.5V2.707l-2.146 2.147a.5.5 0 1 1-.708-.708l3-3a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V8a.5.5 0 0 1-.5.5z"/></svg>
|
||||
</button>
|
||||
<div id="sourceSuggestions" class="list-group position-absolute w-100" style="z-index: 2000;"></div>
|
||||
</div>
|
||||
<div class="input-group mb-2 position-relative">
|
||||
<span class="input-group-text" title="Destination">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#dc3545" class="bi bi-flag" viewBox="0 0 16 16"><path d="M14.778 2.222a.5.5 0 0 1 0 .707l-2.5 2.5a.5.5 0 0 1-.707 0l-2.5-2.5a.5.5 0 0 1 .707-.707L12 3.793l2.071-2.071a.5.5 0 0 1 .707 0z"/><path d="M2.5 15a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5z"/></svg>
|
||||
</span>
|
||||
<input type="text" class="form-control" id="destInput" placeholder="Destination address" autocomplete="off">
|
||||
<button class="btn btn-outline-secondary" type="button" id="useCurrentDest" title="Use current location">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#198754" class="bi bi-crosshair" viewBox="0 0 16 16"><path d="M8 15V1a7 7 0 1 1 0 14zm0-1a6 6 0 1 0 0-12 6 6 0 0 0 0 12z"/><path d="M8 8.5a.5.5 0 0 1-.5-.5V2.707l-2.146 2.147a.5.5 0 1 1-.708-.708l3-3a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V8a.5.5 0 0 1-.5.5z"/></svg>
|
||||
</button>
|
||||
<div id="destSuggestions" class="list-group position-absolute w-100" style="z-index: 2000;"></div>
|
||||
</div>
|
||||
<div class="d-grid gap-2 mb-2">
|
||||
<button type="button" id="plotRouteBtn" class="btn btn-success btn-lg">Plot Route</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-title">Route Options</div>
|
||||
<form>
|
||||
<div class="row g-2">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="avoidHighways">
|
||||
<label class="form-check-label" for="avoidHighways">Avoid freeways</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="useShortest">
|
||||
<label class="form-check-label" for="useShortest">Shortest route</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="avoidTollRoads">
|
||||
<label class="form-check-label" for="avoidTollRoads">Avoid tolls</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="avoidFerries">
|
||||
<label class="form-check-label" for="avoidFerries">Avoid ferries</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="avoidUnpaved">
|
||||
<label class="form-check-label" for="avoidUnpaved">Avoid unpaved</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="d-flex justify-content-between mt-3 mb-2">
|
||||
<button onclick="resetMarkers()" class="btn btn-primary btn-lg flex-fill me-2">Reset Points</button>
|
||||
<div class="btn-group flex-fill" role="group" aria-label="Zoom controls">
|
||||
<button type="button" class="btn btn-outline-secondary btn-lg" id="zoomInBtn" title="Zoom in">+</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-lg" id="zoomOutBtn" title="Zoom out">−</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-grid gap-2 mb-2">
|
||||
<button type="button" id="exportGpxBtn" class="btn btn-warning btn-lg">Export GPX</button>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
||||
<script src="/main.js"></script>
|
||||
<script src="/route.js"></script>
|
||||
<script src="/geolocate.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
// Center on a default point
|
||||
var map = L.map('map', { zoomControl: false }).setView([53.866237, 10.676289], 18);
|
||||
|
||||
// Add OSM tiles
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}).addTo(map);
|
||||
|
||||
var userIcon = L.icon({
|
||||
iconUrl: '/maps-arrow.svg', // Add a motorcycle icon to your static folder
|
||||
iconSize: [40, 40]
|
||||
});
|
||||
|
||||
// Get users location
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.getCurrentPosition(function(position) {
|
||||
var lat = position.coords.latitude;
|
||||
var lon = position.coords.longitude;
|
||||
map.setView([lat, lon], 14);
|
||||
L.marker([lat, lon], {icon: userIcon}).addTo(map).bindPopup('You are here!');
|
||||
});
|
||||
}
|
||||
|
||||
// Custom Bootstrap zoom controls
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var zoomInBtn = document.getElementById('zoomInBtn');
|
||||
var zoomOutBtn = document.getElementById('zoomOutBtn');
|
||||
if (zoomInBtn && zoomOutBtn) {
|
||||
zoomInBtn.addEventListener('click', function() {
|
||||
map.zoomIn();
|
||||
});
|
||||
zoomOutBtn.addEventListener('click', function() {
|
||||
map.zoomOut();
|
||||
});
|
||||
}
|
||||
// Center on a default point
|
||||
var map = L.map('map', { zoomControl: false }).setView([53.866237, 10.676289], 18);
|
||||
|
||||
// Add OSM tiles
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}).addTo(map);
|
||||
|
||||
var userIcon = L.icon({
|
||||
iconUrl: '/maps-arrow.svg', // Add a motorcycle icon to your static folder
|
||||
iconSize: [40, 40]
|
||||
});
|
||||
|
||||
// Get users location
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.getCurrentPosition(function(position) {
|
||||
var lat = position.coords.latitude;
|
||||
var lon = position.coords.longitude;
|
||||
map.setView([lat, lon], 14);
|
||||
L.marker([lat, lon], {icon: userIcon}).addTo(map).bindPopup('You are here!');
|
||||
});
|
||||
}
|
||||
|
||||
// Custom Bootstrap zoom controls
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var zoomInBtn = document.getElementById('zoomInBtn');
|
||||
var zoomOutBtn = document.getElementById('zoomOutBtn');
|
||||
if (zoomInBtn && zoomOutBtn) {
|
||||
zoomInBtn.addEventListener('click', function() {
|
||||
map.zoomIn();
|
||||
});
|
||||
zoomOutBtn.addEventListener('click', function() {
|
||||
map.zoomOut();
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -10,26 +10,25 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
function calculateRoute() {
|
||||
if (points.length === 2) {
|
||||
var options = {
|
||||
"exclude_restrictions": true
|
||||
};
|
||||
var moto = {};
|
||||
// Avoid highways -> lower highway usage weight
|
||||
if (avoidHighwaysCheckbox && avoidHighwaysCheckbox.checked) {
|
||||
options.use_highways = 0;
|
||||
}
|
||||
if (useShortestCheckbox && useShortestCheckbox.checked) {
|
||||
options.use_shortest = true;
|
||||
}
|
||||
if (avoidTollRoadsCheckbox && avoidTollRoadsCheckbox.checked) {
|
||||
options.avoid_toll = true;
|
||||
moto.use_highways = 0.0; // 0..1 (0 avoids, 1 prefers)
|
||||
}
|
||||
// Avoid ferries -> lower ferry usage weight
|
||||
if (avoidFerriesCheckbox && avoidFerriesCheckbox.checked) {
|
||||
options.avoid_ferry = true;
|
||||
moto.use_ferry = 0.0; // 0..1
|
||||
}
|
||||
// Avoid unpaved -> exclude unpaved roads entirely
|
||||
if (avoidUnpavedCheckbox && avoidUnpavedCheckbox.checked) {
|
||||
options.avoid_unpaved = true;
|
||||
moto.exclude_unpaved = true;
|
||||
}
|
||||
// Avoid tolls -> exclude tolls
|
||||
if (avoidTollRoadsCheckbox && avoidTollRoadsCheckbox.checked) {
|
||||
moto.exclude_tolls = true;
|
||||
}
|
||||
|
||||
var costing_options = { motorcycle: options };
|
||||
var costing_options = { motorcycle: moto };
|
||||
|
||||
var requestBody = {
|
||||
locations: [
|
||||
@@ -37,8 +36,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
{ lat: points[1].lat, lon: points[1].lng }
|
||||
],
|
||||
costing: "motorcycle",
|
||||
costing_options: costing_options
|
||||
costing_options: costing_options,
|
||||
units: "kilometers"
|
||||
};
|
||||
if (useShortestCheckbox && useShortestCheckbox.checked) {
|
||||
requestBody.shortest = true; // top-level shortest flag
|
||||
}
|
||||
|
||||
fetch('/route', {
|
||||
method: 'POST',
|
||||
@@ -50,7 +53,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
var leg = data.trip && data.trip.legs && data.trip.legs[0];
|
||||
var infoCard = document.getElementById('routeInfoCard');
|
||||
if (leg && leg.summary && typeof leg.summary.length === 'number' && typeof leg.summary.time === 'number') {
|
||||
var distanceKm = (leg.summary.length / 1000).toFixed(1); // meters to km
|
||||
var distanceKm = (leg.summary.length).toFixed(1); // already in km
|
||||
var durationMin = Math.round(leg.summary.time / 60); // seconds to minutes
|
||||
var info = `<strong>Distance:</strong> ${distanceKm} km<br>
|
||||
<strong>Estimated Time:</strong> ${durationMin} min<br>
|
||||
@@ -201,7 +204,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
|
||||
function reverseGeocode(lat, lon, inputId) {
|
||||
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lon}`)
|
||||
fetch(`/reverse?format=json&lat=${lat}&lon=${lon}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
var input = document.getElementById(inputId);
|
||||
|
||||
Reference in New Issue
Block a user