Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify routing endpoint interface, always do reverse geocoding #5064

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
56 changes: 53 additions & 3 deletions app/assets/javascripts/index/directions-endpoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@ OSM.DirectionsEndpoint = function Endpoint(map, input, iconUrl, dragCallback, ch
function markerDragListener(e) {
var latlng = convertLatLngToZoomPrecision(e.target.getLatLng());

if (endpoint.geocodeRequest) endpoint.geocodeRequest.abort();
delete endpoint.geocodeRequest;

setLatLng(latlng);
setInputValueFromLatLng(latlng);
endpoint.value = input.val();
if (e.type === "dragend") getReverseGeocode();
dragCallback(e.type === "drag");
}

Expand All @@ -52,26 +56,54 @@ OSM.DirectionsEndpoint = function Endpoint(map, input, iconUrl, dragCallback, ch
endpoint.setValue(value);
}

endpoint.setValue = function (value, latlng) {
endpoint.setValue = function (value) {
if (endpoint.geocodeRequest) endpoint.geocodeRequest.abort();
delete endpoint.geocodeRequest;
input.removeClass("is-invalid");

var coordinatesMatch = value.match(/^\s*([+-]?\d+(?:\.\d*)?)(?:\s+|\s*[/,]\s*)([+-]?\d+(?:\.\d*)?)\s*$/);
var latlng = coordinatesMatch && L.latLng(coordinatesMatch[1], coordinatesMatch[2]);

if (latlng && endpoint.cachedReverseGeocode && endpoint.cachedReverseGeocode.latlng.equals(latlng)) {
setLatLng(latlng);
if (endpoint.cachedReverseGeocode.notFound) {
endpoint.value = value;
input.addClass("is-invalid");
} else {
endpoint.value = endpoint.cachedReverseGeocode.value;
}
input.val(endpoint.value);
changeCallback();
return;
}

endpoint.value = value;
removeLatLng();
input.removeClass("is-invalid");
input.val(value);

if (latlng) {
setLatLng(latlng);
setInputValueFromLatLng(latlng);
getReverseGeocode();
changeCallback();
} else if (endpoint.value) {
getGeocode();
}
};

endpoint.swapCachedReverseGeocodes = function (otherEndpoint) {
var g0 = endpoint.cachedReverseGeocode;
var g1 = otherEndpoint.cachedReverseGeocode;
delete endpoint.cachedReverseGeocode;
delete otherEndpoint.cachedReverseGeocode;
if (g0) otherEndpoint.cachedReverseGeocode = g0;
if (g1) endpoint.cachedReverseGeocode = g1;
};

function getGeocode() {
var viewbox = map.getBounds().toBBoxString(); // <sw lon>,<sw lat>,<ne lon>,<ne lat>
var geocodeUrl = OSM.NOMINATIM_URL + "search?q=" + encodeURIComponent(endpoint.value) + "&format=json&viewbox=" + viewbox;

if (endpoint.geocodeRequest) endpoint.geocodeRequest.abort();
endpoint.geocodeRequest = $.getJSON(geocodeUrl, function (json) {
delete endpoint.geocodeRequest;
if (json.length === 0) {
Expand All @@ -82,12 +114,30 @@ OSM.DirectionsEndpoint = function Endpoint(map, input, iconUrl, dragCallback, ch

setLatLng(L.latLng(json[0]));

endpoint.value = json[0].display_name;
input.val(json[0].display_name);

changeCallback();
});
}

function getReverseGeocode() {
var latlng = endpoint.latlng.clone();
var reverseGeocodeUrl = OSM.NOMINATIM_URL + "reverse?lat=" + latlng.lat + "&lon=" + latlng.lng + "&format=json";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to control the match precision here? Might this cause a location to "snap" to something a long way away?

Copy link
Collaborator Author

@AntonKhorev AntonKhorev Sep 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The location wouldn't snap in the same way is does on the currently deployed version. The pointer is not going to move, just the address would be too imprecise. Or too precise in an unhelpful way, for example when you zoom out to see a country and click on a city and you're told that you clicked on a house with this particular address.

Ultimately we should control the precision but I didn't want to do it in this pull request, see #4904 (comment)


endpoint.geocodeRequest = $.getJSON(reverseGeocodeUrl, function (json) {
delete endpoint.geocodeRequest;
if (!json || !json.display_name) {
endpoint.cachedReverseGeocode = { latlng: latlng, notFound: true };
return;
}

endpoint.value = json.display_name;
input.val(json.display_name);
endpoint.cachedReverseGeocode = { latlng: latlng, value: endpoint.value };
});
}

function setLatLng(ll) {
input
.attr("data-lat", ll.lat)
Expand Down
16 changes: 6 additions & 10 deletions app/assets/javascripts/index/directions.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,9 @@ OSM.Directions = function (map) {
if (coordTo) {
routeTo = coordTo.lat + "," + coordTo.lng;
}
endpoints[0].swapCachedReverseGeocodes(endpoints[1]);

OSM.router.route("/directions?" + Qs.stringify({
from: $("#route_to").val(),
to: $("#route_from").val(),
route: routeTo + ";" + routeFrom
}));
});
Expand Down Expand Up @@ -287,17 +286,14 @@ OSM.Directions = function (map) {
var ll = map.containerPointToLatLng(pt);
var precision = OSM.zoomPrecision(map.getZoom());
var value = ll.lat.toFixed(precision) + ", " + ll.lng.toFixed(precision);
var llWithPrecision = L.latLng(ll.lat.toFixed(precision), ll.lng.toFixed(precision));
endpoints[type === "from" ? 0 : 1].setValue(value, llWithPrecision);
endpoints[type === "from" ? 0 : 1].setValue(value);
});

endpoints[0].enable();
endpoints[1].enable();

var params = Qs.parse(location.search.substring(1)),
route = (params.route || "").split(";"),
from = route[0] && L.latLng(route[0].split(",")),
to = route[1] && L.latLng(route[1].split(","));
route = (params.route || "").split(";");

if (params.engine) {
var engineIndex = findEngine(params.engine);
Expand All @@ -307,10 +303,10 @@ OSM.Directions = function (map) {
}
}

endpoints[0].setValue(params.from || "", from);
endpoints[1].setValue(params.to || "", to);
endpoints[0].setValue(params.from || route[0] || "");
endpoints[1].setValue(params.to || route[1] || "");

map.setSidebarOverlaid(!from || !to);
map.setSidebarOverlaid(!endpoints[0].latlng || !endpoints[1].latlng);
};

page.load = function () {
Expand Down