Leaflet map: marker click change popup of different marker - javascript

I'm very basic at programming and require that option just for one specific project.
I'd love to change content of one master popup by clicking on different markers.
Thing is, I have 0 clue how to get .setContent() of popup on different marker, using .on('dblclick') my marker.
I was thinking about giving value to a variable depending on marker number, and then filling one specific popup with info regarding variable number.
I intentionally skipped code block as it wouldn't bring anyone closer to the problem I have. I added my 'project' on jsfiddle.
Thanks!!!
My project on jsfiddle
var map = L.map('map').setView(center, 11);
var popupMaster = L.popup({
closeOnClick: false,
autoClose: false,
closeButton: false
})
.setLatLng([54.451194, 18.744001])
.setContent('Show text here')
.openOn(map);
var marker1 = L.marker([54.351194, 18.644001], {
title: "F-25",
opacity: 0.5
})
.addTo(map)
.bindPopup(popup1)
.on('mouseover', function(e) {
this.openPopup();
this.setOpacity(1.0);
})
.on('mouseout', function(e) {
this.closePopup();
this.setOpacity(0.5)
});

You already have the master popup in a variable, so you can update the content from a dblclick event on another marker like this
marker.on("dblclick", function(e) {
popupMaster.setContent("New content here");
});

Related

MapBox GL JS marker offset

I'm using MapBox GL JS to create a map with a custom marker:
var marker = new mapboxgl.Marker(container)
.setLngLat([
datacenters[country][city].coordinates.lng,
datacenters[country][city].coordinates.lat
])
.addTo(map);
However, I seem to have some kind of offset problem with the marker. The thing is: when zoomed out a bit, the bottom of the marker is not really pointing to the exact location:
When I'm zooming in a bit further it reaches its destination and it's pointing to the exact spot.
I really love MapBox GL, but this particular problem is bugging me and I'd love to know how to solve it. When this is fixed my implementation is far more superior to the original mapping software I was using.
From Mapbox GL JS 0.22.0 you're able to set an offset option to the marker. https://www.mapbox.com/mapbox-gl-js/api/#Marker
For example to offset the marker so that it's anchor is the middle bottom (for your pin marker) you would use:
var marker = new mapboxgl.Marker(container, {
offset: [-width / 2, -height]
})
.setLngLat([
datacenters[country][city].coordinates.lng,
datacenters[country][city].coordinates.lat
])
.addTo(map);
New solution for mapbox-gl.js v1.0.0 - Marker objects now have an anchor option to set the position to align to the marker's Lat/Lng: https://docs.mapbox.com/mapbox-gl-js/api/#marker
var marker = new mapboxgl.Marker(container, {anchor: 'bottom');
This should cover most cases and is more reliable than a pixel offset in my experience.
I've found an solution to my problem. It might be somewhat hacky, but it solves the positioning problem of the marker: I'm using a Popup fill it with a font awesome map marker icon and remove it's "tooltip styled" borders:
Javascript:
map.on('load', function() {
var container = document.createElement('div');
var icon = document.createElement('i');
icon.dataset.city = city;
icon.addEventListener('click', function(e) {
var city = e.target.dataset.city;
var country = e.target.dataset.country
flyTo(datacenters[country][city].coordinates);
});
icon.classList.add('fa', 'fa-map-marker', 'fa-2x');
container.appendChild(icon);
var popup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false
})
.setLngLat([
datacenters[country][city].coordinates.lng,
datacenters[country][city].coordinates.lat
])
.setDOMContent(container)
.addTo(map);
});
CSS:
.map div.mapboxgl-popup-content {
background: none;
padding: 0;
}
.map .mapboxgl-popup-tip {
display: none;
}
I just hope someone comes up with a real solution, because this feels kinda dirty to me. But hey: it does the job just fine!
Mapbox Marker now has an element option see this link Mapbox Marker. So instead of appending the icon HTML to the Div element you can simply add into the options when creating a marker. I found this also gets rid of the offset problem. So using the code above you can do this....
var icon = document.createElement('i');
icon.classList.add('fas', 'fa-map-marker-alt');
icon.style.color = 'blue';
new mapboxgl.Marker(container, {anchor: 'center', offset: [0, 0], element: icon})
Also the CSS for the marker can be updated to allow a pointer
.mapboxgl-marker {
border: none;
cursor: pointer;
}

