kopia lustrzana https://github.com/FacilMap/facilmap
Show markers and popups for search results
rodzic
1feb17b39c
commit
9ec78c79f8
|
@ -13,6 +13,7 @@ var FacilPad = {
|
|||
});
|
||||
|
||||
fp.app.constant("L", L);
|
||||
fp.app.constant("linkifyStr", linkifyStr);
|
||||
|
||||
// Dereferrer
|
||||
$(document).on("click", "a", function(e) {
|
||||
|
|
|
@ -140,15 +140,18 @@
|
|||
var listener = map.addClickListener(function(pos) {
|
||||
message.close();
|
||||
|
||||
map.socket.emit("addMarker", { lon: pos.lon, lat: pos.lat, typeId: type.id }, function(err, marker) {
|
||||
if(err)
|
||||
return map.messages.showMessage("danger", err);
|
||||
markersUi.createMarker(pos, type);
|
||||
});
|
||||
},
|
||||
createMarker: function(pos, type, properties) {
|
||||
map.socket.emit("addMarker", $.extend({ lon: pos.lon, lat: pos.lat, typeId: type.id }, properties), function(err, marker) {
|
||||
if(err)
|
||||
return map.messages.showMessage("danger", err);
|
||||
|
||||
markersUi._addMarker(marker);
|
||||
markersUi._addMarker(marker);
|
||||
|
||||
markersById[marker.id].openPopup();
|
||||
markersUi.editMarker(marker);
|
||||
});
|
||||
markersById[marker.id].openPopup();
|
||||
markersUi.editMarker(marker);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<div class="content container-fluid">
|
||||
<h2>{{result.short_name}}</h2>
|
||||
<p ng-if="result.display_name != result.short_name">{{result.display_name}} ({{result.type}})</p>
|
||||
<p ng-if="result.display_name == result.short_name">{{result.type}}</p>
|
||||
<dl class="dl-horizontal">
|
||||
<dt class="pos" ng-if="result.type != 'coordinates'">Coordinates</dt>
|
||||
<dd class="pos" ng-if="result.type != 'coordinates'">{{round(result.lat, 5)}}, {{round(result.lon, 5)}}</dd>
|
||||
|
||||
<dt ng-repeat-start="(key, value) in result.extratags">{{key}}</dt>
|
||||
<dd ng-repeat-end ng-bind-html="value | fpRenderOsmTag:key">{{value}}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="buttons" ng-if="!readonly">
|
||||
<div uib-dropdown ng-if="(types | fpPropertyCount:{type:'marker'}) > 1">
|
||||
<button id="add-type-button" type="button" class="btn btn-default" uib-dropdown-toggle>Add to map <span class="caret"></span></button>
|
||||
<ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="add-type-button" uib-dropdown-menu>
|
||||
<li role="menuitem" ng-repeat="type in types | fpObjectFilter:{type:'marker'}"><a href="#" ng-click="addToMap(type)">{{type.name}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button ng-if="(types | fpPropertyCount:{type:'marker'}) == 1" class="btn btn-default" ng-click="addToMap()">Add to map</button>
|
||||
</div>
|
|
@ -20,5 +20,8 @@
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="fp-search-buttons" ng-show="searchResults.length > 1">
|
||||
<button class="btn btn-default" ng-model="showAll" uib-btn-checkbox>Show all</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,46 +1,161 @@
|
|||
(function(fp, $, ng, undefined) {
|
||||
|
||||
fp.app.factory("fpMapSearch", function($rootScope, $templateCache, $compile, fpUtils) {
|
||||
fp.app.factory("fpMapSearch", function($rootScope, $templateCache, $compile, fpUtils, L, $timeout) {
|
||||
return function(map) {
|
||||
var iconSuffix = ".n.32.png";
|
||||
|
||||
var scope = $rootScope.$new(true);
|
||||
scope.searchString = "";
|
||||
scope.searchResults = null;
|
||||
scope.showAll = false;
|
||||
scope.activeResult = null;
|
||||
|
||||
scope.search = function() {
|
||||
fpMapSearch.search();
|
||||
scope.searchResults = null;
|
||||
clearRenders();
|
||||
|
||||
if(scope.searchString.trim() != "") {
|
||||
map.loadStart();
|
||||
map.socket.emit("find", { query: scope.searchString }, function(err, results) {
|
||||
map.loadEnd();
|
||||
|
||||
if(err)
|
||||
map.messages.showMessage("danger", err);
|
||||
|
||||
scope.searchResults = results;
|
||||
|
||||
if(results && results.length > 0)
|
||||
scope.showAll ? scope.showAllResults() : scope.showResult(results[0]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
scope.showResult = function(result) {
|
||||
if(result.boundingbox)
|
||||
map.map.flyToBounds([ [ result.boundingbox[0], result.boundingbox[3 ] ], [ result.boundingbox[1], result.boundingbox[2] ] ]);
|
||||
else
|
||||
map.map.flyTo([ result.lat, result.lon ], result.zoom);
|
||||
if(scope.showAll) {
|
||||
map.map.flyToBounds(layerGroup.getBounds());
|
||||
result.marker.openPopup();
|
||||
} else {
|
||||
clearRenders();
|
||||
renderResult(result, true);
|
||||
|
||||
if(result.boundingbox)
|
||||
map.map.flyToBounds([ [ result.boundingbox[0], result.boundingbox[3 ] ], [ result.boundingbox[1], result.boundingbox[2] ] ]);
|
||||
else
|
||||
map.map.flyTo([ result.lat, result.lon ], result.zoom);
|
||||
}
|
||||
};
|
||||
|
||||
scope.showAllResults = function() {
|
||||
clearRenders();
|
||||
|
||||
for(var i=0; i<scope.searchResults.length; i++)
|
||||
renderResult(scope.searchResults[i], false);
|
||||
|
||||
map.map.flyToBounds(layerGroup.getBounds());
|
||||
};
|
||||
|
||||
scope.$watch("showAll", function() {
|
||||
if(!scope.searchResults)
|
||||
return;
|
||||
|
||||
if(scope.showAll)
|
||||
scope.showAllResults();
|
||||
else if(scope.searchResults.length > 0)
|
||||
scope.showResult(scope.activeResult || scope.searchResults[0]);
|
||||
});
|
||||
|
||||
var el = $($templateCache.get("map/search/search.html")).insertAfter(map.map.getContainer());
|
||||
$compile(el)(scope);
|
||||
scope.$evalAsync(); // $compile only replaces variables on next digest
|
||||
|
||||
var layerGroup = L.featureGroup([]).addTo(map.map);
|
||||
|
||||
function renderResult(result, showPopup) {
|
||||
layerGroup.addLayer(
|
||||
L.geoJson(result.geojson, {
|
||||
pointToLayer: function(geoJsonPoint, latlng) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.bindPopup($("<div/>")[0], map.popupOptions)
|
||||
.on("popupopen", function(e) {
|
||||
scope.activeResult = result;
|
||||
renderResultPopup(result, e.popup);
|
||||
})
|
||||
.on("popupclose", function(e) {
|
||||
scope.activeResult = null;
|
||||
ng.element(e.popup.getContent()).scope().$destroy();
|
||||
})
|
||||
.bindTooltip(result.display_name, $.extend({}, map.tooltipOptions))
|
||||
);
|
||||
|
||||
result.marker = L.marker([ result.lat, result.lon ], {
|
||||
icon: L.icon({
|
||||
iconUrl: result.icon.replace(/\.[a-z]+\.[0-9]+\.png$/, iconSuffix),
|
||||
iconSize: [ 32, 32 ],
|
||||
iconAnchor: [ 16, 16 ],
|
||||
popupAnchor: [ 0, -16 ]
|
||||
})
|
||||
})
|
||||
.bindPopup($("<div/>")[0], map.popupOptions)
|
||||
.on("popupopen", function(e) {
|
||||
scope.activeResult = result;
|
||||
renderResultPopup(result, e.popup);
|
||||
})
|
||||
.on("popupclose", function(e) {
|
||||
scope.activeResult = null;
|
||||
ng.element(e.popup.getContent()).scope().$destroy();
|
||||
})
|
||||
.bindTooltip(result.display_name, $.extend({}, map.tooltipOptions, { offset: [ 20, 0 ] }));
|
||||
|
||||
layerGroup.addLayer(result.marker);
|
||||
|
||||
if(showPopup)
|
||||
result.marker.openPopup();
|
||||
}
|
||||
|
||||
function clearRenders() {
|
||||
layerGroup.clearLayers();
|
||||
}
|
||||
|
||||
function renderResultPopup(result, popup) {
|
||||
var scope = map.socket.$new();
|
||||
|
||||
scope.result = result;
|
||||
|
||||
scope.addToMap = function(type) {
|
||||
if(type == null) {
|
||||
for(var i in map.socket.types) {
|
||||
if(map.socket.types[i].type == "marker") {
|
||||
type = map.socket.types[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map.markersUi.createMarker(result, type, { name: result.display_name });
|
||||
};
|
||||
|
||||
var el = popup.getContent();
|
||||
$(el).html($templateCache.get("map/search/result-popup.html"));
|
||||
$compile(el)(scope);
|
||||
|
||||
// Prevent popup close on button click
|
||||
$("button", el).click(function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$timeout(function() { $timeout(function() { // $compile only replaces variables on next digest
|
||||
popup.update();
|
||||
}); });
|
||||
}
|
||||
|
||||
var fpMapSearch = {
|
||||
search: function(query) {
|
||||
if(query != null)
|
||||
scope.searchString = query;
|
||||
|
||||
scope.searchResults = null;
|
||||
if(scope.searchString.trim() != "") {
|
||||
map.loadStart();
|
||||
map.socket.emit("find", { query: scope.searchString }, function(err, results) {
|
||||
map.loadEnd();
|
||||
|
||||
if(err)
|
||||
map.messages.showMessage("danger", err);
|
||||
|
||||
scope.searchResults = results;
|
||||
|
||||
if(results.length > 0)
|
||||
scope.showResult(results[0]);
|
||||
});
|
||||
}
|
||||
scope.search();
|
||||
},
|
||||
|
||||
showFiles: function(files) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
};
|
||||
|
||||
fpUtils.createMarkerIcon = function(colour, huge) {
|
||||
return new L.Icon({
|
||||
return L.icon({
|
||||
iconUrl: fpUtils.createMarkerGraphic(colour, huge),
|
||||
iconSize: huge ? [10000, 10000] : [21, 25],
|
||||
iconAnchor: huge ? [5010, 5025] : [10, 25],
|
||||
|
@ -218,4 +218,23 @@
|
|||
};
|
||||
});
|
||||
|
||||
fp.app.filter('fpRenderOsmTag', function($sce, linkifyStr, fpUtils) {
|
||||
return function(value, key) {
|
||||
if(key.match(/^wikipedia(:|$)/)) {
|
||||
return $sce.trustAsHtml(value.split(";").map(function(it) {
|
||||
var m = it.match(/^(\s*)((([-a-z]+):)?(.*))(\s*)$/);
|
||||
var url = "https://" + (m[4] || "en") + ".wikipedia.org/wiki/" + m[5];
|
||||
return m[1] + '<a href="' + fpUtils.quoteHtml(url) + '" target="_blank">' + fpUtils.quoteHtml(m[2]) + '</a>' + m[6];
|
||||
}).join(";"));
|
||||
} else if(key.match(/^wikidata(:|$)/)) {
|
||||
return $sce.trustAsHtml(value.split(";").map(function(it) {
|
||||
var m = it.match(/^(\s*)(.*?)(\s*)$/);
|
||||
return m[1] + '<a href="https://www.wikidata.org/wiki/' + fpUtils.quoteHtml(m[2]) + '" target="_blank">' + fpUtils.quoteHtml(m[2]) + '</a>' + m[3];
|
||||
}).join(";"));
|
||||
} else {
|
||||
return $sce.trustAsHtml(linkifyStr(value));
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
})(FacilPad, jQuery, angular);
|
|
@ -26,7 +26,8 @@
|
|||
"bootstrap-touchspin": "^3.1.2",
|
||||
"leaflet": "^1.0.1",
|
||||
"leaflet-geometry-util": "https://github.com/makinacorpus/Leaflet.GeometryUtil/raw/master/src/leaflet.geometryutil.js",
|
||||
"leaflet-almostover": "https://github.com/makinacorpus/Leaflet.AlmostOver/raw/gh-pages/src/leaflet.almostover.js"
|
||||
"leaflet-almostover": "https://github.com/makinacorpus/Leaflet.AlmostOver/raw/gh-pages/src/leaflet.almostover.js",
|
||||
"linkifyjs": "^2.1.3"
|
||||
},
|
||||
"overrides": {
|
||||
"bootstrap": {
|
||||
|
@ -36,6 +37,12 @@
|
|||
"dist/js/bootstrap.js",
|
||||
"dist/fonts/glyphicons-halflings-regular.ttf"
|
||||
]
|
||||
},
|
||||
"linkifyjs": {
|
||||
"main": [
|
||||
"linkify.js",
|
||||
"linkify-string.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,14 +51,16 @@ function find(query, callback) {
|
|||
lat: lonlat.lat,
|
||||
lon : lonlat.lon,
|
||||
type : "coordinates",
|
||||
short_name: lonlat.lat + ", " + lonlat.lon,
|
||||
display_name : lonlat.lat + ", " + lonlat.lon,
|
||||
zoom: lonlat.zoom
|
||||
zoom: lonlat.zoom,
|
||||
icon: "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png"
|
||||
} ];
|
||||
return callback(null, results);
|
||||
}
|
||||
|
||||
request({
|
||||
url: nameFinderUrl + "?format=jsonv2&polygon_geojson=1&addressdetails=1&limit=" + encodeURIComponent(limit) + "&extratags=1&q=" + encodeURIComponent(query),
|
||||
url: nameFinderUrl + "?format=jsonv2&polygon_geojson=1&addressdetails=1&namedetails=1&limit=" + encodeURIComponent(limit) + "&extratags=1&q=" + encodeURIComponent(query),
|
||||
json: true
|
||||
}, function(err, response, body) {
|
||||
if(err)
|
||||
|
@ -68,13 +70,17 @@ function find(query, callback) {
|
|||
|
||||
var results = [ ];
|
||||
body.forEach(function(result) {
|
||||
var displayName = makeDisplayName(result);
|
||||
results.push({
|
||||
display_name: makeDisplayName(result),
|
||||
short_name: displayName.split(',')[0],
|
||||
display_name: displayName,
|
||||
boundingbox: result.boundingbox,
|
||||
lat: result.lat,
|
||||
lon: result.lon,
|
||||
extratags: result.extratags,
|
||||
geojson: result.geojson,
|
||||
icon: result.icon,
|
||||
type: result.type,
|
||||
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
|
||||
});
|
||||
|
@ -95,7 +101,7 @@ function makeDisplayName(result) {
|
|||
// address notation guidelines
|
||||
|
||||
var type = result.type;
|
||||
var name = result.address[result.type] || result.display_name.split(',')[0] || "";
|
||||
var name = result.namedetails.name;
|
||||
var countryCode = result.address.country_code;
|
||||
|
||||
var road = result.address.road;
|
||||
|
|
Ładowanie…
Reference in New Issue