Leaflet: Add event to marker? - javascript

I tried to add a click event to a leaflet marker like this:
L.marker([41.866056100409044, 12.5349304759025576]).on('click', red).bindLabel('kebabbari (Ali Baba)', {noHide: true}).addTo(map).showLabel();
But the result is just a marker without any click event (the "red()" function exists)
Marker in leaflet, click event doesn't work

Just ran multiple tests with different scenarios and they all worked with an onclick or mouseover. I'm using Leaflet 1.03 I think your using the previous version.
var Marker = L.marker([41.866056100409044, 12.5349304759025576]).on('click', onClick).addTo(map)
Add a new function like below :-
function onClick(e) {
alert(this.getLatLng());
}
Try this and it will prove your onclick function can work. I think the leaflet Plugin Label might be interfering with it as it has an Onclick option and you may need to look further into that.
But sometimes you need to prove you can make it work first and then add things back in bit by bit.
Also Leaflet.Label does have a conflict with onclick.
https://github.com/Leaflet/Leaflet.label/issues/132 This issue from the forum will help you out they have answer detailed on here.
You need to specifically bind an event to marker.label , e.g.:
L.DomEvent.addListener(marker.label, 'click', function(e) { this.togglePopup() }, marker);
I had to dig in to the code a bit to figure this out, worth a mention in the README on how to access the label and bind events to it.

Related

OpenLayers 3: "movestart" event on map

OpenLayers3 API has a map.on("moveend") , however I cannot find a movestart. Any one know how I can achieve this? Is there a equivalent event?
OpenLayers 2 had a movestart event on map. I am looking an exact parallel in OpenLayers3
Here's a basic jsFiddle. If someone want's to play around. I did add a movestart event there, to show what I want, but it doesn't actually exist I think.
Use Case! one might ask: I have stops on maps that have nearly fullscreen infowindows. Users can switch to next marker from infowindow. I make the windows translucent to show the map panning underneath, so users get a context of where next location is. This work's great in OpenLayers2 with movestart and moveend events. But in the new OL3 version of the map, I can't get the movestart event.
Update: I did answer the question my self, but I am still offering bounty if anyone would like to propose a better solution.
UPDATE v4.2.0 now supports native movestart and moveend events
map.on('movestart', function(event) {
//To Remove after first use: ol.Observable.unByKey(event);
});
map.on('moveend', function(event) {
//To Remove after first use: ol.Observable.unByKey(event);
});
For OpenLayers 3 versions before release of v4.2.0
Okay so in the mean while without the movestart event, and with the moveend only triggering if there is a actual movement in map, here's how I was able to achive movestart and moveend behavior.
jsFiddle:
var pan = ol.animation.pan({
duration: 700,
source: this.map.getView().getCenter()
});
map.beforeRender(function(map, frameState) {
var stillPanning = pan(map, frameState); // returns false panning is done
if (stillPanning) {
// do movestart stuff here
if (!everDone) {
doSomething();
everDone = true;
}
} else {
// do move end stuff here
undoSomething();
everDone = false;
}
return stillPanning;
});
map.getView().setCenter(geom);
So why this works?
ol.animation.pan returns a ol.PreRenderFunction, which returns false if animation is not complete
Writing custom function and providing it to map.renderBefore can be now used to write a wrapper around pan animation as shown above
The whole business with everDone is because, stillPanning section will get called multiple times. This is okay if what you want to do there can take repeated calls, but if you want to toggle something then you want to do it only once.
behavior of 'moveend'
moveend callback is only triggered if map actually moves. This is fine, but it prevents us from doing pre-animation activities, by just doing them before animation done. If you had a scenario where map doesn't actually move, then what ever you did before animation will never undo because that behavior is in moveend which never gets called!
Hope this helps someone. I had to spend good two hours to get it to work for me, because a movestart callback is absent :(
UPDATE
Upon more discussion on this thread there is another solution as suggested by #ahocevar. That is to use the propertychange event on the view like so:
function onpropertychange() {
map.dispatchEvent('movestart');
var view = map.getView();
view.un('propertychange', onpropertychange);
map.on('moveend', function() {
view.on('propertychange', onpropertychange);
});
};
map.getView().on('propertychange', onpropertychange);
Here's a working example of this approach: jsFiddle
you could use the pointerdrag or pointermove event, but you will want to debounce them. I did so here with a variable called dragStarted
http://jsfiddle.net/sean9999/j2cP4/115/
http://openlayers.org/en/v3.8.2/apidoc/ol.MapBrowserEvent.html

Restrict google maps API marker to only one click per marker

I'm creating a simple map Phonegap app where you click the map, and a marker is added, and a popup form shows. This is working just fine, but I need to make sure each marker is clickable only once.
This is what I've tried so far:
google.maps.event.addListener(clickMarker, 'click',
function (e) {
addLocations(this.getPosition()); // calls popup form
/* clickMarker.setOptions({
clickable: false
});*/
clickMarker.setClickable(false);
});
Is what I'm asking possible? If it is possible, what am I doing wrong?
Replace addListener with addListenerOnce. This will ensure that your listener is called once.
no, instead of set the clickable to false, try removing the event listener
clickMarker.addListener('click', //add the listener to your marker object directly
function (e) {
addLocations(this.getPosition()); // calls popup form
// Do ever things you want to do before calling this
// Removing the event, so we can just call once
google.maps.event.clearListeners(clickMarker, "click"); // don't forget the 's'
});
Since you're working with phonegap, I strongly suggest you to use this plugin for google maps, it'll be easier :
https://github.com/wf9a5m75/phonegap-googlemaps-plugin
-- Carlos :-)

