Mouse over popup on leaflet.js marker - popup

How can I add a mouse over pop up on leaflet.js marker . the pop up data will be dynamic.
I have a service which returns a lat & lon positions which will mark on a map.
I would require a popup on mouse over a marker . the event should send the lat and long position for ex to : http://api.openweathermap.org/data/2.5/weather?lat=40&lon=-100
the data from service should be in popup content.
I have tried but cant build the pop up content dynamically each marker
Please do the needful.
below is the code i have used for markers statesdata is array which stores the lat and longitude values
for ( var i=0; i < totalLength1; i++ ) {
var LamMarker = new L.marker([statesData1[i].KK, statesData1[i].LL]).on('contextmenu',function(e) {
onClick(this, i);
}).on('click',function(e) {
onClick1(this, i)
});
marker_a1.push(LamMarker);
map.addLayer(marker_a1[i]);
on click we call click1 function on context of marker we call click function
How can i add a pop on mouse over passing lat and long from the above code?

Attaching a popup to a marker is fairly easy. It is done by calling the bindPopup method of your L.Marker instance. Per default a popup opens on the click event of the L.Marker instance and closes on the click event of your L.Map instance. Now if you want to do something when a popup opens you can listen to the popupopen event of your L.Map instance.
When you want fetch external data in the background on the popupopen event that is usually done via XHR/AJAX. You can write your own logic or use something like jQuery's XHR/AJAX methods like $.getJSON. Once you receive response data you can then update your popup's content.
In code with comments to explain further:
// A new marker
var marker = new L.Marker([40.7127, -74.0059]).addTo(map);
// Bind popup with content
marker.bindPopup('No data yet, please wait...');
// Listen for the popupopen event on the map
map.on('popupopen', function(event){
// Grab the latitude and longitude from the popup
var ll = event.popup.getLatLng();
// Create url to use for getting the data
var url = 'http://api.openweathermap.org/data/2.5/weather?lat='+ll.lat+'&lon='+ll.lng;
// Fetch the data with the created url
$.getJSON(url, function(response){
// Use response data to update the popup's content
event.popup.setContent('Temperature: ' + response.main.temp);
});
});
// Listen for the popupclose event on the map
map.on('popupclose', function(event){
// Restore previous content
event.popup.setContent('No data yet, please wait...');
});
Here's a working example on Plunker: http://plnkr.co/edit/oq7RO5?p=preview
After comments:
If you want to open the popup on hover instead of click you can add this:
marker.on('mouseover', function(event){
marker.openPopup();
});
If you want to close the popup when you stop hovering instead of map click add this:
marker.on('mouseout', function(event){
marker.closePopup();
});
Here's an updated example: http://plnkr.co/edit/wlPV4F?p=preview

I got fed up with fighting with leaflet's built in functionality. The first thing I did was use the alt option to assign a key to the marker:
var myLocation = myMap.addLayer(L.marker(lat,lng],{icon: icon,alt: myKey}))
The next thing was assign an id using this alt and a title via jQuery (why you can't do that by default irritates me):
$('img[alt='+myKey+']').attr('id','marker_'+myKey).attr('title',sRolloverContent)
Then, I used jQuery tooltip (html will only render this way):
$('#marker_'+myKey).tooltip({
content: sRolloverContent
})
Also, by using the jQuery tooltip instead of the click-only bindPopup, I am able to fire the tooltip from my list, where the row has a matching key id:
$('.search-result-list').live('mouseover',function(){
$('#marker_'+$(this).attr('id')).tooltip('open')
})
$('.search-result-list').live('mouseout',function(){
$('#marker_'+$(this).attr('id')).tooltip('close')
})
By adding the id, I can easily use jQuery to do whatever I want, like highlight a list of locations when the marker is hovered:
$('#marker_'+iFireRescue_id).on('mouseover',function(){
('tr#'+getIndex($(this).attr('id'))).removeClass('alt').removeClass('alt-not').addClass('highlight')
})
$('#marker_'+myKey).on('mouseout',function(){
$('tr#'+getIndex($(this).attr('id'))).removeClass('highlight')
$('#search-results-table tbody tr:odd').addClass('alt')
$('#search-results-table tbody tr:even').addClass('alt-not')
})

Related

How to get contents on BindPopup

I am trying to get marker's .bindPopup content on click event so I can save it to localStorage. But it is not working properly for each marker.
L.marker([76.920614, -60.117188])
.addTo(map)
.bindPopup('<div><span class="claimed">DATA 1</span></div>')
.on('click', groupClick);
L.marker([77.841848, -31.289063])
.addTo(map)
.bindPopup('<div><span class="claimed">DATA 2/span></div>')
.on('click', groupClick)
function groupClick(event) {
var a = document.querySelector('.claimed').innerHTML;
console.log(a);
}
it would work on first click but on the second click on different marker, it will take the data from the first marker that i clicked instead of the second marker. In this case i have to click somewhere else on the map or click the popup close button first before i can click on the next marker to properly get the data. is there any fix on this?
PROBLEM:
you are selecting in your function only the first appearance of the class (not the clicked ones child) at
var a = document.querySelector('.claimed').innerHTML;
SOLUTION 1 (NOT RECOMMENDED):
You should use the this keyword, and the getPopup() and getContent() methods instead, your function should look something like:
function groupClick(event) {
var a = this.getPopup().getContent();
console.log(a);
}
This way you'll get the escaped html, so a much better and proper way is...
SOLUTION 2 (RECOMMENDED): if you store the necessary data in the markers options (instead of storing and getting html from popup), like this:
L.marker([40, 12], {data: 1, datastring: 'first'})
.addTo(map)
.bindPopup('ONE')
.on('click', groupClick);
Then you can access this options in your function this way:
function groupClick(event) {
var a = this.options.data + ' ' + this.options.datastring;
alert(a);
}
A working fiddle again.
EDIT: I have found a workaround for the desired logic. But still, you need to link the marker and its popup content, because:
Popup content is not a node in the DOM, so you cannot access it before it is opened with a user click.
So in my solution i store a simple integer in the marker options (divId: int), which is the unique id of the marker. In the popup content, the radio inputs have the same id concatenated with the desired string (<input type="radio" id="Item-10-0" name="Item-10" value="0" checked="">).
L.marker([40, 32], {
divId: 10
})
.addTo(map)
.bindPopup('<div id="2div" class="popup-todo"><input type="radio" id="Item-10-0" name="Item-10" value="0" checked=""><label for="Item-10-0">Claimed</label><input type="radio" id="Item-10-1" name="Item-10" value="1"><label for="Item-10-1">Unclaimed</label></div>')
.on('click', groupClick);
If the user clicks, the new node is already accessible, so you can select it and use its id and value.
function groupClick(event) {
var a = document.querySelector('input[name=Item-'+this.options.divId+']');
document.querySelector('#demo').innerHTML = a.id + ' ' + a.value;
}
The fiddle.

How to use the .openPopup method in a feature group?

I have a set of markers that have binded popups, but I can't figure out how to show all the popups when the marker group is toggled in the layers control.
For example, I have my markers like so:
var testMarker = L.marker([32.9076,33.35449]).bindPopup('Marker 1');
var testMarkerTwo = L.marker([33.58259,34.64539]).bindPopup('Marker 2');
Then, I put it in a freature group and append the openPopup method:
var markerGroup = L.featureGroup([testMarker,testMarkerTwo]).openPopup().addTo(map);
This doesn't work.
My final goal is to add that featureGroup to my layers control where I can toggle the group off/on. Before I get to that part, I need to first understand why the openPopup method is not working.
Edit: The answer below appears to only work with the plain Leaflet API, not the Mapbox API.
There are a couple problems here. The first is that by default, Leaflet closes the previously opened popup each time another is opened. The second is that, while your markers have popups bound to them, markerGroup does not, and even if it did, markerGroup.openPopup would only cause a single popup to open.
To get around the first problem, you can use the hack from this answer. If you place the following code at the beginning of your script (before you define your map) it will override the default behavior and allow you to open multiple popups at once:
L.Map = L.Map.extend({
openPopup: function(popup) {
this._popup = popup;
return this.addLayer(popup).fire('popupopen', {
popup: this._popup
});
}
});
Then, once you are able to open multiple popups, you can open all popups in markerGroup using the eachLayer method:
var markerGroup = L.featureGroup([testMarker,testMarkerTwo]).addTo(map);
markerGroup.eachLayer(function(layer) {
layer.openPopup();
});
Here is an example fiddle:
http://fiddle.jshell.net/nathansnider/02gsb1Lt/

Is there a way in leaflet to get the coordinates of a map click when clicking on a polygon?

It is easy enough to get the lat lng of a map click using something like:
map.on('click', function (e) {
coords= e.latlng.lat + ", " + e.latlng.lng;
});
But if there are shapes on the map the function doesn't get called if you click a place covered by a shape.
Ultimately I want to produce a popup window triggered when a shape is clicked and populated with information based on lat/long.
Welcome to SO!
You could bind your event listener on your shapes as well (possibly through an L.FeatureGroup to avoid having to bind to each individual shape), and you can even use that event listener to fire the "click" event on the map as well.
var shapes = L.featureGroup().addTo(map);
shapes.addLayer(/* some vector shape */); // As many times as individual shapes
shapes.on("click", function (event) {
shapecoords.innerHTML = event.latlng.toString();
map.fire("click", event); // Trigger a map click as well.
});
Demo: http://jsfiddle.net/ve2huzxw/40/

Leaflet Maps Marker Popup Open on Hashtag from URL

I am passing a latlng from a link on another page to my map. My map has the markers based on this latlng. So what I am passing is exactly what the map markers are using to show on the map.
var hash = window.location.hash;
var hashless = hash.replace("#", "");
var ll = hashless.split(",", 2);
map.setView(new L.LatLng(ll[0], ll[1]), 14);
This is working great, but I am struggling at getting the marker to show it's infowindow. I would like only the link clicked on to be the marker that is showing it's popup. I am able to zoom right to the marker, but not able to get the popup to work in a reasonable way.
I have tried a few things, but map.getBounds() seems to be the one I should be working with, unless you can ID a marker based on Lat/Lng. Can you?
I am using bounds in the map.on function.... but none of the events seems to really work well. Originally thought LOAD would do it, but no results... viewreset, mousemove, etc... all show the popup in this simple function, but it is not really any good as it flickers etc... when moving things around:
map.on('viewreset', function () {
// Construct an empty list to fill with onscreen markers.
console.log("YA");
var inBounds = [], bounds = map.getBounds();
datalayer.eachLayer(function (marker) {
if (bounds.contains(marker.getLatLng())) {
inBounds.push(marker.options.title);
marker.openPopup();
}
});
});
How can I set the marker.openPopup() from my link to the current marker at that lat/lng passed to it?

Leaflet.Draw save marker to DB

I'm trying to save marker to DB with fields
lat, lon , marker description.
If there is only one marker on the map everything is fine, but when I add a second one, my code generate 2 sql-s instead 1 and duplicates 1st added marker info.
This is my code:
map.on('draw:created', function (e) {
var type = e.layerType;
var layer = e.layer;
var marker_lat = layer._latlng.lat;
var marker_lng = layer._latlng.lng;
// Here I open Popup to save Marker discription
$('#point_description').modal('show');
// Here save marker lat, Lng + marker description
$(document).on('click', '#save_point', function () {
var point_description_text = $('#point_description_text').val();
insertPlaques(marker_lat, marker_lng, point_description_text, modal_window);
});
drawnItems.addLayer(layer);
});
Your 'draw:created' function is going to be called everytime a new shape is created by Leaflet.Draw. Everytime that method is called, a new on 'click' listener is added to the '#save_point' element. So the second time 'draw:created' is called (and the user clicks '#save_point'), two listeners will be invoked. The third time, three listeners will be invoked.
You should either remove your click listener using off() after the insertPlaques method is called, or consider using a method like one() to add your click listener instead of on() (https://api.jquery.com/one/)