How to trigger native popup on Leaflet polygon - leaflet

How do you manually trigger the native popup on a Leaflet polygon?
I can bind the native popup to each layer like this:
geojsonLayer.on("featureparse", function (e){
// bind the native popup
var popupContent = "popup content goes here";
e.layer.bindPopup(popupContent);
});
And I have manually assigned an ID to each polygon so I can reference them later like this:
map._layers['poly0']
I've tried triggering the popup like this:
map._layers['poly0'].openPopup();
But that gives me an error like this:
map._layers['poly0'].openPopup is not a function
Any idea where I'm going wrong?

openPopup for vector layers only recently appeared in the latest version, it wasn't there before.
Also, check out the Leaflet 0.4 release announcement: http://leaflet.cloudmade.com/2012/07/30/leaflet-0-4-released.html (and note that GeoJSON API was changed and it's not backwards compatible, so you also have to update your code)

Related

Markers in the same position don't work properly with Vue3 + Leaflet Markercluster

The problem is that the leaflet map inside the vue3 App loads perfectly and looks great. Also, when you click on a location with two icons in the same position, they open perfectly, but when you click on the same place again, the icons disappear and the "spider" remains visible (see picture).
spider remains
The methods in the Vue3 App are:
methods:{
setupMarkers(){
this.markers.clearLayers();
this.cursesData.forEach(cursa =>this.ficaMarkers(cursa));
this.map.addLayer(this.markers);
},
setupLeafletMap(){
this.map=L.map("mapContainer").setView(this.center,6);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{
attribution:'OpenStreetMap',
}).addTo(this.map);
this.markers= L.markerClusterGroup({
//spiderfyOnMaxZoom: true,
});
},
ficaMarkers(cursa){
this.markers.addLayer(L.marker([cursa.coordenades[0],cursa.coordenades[1]],{title:cursa.nom})
.bindPopup(cursa.distancies)
)
},
},
If someone could help me, I would be very grateful.
Thanks.
It is a similar issue as in Uncaught TypeError: this._map is null (Vue.js 3, Leaflet) :
What seems to be the culprit is the proxying of this.map by Vue, which seems to interfere with Leaflet events (un)binding. It looks like Vue 3 now automatically performs deep proxying, whereas Vue 2 was shallow.
In your case, the same thing happens for this.markers (which is the Leaflet MarkerClusterGroup).
A solution consists in "unwrapping" / un-proxying the map and the mcg whenever you use them, e.g. with Vue3's toRaw:
toRaw(this.map).addLayer(toRaw(this.markers));
Then we retrieve the normal MCG behaviour, i.e. if you click on the cluster while it is already spiderfied, nothing happens (whereas initially the Markers were collapsing, but the spider legs were remaining indefinitely)
Fixed CodeSandbox: https://codesandbox.io/s/markers-hide-spiders-stay-forked-l2ruqh?file=/src/App.vue

How to resolve Leaflet TypeError: L.control.selectLayers is not a function

I wish to make a dropdown list to replace the default tool for layer selection.
Using this example included in from the GIT repository, and adjust for jsfiddle, I get the following error:
"<a class='gotoLine' href='#77:31'>77:31</a> TypeError: L.control.selectLayers is not a function"
using L.control.layers works fine, however, not selectLayers.
//var control = L.control.layers(baseMaps, overlayMaps)
var control = L.control.selectLayers(baseMaps, overlayMaps)
control.addTo(map);
The appropriate javascript files all seem to be in place, so.. what is missing here?
Fiddle link:
You added the wrong link of the libraries.
You have to use the raw link instead of the Github link

Update Popup data in Mapbox GL JS

