Add search/route to location hash

pull/54/merge
Candid Dauth 2016-10-19 17:52:33 +03:00
rodzic 5f28ad96ea
commit e96e259ab7
5 zmienionych plików z 177 dodań i 77 usunięć

Wyświetl plik

@ -1,6 +1,6 @@
(function(fm, $, ng, undefined) {
fm.app.factory("fmMapHash", function() {
fm.app.factory("fmMapHash", function($rootScope, fmUtils) {
return function(map) {
var hashControl = new L.Hash(map.map);
@ -16,21 +16,33 @@
args = hash.split("/");
var ret = L.Hash.parseHash(args.slice(0, 3).join("/"));
if(ret) {
// This gets called just in L.Hash.update(), so we can already add/remove the layers here
var l = args[3] && args[3].split("-");
if(l && l.length > 0) {
for(var i in map.layers) {
if(l.indexOf(i) == -1) {
if(map.map.hasLayer(map.layers[i]))
map.map.removeLayer(map.layers[i]);
} else if(!map.map.hasLayer(map.layers[i]))
map.map.addLayer(map.layers[i]);
}
// This gets called just in L.Hash.update(), so we can already add/remove the layers here
var l = args[3] && args[3].split("-");
if(l && l.length > 0) {
for(var i in map.layers) {
if(l.indexOf(i) == -1) {
if(map.map.hasLayer(map.layers[i]))
map.map.removeLayer(map.layers[i]);
} else if(!map.map.hasLayer(map.layers[i]))
map.map.addLayer(map.layers[i]);
}
}
var routeParams = args.slice(4);
if(routeParams.length >= 2) {
var mode = null;
if(routeParams.length > 2 && [ "car", "bicycle", "pedestrian" ].indexOf(routeParams[routeParams.length-1]) != -1)
mode = routeParams.pop();
map.searchUi.route(routeParams, mode, !!ret);
} else if(routeParams.length == 1) {
map.searchUi.search(routeParams[0], !!ret, !fmUtils.isSearchId(routeParams[0]));
}
return ret;
};
}.fmWrapApply($rootScope);
hashControl.formatHash = function(mapObj) {
var ret = L.Hash.formatHash(mapObj);
@ -43,6 +55,10 @@
ret += "/" + l.join("-");
var searchHash = map.searchUi.getCurrentSearchForHash();
if(searchHash)
ret += "/" + searchHash.join("/");
return ret;
};
@ -53,6 +69,7 @@
map.map.on("layeradd", hashControl.onMapMove, hashControl);
map.map.on("layerremove", hashControl.onMapMove, hashControl);
map.mapEvents.$on("searchchange", hashControl.onMapMove.bind(hashControl));
function decodeQueryString(str) {
var obj = { };
@ -124,7 +141,7 @@
});
if(obj.c && obj.c.s && obj.c.s.medium)
ret.push(obj.c.s.medium);
ret.push(obj.c.s.medium != "foot" ? obj.c.s.medium : "pedestrian");
}
return ret;

Wyświetl plik

@ -45,9 +45,6 @@
if(destination.suggestionQuery == destination.query)
return resolve();
destination.suggestions = [ ];
destination.suggestionQuery = null;
destination.selectedSuggestionIdx = null;
if(destination.query.trim() != "") {
var query = destination.query;
@ -60,6 +57,9 @@
return reject(err);
}
if(fmUtils.isSearchId(query) && results.length > 0 && results[0].display_name)
destination.query = query = results[0].display_name;
destination.suggestions = results;
destination.suggestionQuery = query;
destination.selectedSuggestionIdx = 0;
@ -70,7 +70,7 @@
});
};
scope.route = function(dragging) {
scope.route = function(dragging, noZoom) {
if(!dragging)
scope.reset();
@ -79,15 +79,14 @@
return $q.all(scope.destinations.map(scope.loadSuggestions)).then(function() {
points = scope.destinations.map(function(destination) {
if(destination.suggestions.length == null)
if(destination.suggestions.length == 0)
throw "No place has been found for search term “" + destination.query + "”.";
var sug = destination.suggestions[destination.selectedSuggestionIdx] || destination.suggestions[0];
return { lat: sug.lat, lon: sug.lon };
return destination.suggestions[destination.selectedSuggestionIdx] || destination.suggestions[0];
});
return $q(function(resolve, reject) {
map.socket.emit("getRoute", { destinations: points, mode: mode }, function(err, res) {
map.socket.emit("getRoute", { destinations: points.map(function(point) { return { lat: point.lat, lon: point.lon }; }), mode: mode }, function(err, res) {
err ? reject(err) : resolve(res);
});
});
@ -96,7 +95,10 @@
route.routeMode = mode;
scope.routeObj = route;
renderRoute(dragging);
scope.routeError = null;
renderRoute(dragging, noZoom);
map.mapEvents.$emit("searchchange");
}).catch(function(err) {
scope.routeError = err;
});
@ -132,7 +134,7 @@
}
}
map.linesUi.createLine(type, scope.routeObj.routePoints, { mode: scope.routeObj.routeMode });
map.linesUi.createLine(type, scope.routeObj.routePoints.map(function(point) { return { lat: point.lat, lon: point.lon }; }), { mode: scope.routeObj.routeMode });
scope.clear();
};
@ -146,7 +148,7 @@
var markers = [ ];
var recalcRoute = fmUtils.minInterval(dragTimeout, false);
function renderRoute(dragging) {
function renderRoute(dragging, noZoom) {
clearRoute(dragging);
routeLayer = L.polyline(scope.routeObj.trackPoints.map(function(it) { return [ it.lat, it.lon ] }), lineStyle).addTo(map.map);
@ -167,7 +169,8 @@
}.fmWrapApply(scope));
if(!dragging) {
map.map.flyToBounds(routeLayer.getBounds());
if(!noZoom)
map.map.flyToBounds(routeLayer.getBounds());
// Render markers
@ -240,7 +243,8 @@
lon: latlng.lng,
display_name: disp,
short_name: disp,
type: "coordinates"
type: "coordinates",
id: disp
} ]
};
}
@ -277,7 +281,6 @@
},
setFrom: function(from, suggestions, selectedSuggestion) {
console.log("setFrom", from);
_setDestination(scope.destinations[0], from, suggestions, selectedSuggestion);
},
@ -292,8 +295,26 @@
_setDestination(scope.destinations[scope.destinations.length-1], to, suggestions, selectedSuggestion);
},
submit: function() {
scope.route();
setMode: function(mode) {
scope.routeMode = mode;
},
getQueries: function() {
if(scope.routeObj) {
return scope.routeObj.routePoints.map(function(point) {
return point.id;
});
}
},
getMode: function(mode) {
if(scope.routeObj) {
return scope.routeObj.routeMode;
}
},
submit: function(noZoom) {
scope.route(noZoom);
}
};
routeUi.hide();