OnClick in an angular-openlayers-directive marker

Thats it I want to create an onclick event on my marker, I'm using angular-openlayers-directive.
So far I've been able to make some markers show up, but I'm unable to get them after a click event.
I would like to perform some actions with these markers custom properties like name, remarks, etc. But it seems too hard to achieve this with openlayers 3.
<openlayers ol-center="ven" height="100vh">
<ol-layer ol-layer-properties="wms">
<ol-marker ng-repeat="marker in markers"
lat="marker.lat"
lon="marker.lon"
></ol-marker>
</ol-layer>
</openlayers>
So how could I handle an onclick event on these markers and get all their info, or a reference to the javascript object "marker" itself.
I wasn't sure if you wanted to have the click on the popover or the marker itself. Below there are instructions for both. Use the Plunker link at the bottom to see a working demo of both options.
To Register Click on Marker Popover:
If you take a look at the directive, you can see that the marker template uses ng-transclude, so you can do the following:
Markup:
<ol-marker ol-marker-properties="santiago" >
<p ng-click="showDetails(santiago)">Santiago de Compostela</p>
</ol-marker>
In your controller:
$scope.showDetails = function(id) {
alert('lat: '+ id.lat+', '+'lon: '+id.lon);
};
Here I'm passing in the marker object to the showDetails function. When you click the popover label for Santiago de Compostela in the Plunker Demo, you'll see the corresponding lat/lon in the alert.
To Register Click on the Marker:
You can add an onClick property to the marker object as follows:
In your controller:
finisterre: {
lat: 42.907800500000000000,
lon: -9.265031499999964000,
label: {
show: false,
},
onClick: function (event, properties) {
console.log(properties);
alert('lat: '+ properties.lat+', '+'lon: '+properties.lon);
}
}
When you click the marker associated with finisterre in the Plunker Demo, you'll see the corresponding lat/lon in the alert.
NOTE:
I could only get this to work though under the following conditions:
The marker object must have a label property defined
The show property of the label must be set to false.
The ol-marker html element must have some transcluded content OR the message property must be set in the marker label object.
I was able to use CSS to prevent the popover from displaying as you can see in the demo, but it seems a little hacky. If you want the popover to display on click as well, you're all set, just remove the css hidden class I added and add your pop-over html.
Plunker Demo
I just got this working today as it happens. What I am doing for now is adding the properties to my markers once I get them from mongo.
function addMarkerProperties ()
// needed to enable click events on a marker!
// Have a label property defined for the marker.
// Have the show property of the label set to false.
// Have some transcluded content in the marker.
{
for (var i = $scope.markers.length - 1; i >= 0; i--) {
$scope.markers[i].onClick = function (event, properties) { console.log('Clicked a marker'); console.log(this); console.log(properties); };
$scope.markers[i].label = {
// Note: Duplication of data here # message. Fix this later.
"message": $scope.markers[i].name,
"show": false,
"showOnMouseOver": false
};
};
}
Once the markers have all the properties they need. It just sort of works but I do have a bug to iron out as well where the marker titles repeat above the map for.... reasons.
As you click the markers the words disappear.
With the latest release (April 6 2016) of the angular-openlayers-directive library (correct) ngClick-handling seems to be implemented. After a bit of searching I came up with the following solution:
The HTML (simplified):
<html ng-controller="mapController">
<openlayers width="100%" height="400px">
<ol-marker ng-repeat="marker in markers" ol-marker-properties="marker" ng-click="showDetails(marker)"></ol-marker>
</openlayers>
</html>
The Angular Javascript for the map controller (expects that your API endpoint called '/api/markerlist' returns a list of JSON objects with the fields: 'latitude', 'longitude'):
$scope.markers = [];
$scope.initializeMarkers = function() {
var markerList = $http.get("yoursite/api/markerlist")
.succes( function(result) {
angular.forEach(result, function(value, key) {
$scope.markers.push({
lat: value.latitude,
lon: value.longitude,
label: {
message: "Your message",
show: false,
showOnMouseOver: false
}
});
});
}
function showDetails(marker) {
alert('Clicked a marker on the map');
console.log(marker);
}
Finally, be sure that you have included the angular-openlayer-directive CSS, so the messages for the labels are not visible.

Accessing a jQuery element Google Maps Listener

I am using jQuery with a Google Maps Listener. I have boxes in my map and I need to make changes on them when they are too close.
The problem is the next one:
I check if the boxes are close and then make them red (for example). I know the condition is OK because I have a "console.log" and everything is nice. Here is my code:
Little explanation:
A marker is an element in the map. Every marker has his own infobox (the boxes in the map I want to change).
A cluster is a group of markers.
clusterListener2 = google.maps.event.addListener(markerCluster, 'click', function (clusterer) {
zoomLimit=12;
var myzoom = map.getZoom();
var olderPosk=1000000;
var olderPosD=1000000;
if (myzoom>zoomLimit) {
clusterClickController=1;
$.each(clusterer.getMarkers(), (function (index, marker) {
var restak=olderPosk-marker.position.k;
var restaD=olderPosD-marker.position.D;
if (restak<0) restak=restak*(-1);
if (restaD<0) restaD=restaD*(-1);
if ((restak<0.0001)&&(restaD<0.0001)) {
console.log("Close elements");
console.log($(this.infobox));
currentInfobox=$(this.infobox);
currentInfobox.css({"background" : "red"});
}
olderPosk=marker.position.k;
olderPosD=marker.position.D;
marker.marker.open(map, this);
marker.infobox.open(map,this);
marker.marker.isHidden = false;
}));
}
else {
clusterClickController=0;
}
});
So, the "Close elements" console.log is appearing in console and the $(this.infobox) prints a jQuery element but when I do the "background red" statement it does not work.
Any help? Thanks
I think you should use infobox.content_.style.cssText to set the new style instead. As it is shown in line 44 of this jsfiddle.

Pins disappearing on bing maps when map is panned

I'm trying to produce a mapping application with Bing Maps with a button that will retrieve a JSON string and places pins on the map based on the center of the map.
That is working fine, but I'm running into two issues that I'm having trouble diagnosing.
The first is that when I move the map after placing the pins, the majority of them disappear from the map except for 1-3. I've figured out that the pins are still being held in map.entities, but just aren't all displaying.
The second issue is that I have a click event on the pins, and sometimes when I click on a pin it will disappear (and sometimes reappear elsewhere on the map).
Here is my code:
function addPin() {
map.entities.clear();
var pinImg = "images/MapPin.jpg";
var latLong = {};
var name;
for (var i = 0; i < factualJson.response.data.length; ++i) {
latLong['latitude'] = factualJson.response.data[i].latitude;
latLong['longitude'] = factualJson.response.data[i].longitude;
name = factualJson.response.data[i].name;
var pin = new Microsoft.Maps.Pushpin(latLong, {
icon: pinImg,
anchor: new Microsoft.Maps.Point(latLong['latitude'], latLong['longitude']),
draggable: true,
width: 48,
height: 48
});
Microsoft.Maps.Events.addHandler(pin, 'click', displayName);
pin.title = name;
pin.id = 'pin' + i;
map.entities.push(pin);
}
document.getElementById("arrayLength").innerHTML = "Number of locations: " + map.entities.getLength();
}
function displayName(e) {
document.getElementById("name").innerHTML = "";
if (this.target.id != -1) {
document.getElementById("name").innerHTML = this.target.title;
}
}
function boot() {
Microsoft.Maps.loadModule('Microsoft.Maps.Overlays.Style', { callback: getMap });
}
function getMap() {
map = new Microsoft.Maps.Map($gel("bingMap"), {
credentials: getKey(),
customizeOverlays: true,
enableClickableLogo: true,
enableSearchLogo: true,
showDashboard: true,
showBreadcrumb: true,
showCopyright: true,
zoom: 10,
labelOverlay: Microsoft.Maps.LabelOverlay.hidden
});
setGeoLocation();
//setTimeout(optimizeMap, 100);
window.onresize = resizeWin;
resizeWin();
}
Currently I make an ajax call from the button, and the callback function calls 'AddPin' which adds the pins to the map. I thought I'd add in the map initialization code in case it was relevant. Currently boot() is called on body load.
For me the solution was similar to yours #canadian coder
Microsoft.Maps.Location() only accepts float values, no strings and Int.
I use MVC architecture and passed a string using a model. Later i converted that string to float and passed to Location.
Problem solved.
var pushpin = new Microsoft.Maps.Pushpin(
center, { icon: '/Content/BingPushpin.png', width: 50, height: 50, draggable: false });
pushpin.setLocation(new Microsoft.Maps.Location
(parseFloat(#Model.Latitude) , parseFloat(#Model.Longitude)));
dataLayer.push(pushpin);
locations.push(new Microsoft.Maps.Location
(parseFloat(#Model.Latitude) , parseFloat(#Model.Longitude)));
EDIT :
Later found out that problem still exist. Another reason can be that you are calling that Map to load twice. So check for any other instance of the map which is being loaded. In my case see below.
$(document).ready(function () {
loadSearchModule(); //calling Map to Load at a div without pushpins
//code to do something
getMapOnLocation();
}
function getMapOnLocation()
{//code to display map with pushpin
}
In the Above example I was telling the control to load my map with PushPins and when the page is fully Loaded load the map without pushpins.
Hope this helps :)
As always I need to ask the question before I figure it out myself.
The issue was that I needed to push a Microsoft location object into the pin and not an object. Like so:
var loc = new Microsoft.Maps.Location(47.592, -122.332);
And NOT my latLong object.
This also seemed to fix the issue of disappearing pins on click event.

Show tooltip on map marker

I want to show twitter bootstrap tooltip option when I hover on map marker so I do this:
function createMarker(place){
var placeLoc=place.geometry.location;
var image = 'https://mts.googleapis.com/vt/icon/name=icons/spotlight/spotlight-waypoint-a.png&psize=14&font=fonts/Roboto-Regular.ttf&color=fffa4c38&ax=44&ay=48&scale=1';
marker = new RichMarker({
position: placeLoc,
shadow: 0,
map: map,
content: '<div class="kikonica" data-toggle="tooltip" data-placement="right"><img src='+image+'</img></div>',
});
So my marker is html code with class .kikonica . I try to add tooltip with:
$(function() {
$('.kikonica').tooltop({placement: 'right'});
});
bt dont work. What is problem here?
I really dont understand why I cant show tooltip on map-marker hover...
please help
At first glance it Looks like you have a typo.
$('.kikonica').tooltop({placement: 'right'});
$(function() {
$('.kikonica').tooltip({placement: 'right'});
});
Edit: 1
I think you have to have a title attribute for the tooltip to work.
...
content: '<div title="my tooltip text" class="kikonica" data-toggle="tooltip" data-placement="right"><img src='+image+'</img></div>',
...
Edit 2
// check if .kikonica exists
$(function() {
alert ($('.kikonica').length);
if($('.kikonica').length > 0){
$('.kikonica').tooltip({placement: 'right'});
}
});
Edit 3
setTimeout(function(){
$('.kikonica').tooltip({placement: 'right'});
},50); // increse this value (50) to higher if needed
Edit 4
Use this signature
google.maps.event.addListener(marker, 'mouseover', function() {
$('.kikonica').tooltip({placement: 'right'});
});
A bit late to the party... But I would add the tooltip when the map is fully loaded to ensure correct tooltip behavior. Adding it on mouseover prevents it from displaying the very first hover.
// Add tooltips when map is fully loaded
google.maps.event.addListenerOnce(map, 'idle', function(){
$('.kikonica').tooltip({placement: 'right'});
});

Categories