I'm making a fleet tracker with Mapbox GL JS, it gets the data from a GeoJson and inserts in the map, as the Add live realtime data, I've also integrated the Mapbox store locator example, by now I can update in realtime the sidebar and the points on the map. A modification that I would like to make is not display only one single popup, but a popup for every icon located there. I would like to know how to update this popups, because in the way I'm making it's creating a new popup every movement of the object, but is not closing the previous one. Here is the function that I'm using for the popups
function createPopUp(currentFeature, data) {
var popUps = document.getElementsByClassName('mapboxgl-popup');
//if (popUps[0]) popUps[0].remove();
// mapboxgl.Popup.remove();
if (map.getZoom() > 9) {
var popup = new mapboxgl.Popup({closeOnClick: false})
.setLngLat(currentFeature.geometry.coordinates)
.setHTML('<h3> Aeronave: '+ currentFeature.properties.dev_id + '</h3>' +
'<h4> Curso: ' + currentFeature.properties.curso + 'ยบ<br> Altitude: ' + currentFeature.properties.alt + ' ft<br> Sinal: ' + currentFeature.properties.rssi +'</h4>')
.addTo(map)
.setMaxWidth("fit-content(10px)");
} else{if (popUps[0]) popUps[0].remove()};
}
If I uncomment the popUps[0] line it will only allow 1 popup to be displayed, I've also tried to change dynamically the number between the [] by the number of active tracked devices, it reduced the popup number, but it still repeat some popups of one ID. Also I've tried to change the class name via the .addClasName but it didn't worked.
Thanks
Without seeing how you're calling the createPopUp method in the context of your application, it is difficult to diagnose exactly what is going wrong. I'm not sure why a new popup is being created each time the map moves, so it sounds like you might be calling this method within the Map#on('move') event. That being said, I'm assuming that you're iterating over all of your features and calling the createPopUp method for each in order to initialize all of the popups.
Rather than using an array of DOM nodes generated with var popUps = document.getElementsByClassName('mapboxgl-popup');, I'd recommend specifying a unique and reproducible class name for each feature's popup element when initialized. It looks like each of your features has a dev_id property, so you could do something like:
var popup = new mapboxgl.Popup({closeOnClick: false, className: `mapbox-gl-popup-${dev_id}`})
If you need to change the popup for a particular feature in the future, you can create a helper function to retrieve the relevant DOM node:
function retrievePopUp(feature) {
return document.getElementsByClassName(`mapboxgl-popup-${feature.properties.dev_id}`);
}

Leaflet labels when upgrading to 1.0.3

I try to use leaflet labels and on several pages it is successful. I wanted to use the same approach to display labels on another page and it responded with an obscure technical message which I did not understand:
Uncaught TypeError: Cannot read property 'call' of undefined
at e.whenReady (leaflet.js:6)
at e.addLayer (leaflet.js:6)
at e.showLabel (leaflet.label-src.js:538)
at e.showLabel (leaflet.label-src.js:287)
at e._onMarkerAdd (leaflet.label-src.js:383)
at e.fire (leaflet.js:5)
at e._layerAdd (leaflet.js:6)
at e.whenReady (leaflet.js:6)
at e.addLayer (leaflet.js:6)
at e.onAdd (leaflet.js:7)
After a lot of researching I found out that leaflet.label is deprecated for Leaflet 1.0.3, which makes sense, since we are using older leaflet version in other pages where the labels appear correctly, but on the newer leaflet versions it crashes the map. The docs say that I should use bindTooltip instead of bindLabel, but I do not know how. I have tried to call it with some content on a marker but it did not appear on the map and I did not find it in the generated structure.
So, my question is as follows: How can I use labels with Leaflet 1.0.3, which will be bound to a marker and will adjust in case of translation/zoom?
The Tooltip is indeed now directly part of Leaflet main library.
Note that it appears only on mouseover by default, but you can use the permanent option to have it remain always visible.
marker.bindTooltip("Some tooltip content", {
permanent: true
});
Example: http://playground-leaflet.rhcloud.com/tiqo/1/edit?html,output

Markercluster in Mapbox

I am following markercluster examples from Mapbox library, but can't solve my problem. If you guys take a look at my working example here, you will notice this line of code:
L.mapbox.featureLayer(markerLayer).on('ready', function(e) {
What I initally thought was I could put markers inside of markercluster featureLayer, but I guess it was a wrong approach. Any solutions? Thanks.
Example following here
The mapbox example you refer to makes an AJAX call to retrieve the GeoJSON data, hence it needs to attach an on "ready" listener.
In your case your GeoJSON data is defined in your scripts, so the "ready" event will not be triggered (besides, you should use L.mapbox.featureLayer with your GeoJSON object directly, not a Feature Layer).
You can simply use the eachLayer method to iterate through all created markers within the Feature Layer, and add them into your Marker Cluster Group.
var clusterGroup = new L.MarkerClusterGroup();
var markerLayer = L.mapbox.featureLayer(markers).eachLayer(function(layer) {
clusterGroup.addLayer(layer);
});
map.addLayer(clusterGroup);
Updated Plunker: http://plnkr.co/edit/fN6xYcn1Lg532eLe39IS?p=preview