Wyświetl plik

@ -11,7 +11,7 @@
scope.showAll = false;
scope.activeResult = null;
scope.search = function() {
scope.search = function(noZoom) {
scope.searchResults = null;
scope.loadedSearchString = "";
clearRenders();
@ -34,41 +34,54 @@
if(err)
return map.messages.showMessage("danger", err);
if(fmUtils.isSearchId(q) && results.length > 0 && results[0].display_name)
scope.searchString = q = results[0].display_name;
scope.loadedSearchString = q;
map.mapEvents.$emit("searchchange");
if(typeof results == "string")
loadSearchResults(parseFiles([ results ]));
loadSearchResults(parseFiles([ results ]), noZoom);
else
loadSearchResults(results);
loadSearchResults(results, noZoom);
});
}
};
scope.showResult = function(result) {
scope.showResult = function(result, noZoom) {
if(scope.showAll) {
_flyToBounds(layerGroup.getBounds());
if(!noZoom)
_flyToBounds(layerGroup.getBounds());
result.marker ? result.marker.openPopup() : result.layer.openPopup();
} else {
clearRenders();
renderResult(scope.loadedSearchString, scope.searchResults, result, true, layerGroup);
if(result.lat && result.lon && result.zoom)
map.map.flyTo([ result.lat, result.lon ], result.zoom);
else if(result.boundingbox)
_flyToBounds(L.latLngBounds([ [ result.boundingbox[0], result.boundingbox[3 ] ], [ result.boundingbox[1], result.boundingbox[2] ] ]));
else if(result.layer)
_flyToBounds(result.layer.getBounds());
if(!noZoom) {
if(result.lat && result.lon && result.zoom)
map.map.flyTo([ result.lat, result.lon ], result.zoom);
else if(result.boundingbox)
_flyToBounds(L.latLngBounds([ [ result.boundingbox[0], result.boundingbox[3 ] ], [ result.boundingbox[1], result.boundingbox[2] ] ]));
else if(result.layer)
_flyToBounds(result.layer.getBounds());
}
}
map.mapEvents.$emit("searchchange");
};
scope.showAllResults = function() {
scope.showAllResults = function(noZoom) {
clearRenders();
for(var i=0; i<scope.searchResults.length; i++)
renderResult(scope.loadedSearchString, scope.searchResults, scope.searchResults[i], false, layerGroup);
_flyToBounds(layerGroup.getBounds());
if(!noZoom)
_flyToBounds(layerGroup.getBounds());
map.mapEvents.$emit("searchchange");
};
scope.showRoutingForm = function() {
@ -125,13 +138,13 @@
map.map.flyTo(bounds.getCenter(), Math.min(15, map.map.getBoundsZoom(bounds)));
}
function loadSearchResults(results) {
function loadSearchResults(results, noZoom) {
clearRenders();
scope.searchResults = results;
if(results && results.length > 0)
scope.showAll ? scope.showAllResults() : scope.showResult(scope.searchResults[0]);
scope.showAll ? scope.showAllResults(noZoom) : scope.showResult(scope.searchResults[0], noZoom);
}
function parseFiles(files) {
@ -355,15 +368,42 @@
el.hide();
},
search: function(query) {
search: function(query, noZoom, showAll) {
if(query != null)
scope.searchString = query;
scope.search();
if(showAll != null)
scope.showAll = showAll;
scope.search(noZoom);
},
showFiles: function(files) {
loadSearchResults(parseFiles(files));
},
route: function(destinations, mode, noZoom) {
searchUi.hide();
routeUi.show();
routeUi.setQueries(destinations);
if(mode)
routeUi.setMode(mode);
routeUi.submit(noZoom);
},
getCurrentSearchForHash: function() {
if(el.is(":visible")) {
if(!scope.showAll && scope.activeResult && scope.activeResult.id)
return [ scope.activeResult.id ];
else if(scope.loadedSearchString)
return [ scope.loadedSearchString ];
} else {
var queries = routeUi.getQueries();
if(queries)
return queries.concat([ routeUi.getMode() ]);
}
}
};

Wyświetl plik

@ -435,6 +435,10 @@
});
};
fmUtils.isSearchId = function(string) {
return string && string.match(/^[nwr]\d+$/i);
};
return fmUtils;
});