How to prevent LeafletJS from issuing multiple click events on overlapping markers?

I have a LeafletJS map with a lot of markers on it, and many of them overlap at high zoom levels. Currently, when I click on a few overlapping markers, multiple click events are being issued, each of which then issues a popupopen event which in turn does a $.getJSON() to populate the popup. Obviously, this isn't ideal, so I'd like to find out how to get Leaflet to just execute one click at a time.
Other answers I find on here talk about e.preventDefault() or e.stopPropagation(). Neither of those appear to be available in Leaflet's click or popupopen events, so I'm thinking there must be a smarter way that I've not heard of.
Here's my code, watered down for the purpose of this question:
var geojson_options = {
onEachFeature: function(feature, layer){
layer.bindPopup('<img src="/spinner.gif" />');
layer.on("popupopen", function(e){
// e.preventDefault and e.stopPropogating don't exist
$.getJSON("some-url.json", function(json){
e.popup.setContent("Some processing of the json");
});
});
},
pointToLayer: function (feature, latlng) {
// Irrelevant stuff
}
};
L.geoJson(geojson_data, geojson_options);
I've tried variations on using layer.on("click", ...) to set a variable called popping_open to true to keep state while the popup is opening, but that didn't work either. Tell me there's a clean way to handle this?
There is a plugin called OverlappingMarkerSpiderfier-Leaflet that spreads overlapping markers on an onClick event so their identification is more easy. You can see a demo here and download it from github. Maybe it is useful for your application.
It sounds like the issue here, if I'm understanding correctly, is that when you try to click on a marker, the click event is being triggered by multiple markers that overlap instead of being triggered by the intended marker. The only way I know to fix this is to separate the markers before the click event can be triggered. You can do this by using a plugin as suggested, or by preventing popups from opening at specific zoom levels.
I recommend using a plugin called Leaflet.markercluster (https://github.com/Leaflet/Leaflet.markercluster). It creates clusters of overlapping markers that separate as you zoom in. Clicking on a cluster will zoom to the geographic bounds of the cluster, showing markers individually as long as they don't overlap. You could use the plugin with this basic format:
var markerClusterLayer = L.markerClusterGroup();
var geojson_options = {
onEachFeature: function(feature, layer){
layer.bindPopup(your popup content goes here);
... other stuff you want to do ...
markerClusterLayer.addLayer(layer);
}
};

How do I disable all mouse events on the map (click, hover, etc)?

I am wanting to use this product to display the US map with states selected already. I do not need any click functionality. I cannot for the life of me prevent the onRegionClick function from firing. I have tried using the ' event.preventDefault ' method, but it doesn't work. Can anybody help?
Thanks,
Brad
I tried this:
jQuery('#vmap').vectorMap({
map: 'russia_en',
// removed other declarations not needed in this example
onRegionOver: function(event,code, region)
{
if (code)
{
event.preventDefault();
}
}
});
This prevents the mouseover event to do it's work on the map I loaded. If you add similar code for the other events you should be good.
I ran into the same issue recently and I ended up using a workaround.
In onRegionClick: function(event, code, region) {...} you could check if code is in the selected states array and use $vmap.vectorMap('set', 'colors', '#selectedOrDeselected') to set the state colors accordingly
I also struggled to disable the click on regions, finally I used a simpler solution to disable the clicking on the map :
$('#vmap').off('click');

jQuery: How does one use .live() on an existing event handler (Cloud Zoom Plugin)?

Not sure how to phrase this properly, so please bear with me. I have a piece of jQuery that looks like the following:
jQuery(document).ready(function() {
$('#main-image').live('mouseover', function() {
$(this).wrap(function() {
return '<a href=' + $(this).attr('src').replace(/\bproduct\b/, 'original') + ' class="cloud-zoom" id="zoom1" rel="adjustX: 10, adjustY:-4, position: \'inside\'">';
});
});
$('#main-image').live('mouseout', function() {
var link_element = $(this).closest('a');
link_element.parent().append($(this));
link_element.remove();
});
});
My HTML markup is straight forward as well:
<img alt="foo" id="main-image" src="/assets/products/1051/product/Perspective_View-0.jpeg?1290039436">
The problem I have is I'm trying to use the cloud zoom jQuery plugin: http://www.professorcloud.com/mainsite/cloud-zoom.htm and it doesn't like the nature of the way I'm binding events here. If I predefine the anchor tag as the wrap() invocation does statically in my HTML, the plugin works perfectly. If I add the anchor tag dynamically to the DOM, cloud zoom does not work. The reason I cannot do it statically is I have a row of photos, and once you click on one of those photos, it goes to the main-image element where it is enlarged. At that point, I want cloud zoom to bind itself to the image. The JavaScript above works great at adding itself and removing itself dynamically around the img tag, however it doesn't bode well with cloud zoom as the event handler that's in cloud zoom is probably attaching itself to the anchor tags on DOM load, not any point after.
Is there anyway to go around fixing this, or will it require hacking the cloud zoom source to also include some kind of jQuery.live() functionality?
Looking at the cloud zoom source, they do indeed use .bind(), which of course only binds handlers to existing elements. Just search and replace .bind with .live in the main cloud-zoom src, and everything should work.

Categories