I am pulling my latlng object from a database and when I loop through the query in the javascript the markers all populate just fine, but when ever I click on one they all open the same infoWindow object on a different marker. I assume this is some sort of naming issue, but I am having trouble finding out why because it all looks right to me. the following code is in a cfoutput tag creating the loop.
var latlng_#get_latlng.recordcount# = new google.maps.LatLng(#get_latlng.mlat#,#get_latlng.mlong#);
var marker_#get_latlng.recordcount# = new google.maps.Marker({
position: latlng_#get_latlng.recordcount#,
map: map,
title: "test"
});
var contentString_#get_latlng.recordcount# = "test" + #get_latlng.recordcount#;
var infowindow_#get_latlng.recordcount# = new google.maps.InfoWindow({
content: contentString_#get_latlng.recordcount#
});
google.maps.event.addListener(marker_#get_latlng.recordcount#, 'click', function() {
infowindow_#get_latlng.recordcount#.open(map,marker_#get_latlng.recordcount#);
});
Rather than producing so much redundant JS, I'd create a function that adds the markers.
function addMarker(lat, lng, title, content) {
var latlng = new google.maps.LatLng(lat, lng);
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: title
});
var infowindow = new google.maps.InfoWindow({ content: content });
google.maps.event.addListener(marker, "click", function() {
infowindow.open(map, marker);
});
}
Then in your loop:
addMarker(#get_latlng.mlat#,#get_latlng.mlong#,"#get_latlng.title#","#get_latlng.content#");
Doesn't 'recordcount' return the number of values in your result set? In which case, all your variable names will be the same. Therefore they will all be rendered correctly, but will continually overwrite the JavaScript variable reference: and will all create an infoWindow based on the last one you did.
You need a more unique name: I presume you wanted an index based on the resultset index, but a simple count would be fine.
Related
I set up a map with multiple markers using Google Maps Javascript API. If a marker is clicked, an infowindow opens. However, while the content is correct (different for each marker), the infowindow opens above one and the same marker, no matter which one is clicked.
To fix this, I tried to explicitly set the correct position (long/lat) in the eventlistener function. According to console log output, the values for long and lat are correct. But the infowindows still opens at the wrong, identical position.
Here is the code; placeMarker is called from within a loop through all locations:
var activeInfoWindow;
function placeMarker(map, lat, lng, markerurl, title, contentString) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
icon: markerurl,
map: map,
title: title,
});
var infowindow = new google.maps.InfoWindow({
content: contentString
});
google.maps.event.addListener(marker, 'click', function() {
// close other active infowindows
if (activeInfoWindow) {
activeInfoWindow.set("marker", null);
activeInfoWindow.close();
}
// added to explicitly set new position:
infowindow.setPosition(new google.maps.LatLng(lat, lng));
// check: console log shows on click: lat and long correct (different for each clicked marker)
console.log(lat+' '+lng+' '+title);
infowindow.open(map, marker);
activeInfoWindow = infowindow;
});
}
Any idea what I am missing?
Thanks!
Solved. Simply needed to add "var" before "marker":
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
icon: markerurl,
map: map,
title: title,
});
I have multiple markers and currently when more than one infoWindow is clicked, the other already-opened infoWindows stay open, cluttering the map. I would prefer it if I could simply reuse a single infoWindow, move it and update it's content. This is what I am attempting to do below:
var info = new SnazzyInfoWindow ();
/*
* Loop through each item in the 'features' array, including info windows, and display the marker
*/
features.forEach(function (feature) {
var marker = new google.maps.Marker({
position: feature.position,
icon: icons[feature.type].icon,
map: map
});
var infoContent = feature.contentImage + feature.content;
marker.addListener('click', function() {
infoCallback(infoContent, marker);
});
});
function infoCallback(infoContent, marker) {
return function() {
info.close();
info.setContent(infoContent)
info.open(map, marker);
};
};
However I am receiving the error Cannot read property 'placement' of undefined and can't seem to figure out what's wrong here.
Note that I am using the "Snazzy Info Window" plugin, but I think the same would apply to the stock infoWindow.
Yes. Inside the onClick function, when marker.addListener('click' is being executed, you don't have feature/marker. The variables are not what they were when the foreach was executed.
One trick I mostly use, is to make an array of the marker objects. Inside the onClick you search for the 'this' marker inside the array.
Something like this:
var markers = []; // store the markers in this array
features.forEach(function (feature) {
var marker = new google.maps.Marker({
position: feature.position,
icon: icons[feature.type].icon,
map: map
});
markers.push(marker);
marker.addListener('click', function() {
// first find out which marker was clicked on
var index = markers.indexOf(this); // this represents the marker that was clicked on
// index should be the same index as the index for features.
var feature = features[index];
var marker = markers[index];
var infoContent = feature.contentImage + feature.content;
// now we can call infoCallback.
infoCallback(infoContent, marker);
});
});
I'm having a google map where google markers are put up. The placement of markers works well. But if I click a marker, the adress should open up in an infowindow. The adress, longtitude and latitude are loaded from model.js into the variable myLocations.
EDIT: Currently a click on any marker returns the adress of the last object in myLocations. But I would like to get the myLocations.adress of the one who was clicked.
var markerspots;
var spot;
var j;
for (j = 0; j < myLocations.length; j++){
spot = {
lat: parseFloat(myLocations[j].lati),
lng: parseFloat(myLocations[j].long)
};
contentString = myLocations[j].adress;
markerspots = new google.maps.Marker({
position: spot,
map: map,
icon: markerspot,
content: contentString,
id: j
});
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(markerspots, "click", (function(marker) {
return function(evt) {
infowindow.setContent(contentString);
infowindow.open(map, markerspots);
}
})(markerspots));
}
I have found lots of solutions, but I don't understand any of those. So how can I make the content of the clicked marker show up in an infowindow?
Thanks
Well you are accessing your contentString, which is set to the last one you created in your for loop.
What you really want is the content property of the marker you clicked on, which is stored in this.
So
google.maps.event.addListener(markerspots, 'click', function() {
console.log(this.content);
});
should do the trick.
Example here: https://jsfiddle.net/4tpnh00u/
I really cant understand javascript, i know it should be a very easy question but i stucked..
I have a google map with multiple markers and i added every marker and work perfect but i wanted to give them links. My locations array is like;
['http://website.com',36.598900,35.202094,'1']
i use [1] and [2] as lat long but i wanted to use [0] as link. My loop works perfect but every marker's link going to last item's link
Here is my loop
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
map: map,
icon: image,
url: locations[i][0],
});
google.maps.event.addListener(marker, 'click', function() {
window.location.href = marker.url;
});
}
Where did i make the mistake?
1/ You need to add var before marker = new google.maps.Marker({ ,
Because , you use now marker as Global variable which is overridden for each iteration.
2/ Anyway, best practices are to save all markers as object attributes . Let's call this Object: mk , then your markers will be mk.marker0,mk.marker1,...so on.
var mk={}; // this is nameSpace to save all markers
locations.map((loc,i)=>{
mk['marker'+i] = new google.maps.Marker({
position: new google.maps.LatLng(loc[1], loc[2]),
map: map,
icon: image,
url: loc[0],
});
return mk['marker'+i];
}).forEach((marker)=>{
google.maps.event.addListener(marker, 'click', function() {
window.location.href = marker.url;
});
})
Wonder if anyone can help me, I have setup a google map all works nicely. The only thing I cant work out how to do is to open an info window based on ID from an external html link that's not in the JS.
function initialize() {
// Create the map
// No need to specify zoom and center as we fit the map further down.
var map = new google.maps.Map(document.getElementById("map"), {
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true
});
infowindow = new google.maps.InfoWindow();
// Custom markers
var icon = "img/marker.png";
// Define the list of markers.
// This could be generated server-side with a script creating the array.
var markers = [
{ val:0, lat: -40.149049, lng: 172.033095, title: "Title", html: "<div style='text-align:left'><h4 style='color:#0068a6;font-size:16px;margin:0px 0px 10px 0px;'>Title</h4><strong>Telephone</strong><br /><br />Address</div>" },
{ val:1, lat: -41.185765, lng: 174.827516, title: "Title", html: "<div style='text-align:left'><h4 style='color:#0068a6;font-size:16px;margin:0px 0px 10px 0px;'>Title</h4><strong>Telephone</strong><br /><br />Address</div>" },
];
// Create the markers ad infowindows.
for (index in markers) addMarker(markers[index]);
function addMarker(data) {
// Create the marker
var marker = new google.maps.Marker({
position: new google.maps.LatLng(data.lat, data.lng),
map: map,
title: data.title,
icon: icon,
id: data.val
});
// Create the infowindow with two DIV placeholders
// One for a text string, the other for the StreetView panorama.
var content = document.createElement("DIV");
var title = document.createElement("DIV");
title.innerHTML = data.html;
content.appendChild(title);
// Open the infowindow on marker click
google.maps.event.addListener(marker, "click", function() {
infowindow.setContent(content);
infowindow.open(map, this);
map.setCenter(this.position);
console.log(this.id);
});
}
// Zoom and center the map to fit the markers
// This logic could be conbined with the marker creation.
// Just keeping it separate for code clarity.
var bounds = new google.maps.LatLngBounds();
for (index in markers) {
var data = markers[index];
bounds.extend(new google.maps.LatLng(data.lat, data.lng));
}
map.fitBounds(bounds);
}
<p id="1">link to open marker</p>
Any help would be gratefully appreciated
Richard :)
The Golden Goose
Then in your js have a function to open the infowindow (such as show()) which takes the properties from that link (opening id 7).
function show(id){
myid = id;
if(markers[myid]){
map.panTo(markers[myid].getPoint());
setTimeout('GEvent.trigger(markers[myid], "click")',500);
map.hideControls();
}
}
That's the function I used previously with one of the marker managers from v2. You have to make sure you set an id for each marker as you set it and then you can call it.
The one thing I made sure of (to simplify matters) was to make sure the map marker set/array was exactly the same as the sql result I used on the page. That way, using id's was a piece of cake.