Wyświetl plik

@ -70,42 +70,61 @@ function find(query, loadUrls) {
return loadUrl(query);
}
var lonlat_match = query.match(/^(geo\s*:\s*)?(-?\s*\d+([.,]\d+)?)\s*[,;]\s*(-?\s*\d+([.,]\d+)?)(\s*\?z\s*=\s*(\d+))?$/)
if(lonlat_match)
{ // Coordinates
var lonlat = {
lat: 1*lonlat_match[2].replace(",", ".").replace(/\s+/, ""),
lon : 1*lonlat_match[4].replace(",", ".").replace(/\s+/, ""),
zoom : lonlat_match[7] != null ? 1*lonlat_match[7] : null
};
var lonlat_match = query.match(/^(geo\s*:\s*)?(-?\s*\d+([.,]\d+)?)\s*[,;]\s*(-?\s*\d+([.,]\d+)?)(\s*\?z\s*=\s*(\d+))?$/);
var osm_match = query.match(/^([nwr])(\d+)$/i);
if(lonlat_match || osm_match)
{ // Reverse search
var url = nameFinderUrl + "/reverse?format=json&addressdetails=1&polygon_geojson=1&extratags=1&namedetails=1";
var lonlat;
if(lonlat_match) {
lonlat = {
lat: 1*lonlat_match[2].replace(",", ".").replace(/\s+/, ""),
lon : 1*lonlat_match[4].replace(",", ".").replace(/\s+/, ""),
zoom : lonlat_match[7] != null ? 1*lonlat_match[7] : null
};
url += "&lat=" + lonlat.lat
+ "&lon=" + lonlat.lon
+ "&zoom=" + (lonlat.zoom != null ? (lonlat.zoom >= 12 ? lonlat.zoom+2 : lonlat.zoom) : 17);
} else {
url += "&osm_type=" + osm_match[1].toUpperCase()
+ "&osm_id=" + osm_match[2]
}
return request({
url: nameFinderUrl + "/reverse?format=json&addressdetails=1&polygon_geojson=1&extratags=1&namedetails=1"
+ "&lat=" + lonlat.lat
+ "&lon=" + lonlat.lon
+ "&zoom=" + (lonlat.zoom != null ? (lonlat.zoom >= 12 ? lonlat.zoom+2 : lonlat.zoom) : 17),
url: url,
json: true
}).then(function(body) {
if(!body || body) {
var name = utils.round(lonlat.lat, 5) + ", " + utils.round(lonlat.lon, 5);
return [ {
lat: lonlat.lat,
lon : lonlat.lon,
type : "coordinates",
short_name: name,
display_name : name,
zoom: lonlat.zoom != null ? lonlat.zoom : 15,
icon: "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png"
} ];
if(!body || body.error) {
if(lonlat) {
var name = utils.round(lonlat.lat, 5) + ", " + utils.round(lonlat.lon, 5);
return [ {
lat: lonlat.lat,
lon : lonlat.lon,
type : "coordinates",
short_name: name,
display_name : name,
zoom: lonlat.zoom != null ? lonlat.zoom : 15,
icon: "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png"
} ];
} else
throw body ? body.error : "Invalid response from name finder";
}
body.lat = lonlat.lat;
body.lon = lonlat.lon;
if(lonlat) {
body.lat = lonlat.lat;
body.lon = lonlat.lon;
if(lonlat.zoom != null)
body.zoom = lonlat.zoom;
if(lonlat.zoom != null)
body.zoom = lonlat.zoom;
}
return [ prepareSearchResult(body) ];
var res = prepareSearchResult(body);
if(lonlat)
res.id = query;
return [ res ];
});
}
@ -137,8 +156,7 @@ function prepareSearchResult(result) {
geojson: result.geojson,
icon: result.icon || "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
type: result.type == "yes" ? result.category : result.type,
osm_id: result.osm_id,
osm_type: result.osm_type
id: result.osm_type.charAt(0) + result.osm_id
};
}