kopia lustrzana https://github.com/FacilMap/facilmap
Add search/route to location hash
rodzic
5f28ad96ea
commit
e96e259ab7
|
@ -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,8 +16,9 @@
|
|||
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) {
|
||||
|
@ -28,9 +29,20 @@
|
|||
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;
|
||||
|
|
|
@ -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,6 +169,7 @@
|
|||
}.fmWrapApply(scope));
|
||||
|
||||
if(!dragging) {
|
||||
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();
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
scope.showAll = false;
|
||||
scope.activeResult = null;
|
||||
|
||||
scope.search = function() {
|
||||
scope.search = function(noZoom) {
|
||||
scope.searchResults = null;
|
||||
scope.loadedSearchString = "";
|
||||
clearRenders();
|
||||
|
@ -34,18 +34,24 @@
|
|||
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) {
|
||||
if(!noZoom)
|
||||
_flyToBounds(layerGroup.getBounds());
|
||||
|
||||
result.marker ? result.marker.openPopup() : result.layer.openPopup();
|
||||
|
@ -53,6 +59,7 @@
|
|||
clearRenders();
|
||||
renderResult(scope.loadedSearchString, scope.searchResults, result, true, layerGroup);
|
||||
|
||||
if(!noZoom) {
|
||||
if(result.lat && result.lon && result.zoom)
|
||||
map.map.flyTo([ result.lat, result.lon ], result.zoom);
|
||||
else if(result.boundingbox)
|
||||
|
@ -60,15 +67,21 @@
|
|||
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);
|
||||
|
||||
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() ]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -435,6 +435,10 @@
|
|||
});
|
||||
};
|
||||
|
||||
fmUtils.isSearchId = function(string) {
|
||||
return string && string.match(/^[nwr]\d+$/i);
|
||||
};
|
||||
|
||||
return fmUtils;
|
||||
});
|
||||
|
||||
|
|
|
@ -70,23 +70,33 @@ 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 = {
|
||||
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) {
|
||||
if(!body || body.error) {
|
||||
if(lonlat) {
|
||||
var name = utils.round(lonlat.lat, 5) + ", " + utils.round(lonlat.lon, 5);
|
||||
return [ {
|
||||
lat: lonlat.lat,
|
||||
|
@ -97,15 +107,24 @@ function find(query, loadUrls) {
|
|||
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";
|
||||
}
|
||||
|
||||
if(lonlat) {
|
||||
body.lat = lonlat.lat;
|
||||
body.lon = lonlat.lon;
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue