I'm trying to create multiple infowindow for multiple marker, But it seem like just refer to last infowindow
This is my code (in for loop, _lat and _long is unique value):
marker.addListener('click', function(){
//markerInfoWindow.close();
markerInfoWindow.setContent('Unsave place', true);
markerInfoWindow.open(map, this);
});
marker.setMap(map);
I tested with marker, marker show correctly but all of them link to the last infoWindow.
How can I make new infoWindow for each Marker?
Update:
This is fully my function after update:
function getListPosition(listMarkers, map){
db.transaction(function(tx){
tx.executeSql('SELECT * FROM Position', [], function(tx, rs) {
var numberOfItems = rs.rows.length;
var markerInfoWindow = new google.maps.InfoWindow();
var marker;
for (var i = 0; i < numberOfItems; i++) {
var _lat = rs.rows.item(i).Lat;
var _long = rs.rows.item(i).Long;
marker = new google.maps.Marker({
position: {lat: _lat , lng: _long}
});
listMarkers.push(marker);
google.maps.event.addListener(marker, 'click', (function(marker) {
return function() {
markerInfoWindow.setContent('Unsave place', true);
markerInfoWindow.open(map, marker);
}
})(marker));
// marker.addListener('click', function(){
// //markerInfoWindow.close();
// markerInfoWindow.setContent('Unsave place', true);
// markerInfoWindow.open(map, this);
// });
marker.setMap(map);
// Set map center to the last marker
if (i == numberOfItems - 1){
map.setCenter({lat: _lat, lng: _long});
}
}
});
}, function(err){
console.log('Error when get list position. Error code: ' + err.code);
});
}
You need function closure on the loop variables that are needed when the click listener function runs. In your case _lat and _lng. It would probably be simplest to just get those from the marker (this) though:
google.maps.event.addListener(marker, 'click', function(evt) {
markerInfoWindow.setContent('Unsave place', true);
markerInfoWindow.open(map, this);
});
(not tested)
Related
I am using ionic to display benefits data on Google map. It works fine except on click of any marker, it opens the last markup content. Follownig is my google map js code
.controller('BenefitsMapCtrl', function ($scope, LocationBenefits, Utilities, $ionicLoading, $compile) {
$scope.init = function () {
var userId = Utilities.getUserId();
LocationBenefits.getLocationBenefits(userId, function (userBenefits) {
console.log("Got location benefits data for Google mp for user id "+userId);
$scope.userBenefits = userBenefits;
var centerLatlng;
if (typeof $scope.userBenefits !== "undefined" && $scope.userBenefits.length > 0) {
var firstBenefitLocation = $scope.userBenefits[0];
centerLatlng = new google.maps.LatLng(firstBenefitLocation.location.lat, firstBenefitLocation.location.lng);
}
var mapOptions = {
center: centerLatlng,
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
$scope.markers=[];
//Loop in each benefits and place on Google map
if (typeof $scope.userBenefits !== "undefined" && $scope.userBenefits.length > 0) {
for (var i = 0; i < $scope.userBenefits.length; i++) {
var benefit = $scope.userBenefits[i];
//Marker + infowindow + angularjs compiled ng-click
var contentString = "<div><div><img class='shop-icon' src='" + benefit.shopicon + "' alt='" + benefit.shopName + "'/><span class='item-text-wrap'>" + benefit.shopName + "</span></div><div class='shop-offer'>"+benefit.benefits.short_benefitText+"</div><div class='card'><img class='card-art' src='"+benefit.cardart+"' alt='"+benefit.card+"'/></div></div>";
var compiled = $compile(contentString)($scope);
var infowindow = new google.maps.InfoWindow({
content: compiled[0]
});
//Get location
var locationLatLng = new google.maps.LatLng(benefit.location.lat, benefit.location.lng);
var marker = new google.maps.Marker({
position: locationLatLng,
map: map,
title: benefit.shopName
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
$scope.markers.push(marker);
}
}
//Finally set the map
$scope.map = map;
});
};
// google.maps.event.addDomListener(window, 'load', initialize);
$scope.centerOnMe = function () {
if (!$scope.map) {
return;
}
$scope.loading = $ionicLoading.show({
content: 'Getting current location...',
showBackdrop: false
});
navigator.geolocation.getCurrentPosition(function (pos) {
$scope.map.setCenter(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
$scope.loading.hide();
}, function (error) {
alert('Unable to get location: ' + error.message);
});
};
$scope.clickTest = function () {
alert('Example of infowindow with ng-click')
};
});
Issue: On click of any markup on Google map, it always opens the last markup.
Please help.
I had the same problem and spend a lot of time to figure out what's going on so I'd like to add the answer for the future generations,lol.
First of all it's a good idea to refer to official Google maps API docs and take a look at "Events section". I found there one interface of adding event listeners to markers that I never seen before(even after googling this issue for few hours).
marker.addListener('click', function() {});
google.maps.event.addListener(marker, 'click', function () {});
It pointed me out to the idea that when you are trying to do it in the loop using an "old" way, your marker variable is obviously equals to the last element of your markers array. And when event really can be triggered your initialization process is finished what means that your variable has always wrong value in anonymous function at the moment it can be really called. So, again, you didn't passed marker as a parameter to that anonymous event handler.
But you still can do what you want. Just use this.inside your event handler. Bellow is my code sample
marker.addListener('click', function() {
var it = this;
$scope.$apply(function() {
$scope.activeEvent = EventService.getShort($scope.events[it.id]);
});
});
I believe that you can try to use this. in "old-style" interface as well.
I had the same problem and I found the solution here. Apparently, you just have to create a function to create the markers and call that function inside the for loop:
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
$scope.map = map; //Attach the map to the scope before adding the markers
$scope.markers=[];
var infowindow = new google.maps.InfoWindow();
var createMarkers = function (benefit){
//Info window's content
var contentString = "<div><div><img class='shop-icon' src='" + benefit.shopicon + "' alt='" + benefit.shopName + "'/><span class='item-text-wrap'>" + benefit.shopName + "</span></div><div class='shop-offer'>"+benefit.benefits.short_benefitText+"</div><div class='card'><img class='card-art' src='"+benefit.cardart+"' alt='"+benefit.card+"'/></div></div>";
var compiled = $compile(contentString)($scope);
//Get location
var locationLatLng = new google.maps.LatLng(benefit.location.lat, benefit.location.lng);
//Create marker
var marker = new google.maps.Marker({
position: locationLatLng,
map: map,
title: benefit.shopName
});
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent(compiled[0]);
infoWindow.open($scope.map, marker);
});
$scope.markers.push(marker);
}
//Loop in each benefits and place on Google map
if (typeof $scope.userBenefits !== "undefined" && $scope.userBenefits.length > 0) {
for (var i = 0; i < $scope.userBenefits.length; i++) {
var benefit = $scope.userBenefits[i];
createMarkers(benefit);
}
}
I have a problem with InfoWindow. I have an ajax function that retrieves data via JSON, but I can not get close InfoWindow automatically when you open another.
My code is this:
var mapOptions = {
center: new google.maps.LatLng(44.49423583832911, 11.346244544982937),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("mappa_locali"),mapOptions);
$.ajax({
type:'GET',
url:"locali_json.php"+urlz,
success:function(data){
var json = JSON.parse(data);
for (var i=0; i<json.length; i++) {
point = new google.maps.LatLng(json[i].latitudine,json[i].longitudine);
var infowindow = new google.maps.InfoWindow;
infowindow.setContent(''+json[i].nome_locale+'<br>'+json[i].address);
addMarkerz(point,infowindow);
}
}
})
}
function addMarkerz(point,infowindow) {
position: point,
map: map
});
google.maps.event.addListener(marker,'mouseover',infoCallback(infowindow, marker));
markers.push(marker);
infos.push(infowindow);
}
function infoCallback(infowindow, marker) {
return function() {
infowindow.close();
infowindow.open(map, marker);
};
}
Does anyone know where decreased mistake? Or do you have any advice for me?
The suggestion is only create one infowindow (in the global scope), reuse it and change its contents when a marker is clicked, close it if the user clicks on the map.
code snippet (removes the dependency on the AJAX call):
// global variables
var map;
var markers = [];
var infowindow = new google.maps.InfoWindow();
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(44.49423583832911, 11.346244544982937),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("mappa_locali"), mapOptions);
var json = JSON.parse(data);
for (var i = 0; i < json.length; i++) {
point = new google.maps.LatLng(json[i].latitudine, json[i].longitudine);
var infowindowHtml = '' + json[i].nome_locale + '<br>' + json[i].address;
addMarkerz(point, infowindowHtml);
}
}
function addMarkerz(point, infowindowHtml) {
var marker = new google.maps.Marker({
position: point,
map: map
});
google.maps.event.addListener(marker, 'mouseover', infoCallback(infowindowHtml, marker));
markers.push(marker);
}
function infoCallback(infowindowHtml, marker) {
return function() {
infowindow.close();
// update the content of the infowindow before opening it
infowindow.setContent(infowindowHtml)
infowindow.open(map, marker);
};
}
var data = JSON.stringify([{
latitudine: 44.494887,
longitudine: 11.3426163,
id_locale: "0",
nome_locale: "Bologna",
address: "Bologna, Italy"
}, {
latitudine: 44.4946615,
longitudine: 11.314634999999953,
id_locale: "0",
nome_locale: "Quartiere Saragozza",
address: "Quartiere Saragozza, Bologna, Italy"
}]);
google.maps.event.addDomListener(window, "load", initialize);
html,
body,
#mappa_locali {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="mappa_locali"></div>
function infoCallback(infowindow, marker) {
return function() {
infowindow.close();
infowindow.open(map, marker);
};
}
should be changed to
function infoCallback(infowindow, marker) {
return function() {
//Close active window if exists
if (activeWindow != null) {
activeWindow.close();
}
//Open new window
infowindow.open(map,marker);
//Store new window in global variable
activeWindow = infowindow;
};
}
and declare activeWindow as a global variable in your .js file as var activeWindow.
I think I have a simple solution. I just save the last open mark. On the next click first of all I close the last mark.
var markers = [];
var infowindows = [];
function addMarkes(facilityID) {
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < variants.length; i++) {
var v = variants[i];
var position = new google.maps.LatLng(v.Lat, v.Long);
bounds.extend(position);
markers[i] = new google.maps.Marker({
position: position,
title: v.Title,
map: map,
animation: google.maps.Animation.DROP,
icon: v.Icon,
infoWindowIndex: i //synchronize with infoWindows
});
var localContent = '<div><span class="address">' + v.Address + '</span></div>';
infowindows[i] = new google.maps.InfoWindow({
content: localContent
});
//Just for multiple marks.
if (variants.length > 0) {
var lastOpen = -1; //Save the last open mark
google.maps.event.addListener(markers[i], 'click', function (innerKey) {
return function () {
//Close the last mark.
if (lastOpen > -1) {
infowindows[lastOpen].close();
}
infowindows[innerKey].open(map, markers[innerKey]);
lastOpen = innerKey;
}
}(i));
}
}
map.fitBounds(bounds);
}
I have a java script function which I am using to display a marker on the selected position of the map and also show the latitude and longitude at the marker's location in a InfoWindow.
I could display the marker at any location but unable to show a InfoWindow with the coordinates.
This is the function:
function init()
{
var mapoptions=
{
center: new google.maps.LatLng(17.379064211298, 78.478946685791),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map=new google.maps.Map(document.getElementById("map_can"), mapoptions);
var marker;
google.maps.event.addListener(map,'click',function(event)
{
marker= new google.maps.Marker({position:event.latLng,map:map});
});
var iwindow= new google.maps.InfoWindow();
google.maps.event.addListener(marker,'click',function(event)
{
iwindow.setContent(event.latLng.lat()+","+event.latLng.lng());
iwindow.open(map,marker);
});
}
Where am I wrong? Suggestions please.
This is because you attach event to an empty marker object (it is unassigned at the moment when you invoke
google.maps.event.addListener(marker,'click',function(event) { ... });
Try attaching click event to the marker after you create it, e.g.:
google.maps.event.addListener(map,'click',function(event)
{
marker= new google.maps.Marker({position:event.latLng,map:map});
google.maps.event.addListener(marker,'click',function(event)
{
iwindow.setContent(event.latLng.lat()+","+event.latLng.lng());
iwindow.open(map,marker);
});
});
You can try this snipped code :
function addMarkerWithTimeout(position, timeout, id) {
window.setTimeout(function () {
markers.push(new google.maps.Marker({
position: position,
map: map,
icon: image1,
title: "whatever!",
draggable: true,
animation: google.maps.Animation.ROUTE
}));
google.maps.event.addListener(map, 'click', function (event)
{
google.maps.event.addListener(markers[id], 'click', function (event)
{
infoWindow.setContent(event.latLng.lat() + "," + event.latLng.lng());
infoWindow.open(map, markers[id]);
});
});
}, timeout);
}
I've seen several other posts about this, but the answers from those responses don't work for me.
The other responses:
How do I bind a google maps geocoder.geocode() callback function
Backbone.js with Google Maps - problems with this and listeners
My code:
var ns = namespace('camelcase.geomanager.map');
ns.Site = Backbone.Model.extend({
url: '/site'
});
ns.Sites = Backbone.Collection.extend({
model: ns.Site
});
ns.MapView = Backbone.View.extend({
initialize: function() {
this.markers = new Array();
// Create the Google Map
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.googleMap = new google.maps.Map(this.$(".mapCanvas")[0], mapOptions);
// Register events
this.collection.on('add', this.addSite, this);
this.collection.on('remove', this.removeSite, this);
},
addSite: function(model) {
// Get model attributes
var elementId = model.get('elementId');
var latitude = model.get('latitude');
var longitude = model.get('longitude');
var id = model.get('id');
var notes = model.get('notes');
var title = ""+id;
// Create icon and marker
var icon = '/resources/img/elements/' + elementId + '_marker.png';
var latLng = new google.maps.LatLng(latitude, longitude);
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: this.googleMap,
icon: icon
});
// Load info window
var siteBubbleTemplate = _.template($('#siteBubbleTemplate').html());
var siteContent = $(siteBubbleTemplate({
siteId: id,
siteNotes: notes
}))[0];
var infoWindow = new google.maps.InfoWindow({
content: siteContent
});
// Show info window when clicking on marker
_.bindAll(this, this.openSite);
google.maps.event.addListener(marker, 'click', this.openSite(id));
this.markers.push({
id: id,
marker: marker,
infoWindow: infoWindow
});
},
openSite: function(id) {
var marker;
for (var c=0; c<this.markers.length; c++) {
marker = this.markers[c];
// Open the appropriate marker info window
if (marker.id == id) {
marker.infoWindow.open(googleMap, marker.marker);
}
// Close the rest
else {
marker.infoWindow.close();
}
}
}
});
The offending line:
google.maps.event.addListener(marker, 'click', this.openSite(id));
The error being reported in firebug:
TypeError: func is undefined
underscore.js (line 482)
I suspect this.marker is the problem, since you should be able to just refer to it by name.
google.maps.event.addListener(marker, 'click', this.openSite(id));
Looks like it was a scoping issue. I solved my problem with the following code:
// Show info window when clicking on marker
_.bindAll(this);
var _self = this;
var doSomething = function(event) {
_self.openSite({
event: event
});
};
google.maps.event.addListener(marker, 'click', doSomething);
I'll give the answer to whoever can best explain why this works.
In a model/collection event handler, Backbone sets 'this' to the model/collection which raised the event. If you call _.bindAll(this) in your view's initialize(), 'this' will be set to the view in your event handlers. Check out this jsfiddle: http://jsfiddle.net/9cvVv/339/ and see what happens when you uncomment _.bindAll(this);
var MyView = Backbone.View.extend({
initialize: function() {
// TODO: uncomment this line
// _.bindAll(this);
this.collection.bind('myEvent', this.onDoSomething);
},
updateCollection: function() {
this.collection.doSomething();
},
onDoSomething: function() {
if (this.models && typeof this.models.length === 'number') {
alert('"this" is a collection.');
}
else if (this.collection) {
alert('"this" is the view.');
}
else {
alert('"this" is something else.');
}
}
});
I created a google maps (api v3) with the number of markers depending on the search results. When I click a marker, it opens an infowindow. What's the best way to have that infowindow show information associated to its marker? The information related to all the markers is in a json object I receive from an ajax request.
for (i=0; i < result.point.length; i++) {
var latLng = new google.maps.LatLng(result.proint[i].Latitude,result.point[i].Longitude);
var marker = new google.maps.Marker({
position: latLng,
title: i.toString()
//map: map
});
markersArray.push(marker);
var infowindow = new google.maps.InfoWindow({
content: 'specific information associated to the marker clicked'
});
google.maps.event.addListener(markersArray[i], 'click', function(event) {
infowindow.open(map, this);
});
Create only 1 infoWindow as suggested above.
The content store inside the marker:
var marker = new google.maps.Marker({
position: latLng,
title: i.toString(),
//set your content here
content:'your specific content'
//map: map
});
The opening of the window:
google.maps.event.addListener(markersArray[i], 'click', function(event) {
infoWindow.setContent(this.content);
infowindow.open(map, this);
});
First, you should move the the creation of the infoWindow out of the for loop.
Next, change where you attach the click event to this:
google.maps.event.addListener(markersArray[i], 'click', function(content) {
return function(event){
infowindow.setContent(content);
infowindow.open(map, this);
}
}(WHATEVER_THE_CONTENT_SHOULD_BE_FOR_THIS_MARKER));
You want to use this instead of marker. this will refer to the object the event took place on, while marker will refer to the last marker created.
You have some typos in your example (proint) At the top of you loop:
for (i=0; i < result.point.length; i++) {
var info_window_content = result.point[i].Latitude + '<br />';
info_window_content += result.point[i].Longitue + '<br />';
// etc for any value in you json object
// create your marker as is.
...
var infowindow = new google.maps.InfoWindow({
content: info_window_content
});
// etc, etc.
You do need to add an eventListener to each marker, as you are doing. I don't see any problem with that.
Except I'd use infoWindow.open(map, marker) vs. this.
There is probably a more efficient way to do it, i.e. after infoWindow.open(); infoWindow.setContent(info_window_content)
Try this, it works I tested it already
// Add markers
for (i=0; i < result.point.length; i++) {
var latLng = new google.maps.LatLng(result.proint[i].Latitude, result.point[i].Longitude);
var marker = new google.maps.Marker({
position: latLng,
title: i.toString()
//map: map
});
// marker info start
var infowindow = new google.maps.InfoWindow();
(function (marker, result.point[i]) {
// add click event
google.maps.event.addListener(marker, 'click', function() {
var infoContent: "specific information associated to the marker clicked"
});
infoWindow.setContent(infoContent);
infowindow.open(map, marker);
});
// selected marker 4 infowindow
(marker, result.point[i]);
markersArray.push(marker);
}
Not entirely sure what it is you are trying to do. Where/ what content are you trying to load?
google.maps.event.addListener(marker, 'click', (function(event, index) {
return function(){
infowindow.content = markersArray[index].yourcontent;
// or
infowindow.content = yourcontentarray[index];
infowindow.open(map,this);
}
})(marker,i));
Make sure you declare your marker and infowindow variables outside of a function.