document.addEventListener('DOMContentLoaded', function() { var avoidHighwaysCheckbox = document.getElementById('avoidHighways'); var useShortestCheckbox = document.getElementById('useShortest'); var avoidTollRoadsCheckbox = document.getElementById('avoidTollRoads'); var avoidFerriesCheckbox = document.getElementById('avoidFerries'); var avoidUnpavedCheckbox = document.getElementById('avoidUnpaved'); var points = []; var markers = []; var routePolyline = null; function calculateRoute() { if (points.length === 2) { var options = { "exclude_restrictions": true }; if (avoidHighwaysCheckbox && avoidHighwaysCheckbox.checked) { options.use_highways = 0; } if (useShortestCheckbox && useShortestCheckbox.checked) { options.use_shortest = true; } if (avoidTollRoadsCheckbox && avoidTollRoadsCheckbox.checked) { options.avoid_toll = true; } if (avoidFerriesCheckbox && avoidFerriesCheckbox.checked) { options.avoid_ferry = true; } if (avoidUnpavedCheckbox && avoidUnpavedCheckbox.checked) { options.avoid_unpaved = true; } var costing_options = { motorcycle: options }; var requestBody = { locations: [ { lat: points[0].lat, lon: points[0].lng }, { lat: points[1].lat, lon: points[1].lng } ], costing: "motorcycle", costing_options: costing_options }; fetch('/route', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(requestBody) }) .then(response => response.json()) .then(data => { var latlngs = decodePolyline6(data.trip.legs[0].shape); if (routePolyline) { map.removeLayer(routePolyline); } routePolyline = L.polyline(latlngs, { color: 'red', weight: 5}).addTo(map); map.fitBounds(routePolyline.getBounds()); }); } } map.on('click', function(e) { if (points.length < 2) { var marker = L.marker(e.latlng).addTo(map); markers.push(marker); points.push(e.latlng); marker.bindPopup(points.length === 1 ? "Start" : "End").openPopup(); } calculateRoute(); }); // Listen for changes on all checkboxes [ avoidHighwaysCheckbox, useShortestCheckbox, avoidTollRoadsCheckbox, avoidFerriesCheckbox, avoidUnpavedCheckbox ].forEach(function(checkbox) { if (checkbox) { checkbox.addEventListener('change', calculateRoute); } }); // Disable other checkboxes when "Use shortest route" is checked useShortestCheckbox.addEventListener('change', function() { var disable = useShortestCheckbox.checked; [ avoidHighwaysCheckbox, avoidTollRoadsCheckbox, avoidFerriesCheckbox, avoidUnpavedCheckbox ].forEach(function(cb) { cb.disabled = disable; }); }); // Adapted from Valhalla docs — polyline6 decoder for JS function decodePolyline6(encoded) { var coords = []; var index = 0, lat = 0, lng = 0; var shift = 0, result = 0, byte = null, latitude_change, longitude_change; var factor = Math.pow(10, 6); while (index < encoded.length) { byte = shift = result = 0; do { byte = encoded.charCodeAt(index++) - 63; result |= (byte & 0x1f) << shift; shift += 5; } while (byte >= 0x20); latitude_change = (result & 1) ? ~(result >> 1) : (result >> 1); shift = result = 0; do { byte = encoded.charCodeAt(index++) - 63; result |= (byte & 0x1f) << shift; shift += 5; } while (byte >= 0x20); longitude_change = (result & 1) ? ~(result >> 1) : (result >> 1); lat += latitude_change; lng += longitude_change; coords.push([lat / factor, lng / factor]); } return coords; } // Remove Markers function resetMarkers() { markers.forEach(function(marker) { map.removeLayer(marker); }); markers = []; points = []; if (routePolyline) { map.removeLayer(routePolyline); routePolyline = null; } } // Make resetMarkers available globally window.resetMarkers = resetMarkers; // Plot Route button logic document.getElementById('plotRouteBtn').addEventListener('click', function() { var sourceInput = document.getElementById('sourceInput'); var destInput = document.getElementById('destInput'); var sourceLat = parseFloat(sourceInput.dataset.lat); var sourceLon = parseFloat(sourceInput.dataset.lon); var destLat = parseFloat(destInput.dataset.lat); var destLon = parseFloat(destInput.dataset.lon); if (!isNaN(sourceLat) && !isNaN(sourceLon) && !isNaN(destLat) && !isNaN(destLon)) { // Remove old markers markers.forEach(function(marker) { map.removeLayer(marker); }); markers = []; points = []; // Add new markers var startMarker = L.marker([sourceLat, sourceLon]).addTo(map).bindPopup("Start").openPopup(); var endMarker = L.marker([destLat, destLon]).addTo(map).bindPopup("End").openPopup(); markers.push(startMarker, endMarker); points.push({lat: sourceLat, lng: sourceLon}, {lat: destLat, lng: destLon}); calculateRoute(); } else { alert("Please enter valid addresses for both start and destination."); } }); });