ionic for multi marker google map opens last markup - google-maps-api-3

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);
}
}

Related

Multiple infoWindow in Google Map API

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)

new info window does not work when i click on google map marker

Hello i am having problem to show new infowindow when i click on marker.I want to show infowindow after click on marker. Please someone one give me a solution. My code is given bellow.
var markerClusterer = null;
var map = null;
function refreshMap() {
if (markerClusterer) {
markerClusterer.clearMarkers();
}
var markers = [];
var style = parseInt(document.getElementById('style').value, 10);
if (style == 0) {
var data =w_plaza;
var imageUrl = 'images/walton.png';
}
if (style == 1) {
var data =w_dealer;
var imageUrl = 'images/people35.png';
}
if (style == 2) {
var data =w_service_center;
var imageUrl = 'images/service_center.png';
}
var markerImage = new google.maps.MarkerImage(imageUrl);
// var markerImage = new google.maps.MarkerImage(imageUrl,
//new google.maps.Size(24, 32));
for (var i = 0; i < data.length; i++) {
var loc = data[i];
var latLng = new google.maps.LatLng(loc[1],loc[2]);
var content = loc[0] + ":" + loc[1] + "," + loc[2];
var marker = new google.maps.Marker({
position: latLng,
draggable: true,
icon: markerImage
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent("hello");
infowindow.open(map, marker);
});
markers.push(marker);
}
The first time we see infowindow in your code is at:
infowindow.setContent("hello");
What is infowindow, where was it created? Nowhere as far as I can see. Somewhere in your function, before we get as far as creating the marker, create it something like this:
var infowindow = new google.maps.InfoWindow();

Google Maps API - External link to map markers and open infowindow

I have a map populating with markers taken from an xml file that are stored in a database. Below the map I am pulling the same info from each marker and displaying them as listings. What I'm trying to to is create a <a href=""> type link that will open the corresponding marker and infowindow beside each listing. Here is my page, it might better explain what I mean: http://poultry.ie/plugin/page/breeders
Here is my code:
<script type="text/javascript">
//<![CDATA[
var redpin = new google.maps.MarkerImage('http://labs.google.com/ridefinder/images/mm_20_red.png',
new google.maps.Size(20,32),
new google.maps.Point(0,0),
new google.maps.Point(0,32)
);
var redpinshadow = new google.maps.MarkerImage('http://labs.google.com/ridefinder/images/mm_20_shadow.png',
new google.maps.Size(37,32),
new google.maps.Point(0,0),
new google.maps.Point(0, 32)
);
function load() {
var gmarkers = [];
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(53.5076512854544, -7.701416015625),
zoom: 7,
mapTypeId: 'roadmap'
});
var infoWindow = new google.maps.InfoWindow;
// Change this depending on the name of your PHP file
downloadUrl("http://poultry.ie/plugins/CustomPages/pages/phpsqlajax_genxml3.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
var phone = markers[i].getAttribute("phone");
var breeds = markers[i].getAttribute("breeds");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + name + "</b><br />" + address + "<br/>" + phone + "<br/>" + breeds;
var marker = new google.maps.Marker({
map: map,
shadow: redpinshadow,
icon: redpin,
position: point
});
bindInfoWindow(marker, map, infoWindow, html);
}
});
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
//]]>
</script>
And the php that is dynamically displaying the listings (for this one county):
//Armagh
$data = mysql_query("SELECT * FROM markers WHERE address='Armagh'")
or die(mysql_error());
while($info = mysql_fetch_array( $data ))
{
Print '<div class="county all armagh">';
Print "<h4>".$info['name'] . "</h4> ";
Print "<em>".$info['address'] . "</em><br /> ";
Print "".$info['phone'] . "<br /> ";
Print 'See on Map<br />';
Print "<em>Breeds:</em> ".$info['breeds'] . "<hr/></div>";
}
The <a href="javascript:myclick( is from a previous attempt at creating this, it doesn't actually have a function at the moment.
I have tried to apply many examples to my code without success as my knowledge of javascript is fairly limited to say the least. My above code might also not be the cleanest as it is my putting together from a lot of examples.
Here is an example (ported from Mike Williams' v2 tutorial) which loads markers from an xml file and has a clickable sidebar

Google Maps API with backbone, how to bind an event

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.');
}
}
});

Google Maps API v3 - set bounds and center not working with Ajax/PHP

I am trying to get the automatic bounds-and-zoom functions in Google Maps API 3 to work with Ajax/PHP-generated markers and having no luck so far. The PHP-gen map works fine (with manual center and zoom) until I add the bounds-related code, which I got from here at stackoverflow. It now just centers at (0,0) in the middle of the ocean and only the first of my markers displays. The former doesn't seem totally surprising based on the initial center declaration of (0,0), but it worked for the original poster and I'm a Javascript noob so don't really know what I'm doing! I would be eternally grateful if someone could spot the problem.
Here's my current code (I've left out the icon definitions to save space):
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(0, 0),
zoom: 10,
mapTypeId: '<?php echo $maptype; ?>'
});
var infoWindow = new google.maps.InfoWindow;
// Change this depending on the name of your PHP file
downloadUrl("gen-xml.php?<?php if($country) echo "country=$country"; if($location) echo "&location=$location"; ?>", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("city");
var type = markers[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lon")));
var html = "<div class='infowindow'>" + name + " <br/>" + address + " <br/></div>";
var icon = customIcons[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon,
shadow: icon.shadow
});
bounds.extend(myLatLng);
map.fitBounds(bounds);
bindInfoWindow(marker, map, infoWindow, html);
}
});
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
Try
bounds.extend(point);
instead of
bounds.extend(myLatLng);
which seems not to be related to any part of your code

Resources