My scenario is that the user would click on a marker that is part of a cluster and be redirected somewhere else. Then when they come back they need to return the the same bounds on the map where they were before at that marker, but the cluster in which the marker is found is no longer expanded/spiderfy'd, which I need to get done.
At this point I know which marker I'm looking for, but need to expand its cluster. What I've done so far:
Iterate through the markers in the initially populated L.markerClusterGroup() object:
layers = L.markerClusterGroup();
. . . populate 'layers' ...
$.each(layers, function (idx, layer) {
if(layer._tooltip._content === 'known marker tooltip') {
layer.__parent.spiderfy();
}
});
Although the spiderfy() function sort of works, it doesn't seem to be intended to be used on its own and breaks the cluster pretty bad.
Alternatively, I've tried calling fire('clusterclick') on the above layer object, as well as on layer.__parent, which I presume would represent the cluster, but can't get anything working.
I would need a solution in which I can properly trigger the clusterclick event that would handle everything, as if I had actually clicked the cluster myself.
Related
markerGroup: L.LayerGroup;
this.markerGroup.eachLayer(function (layer) {
this.markerGroup.removeLayer(layer);
});
this.markerGroup.clearLayers();
removeLayer() and clearLayers() are working as described in the leaflet documentation but I am wondering if there is a way to remove the layer/marker/instance from my markerGroup variable entirely. Even though the markers are cleared/removed, when my refresh button is called it still has the previous markers in the markerGroup variable and adds the same ones again thus duplicating them. This is a problem as I have shadows for these markers which duplicate over each other and eventually becoming 100% opaque. Has anybody got any suggestions or come across this problem before?
Edit: Thanks for the suggestion #Falke Design. map.removeLayer doesn't work for me unfortunately. Hopefully the information below is more helpful:
refreshButton() {
this.markerGroup = new L.LayerGroup;
clearInterval(this.refreshTimer);
this.dynamicLatLong = this.map.getCenter();
this.dynamicZoom = this.map.getZoom();
this.markerGroup.clearLayers();
this.polygonGroup.clearLayers();
this.map.removeLayer(this.markerGroup);
this.getCurrentAzure();
this.leafletMap();
}
getCurrentAzure() uses a for loop to get the data such as lat, lng, etc. of each instance and assigns it to a variable named marker. Each marker is added to markerGroup with this line:
marker.addTo(this.markerGroup);
leafletMap() creates the map and draws the markerGroup onto the map with this line:
this.markerGroup = L.layerGroup().addTo(this.map);
I have created a directions map from one point to multiple specific point. When one change end point the map should update, and alternative routes should be shown on the right sidebar, with details under it. However, when I change end point it's not updating nicely, sometimes it just add alternative directions under "old" directions,sometimes alternatives are messed up, not really sure what the problem is, though I suspect that there might be a problem if theres's no alternative routes returned for the specific end point. Here's a preview of what I made so far:
jsbin.com/hoqebofice/edit?output
Also in the end, I'd like to have map updated once alternative route is clicked from the right sidebar as well.
In your OnChangeHandler add this line:
var onChangeHandler = function() {
document.getElementById("setPanel").innerHTML = ""; // THIS ONE!
calculateAndDisplayRoute(directionsService, directionsDisplay);
};
I'd like to list all of the elements from a Mapbox gridLayer that are visible to a user in the viewport.
There is an excellent example on the Mapbox site called 'Listing markers in view'. It shows all the markers on the featureLayer that are in the view of the browser.
I'd like to create something similar, but using using a gridLayer instead. (the gridLayer was created in TileMill)
Here is an example fiddle of the data with a version of non-working 'in-bounds' code:
http://jsfiddle.net/bfab/uSLVw/1/
For reference, the gridLayer has a variable in it (passed from TileMill in the UTFGrid) called '{{{Magnitude}}}' I'd like to list each of the instances of earthquakes that appear to the user, and add it to a list on the bottom left of the example. The function I'm trying to use is gridLayer.getData(latlng,callback).
Here is the snippet of code that is not working:
map.on('move', function() {
// Construct an empty list to fill with gridLayer elements.
var inBounds = [],
// Get the map bounds - the top-left and bottom-right locations.
bounds = map.getBounds();
// For each part of the grid, consider whether
// it is currently visible by comparing with the current map bounds.
// This is what fails....
myGridLayer.getData(bounds,function(earthquake){
inBounds.push(earthquake.Magnitude);
});
// Display a list of markers.
document.getElementById('coordinates').innerHTML = inBounds.join('\n');
});
Apologies if I am making a simple error...
Actually you can't (not easily at least)
1/ You misunderstand the getData function on the gridlayer
first parm is not a boundary but a location latlng
when you use this in a callback (onclick for example) you will get data only if you click on one of your circles, if not you get undefined). The data is not a list of markers but the information of your earthquake (e.g. {DateTime: "2014-04-26T16:59:15.710+00:00", Magnitude: 3.9})
myGridLayer.getData(event.latlng, function(data) {
console.log(data);
// if clicked on a marker: data is defined
// e.g. Object {DateTime: "2014-04-26T16:59:15.710+00:00", Magnitude: 3.9}
});
http://jsfiddle.net/FranceImage/uSLVw/11/
2/ It is not easy to think in terms of markers when using gridlayer as the markers are already part of the image when you load tiles:
http://a.tiles.mapbox.com/v3/bfab.i4nm0adm/3/0/2.png
The interaction is described in some javascript loaded at the same time
http://a.tiles.mapbox.com/v3/bfab.i4nm0adm/3/0/2.grid.json
I've got a pretty specific question that I'm not really expecting a direct answer to, but any guidance will be helpful.
Simple and plain, I want to programmatically fire a click event on a marker positioned on a Leaflet map, powered by CartoDB. I have a single layer on the map that contains markers, and each marker has click events associated with them. So, essentially, I just need to find the marker and fire the click event on it.
For context, Mapbox actually does exactly this, but unfortunately I can not use Mapbox for this particular implementation:
https://www.mapbox.com/mapbox.js/example/v1.0.0/open-popup-externally/
I'm open to suggestions, but preferably, I'd like to do something similar to the code in the link above -- interrogate either Leaflet or CartoDB via javascript to find and access the marker via custom properties/lat-lng/??. I figure it would be simple enough to go from there.
Another way could be to hook an event when the markers are created, store them in a hash, then access that storage when I need to do my manual click. However, I don't know of any such event that exists, and I can't locate documentation that lists supported events.
Since I'm not creating the markers myself, and can not (for reasons), storing them as I add them to the map is not an option here.
I assume since Mapbox is doing it, there must be some hook, but I can't find any valuable documentation to point me in the right direction.
Any suggestions or pointers?
To anyone who stumbles upon this, I've got a workable solution for my particular case. This call will do it for you:
layer.trigger 'featureClick', event, latlng, pos, data, layer_count
Essentially, you'll want to grab the layer in question and trigger the click, passing the appropriate data:
event: this can be null, since there is no event
latlng: the lat/long position
data: an object like { cartodb_id: 123 }. The cartodb_id is required.
layer_count: the index of your layer (probably 0)
To grab the latlng and the cartodb_id here, you'll probably need to do what I did -- query for it:
function openMarker(layer, my_object_id) {
vars = { database_id: my_object_id };
opts = { format: 'geojson' };
query = "SELECT * FROM my_table WHERE my_object_id = {{ my_object_id }}"
sql = new cartodb.SQL({user: my_user_id});
sql.execute(query, vars, opts).done(function(data) {
if (data.features != undefined && data.features.length == 1)
row = data.features[0];
latlng = [ row.geometry.coordinates[1], row.geometry.coordinates[0] ];
layer.trigger('featureClick', null, latlng, null, { cartodb_id: row.properties.cartodb_id }, 0);
});
}
Then, you can just call open_marker, passing the layer you wish to open the marker on and your object identifier. As long as that's in your cartodb database, you can grab it. Of course, the query can be adjusted to suit your means.
For my particular implementation, I had to use a setTimeout call to get the flow of control right, as I do my calls on page load. But if you're calling after the page has loaded, should be no problem.
So, simple enough way to open a marker given a local identifier. Hope this helps someone else!
Kudos for the inspiration for this solution go to:
https://gist.github.com/javisantana/7b817fda1e7511c451c7#file-index-html-L39
I want to add and remove data sets from the clusterer - but when a particular data set cluster is toggled off the original (non-clustered) markers dont re-appear - i cant make them visible...
function clusterEvents(i)
{
cluster[0][i]=cluster[0][i]?0:1 // to tell which data set is in use
if(cluster[1]) // clear the cluster
cluster[1].clearMarkers()
cluster[1]=new MarkerClusterer(map,[],{gridSize:50,maxZoom:15})
for(i in iconz) // import markers
{
if(iconz[i].type<20)
{
if(cluster[0][iconz[i].type]||cluster[0][iconz[i].type-6]) // if target then cluster
cluster[1].addMarker(iconz[i],true)
else
**iconz[i].setVisible(true) // make it visible**
}
}
}
The problem lay with the syntax of making the markers visible in the code above
iconz[i].setVisible(true)
the correct syntax is:
iconz[i].setOptions({map:map[j_W],visible:true})
whats nice about this is that clusters can be assigned to their own layers/arrays and can be toggled on and off