so I have a project that's working with Google Maps, using KnockoutJS. I define the markers like so:
for (i = 0; i < markerData.length; i++) {
// Grab marker data so we only have to call it once
var m = markerData[i];
// Define everything
var position = new google.maps.LatLng(m.location.lat, m.location.lng);
var title = m.title;
// etc etc
// Push all this info to the google maps marker
var marker = new google.maps.Marker({
map: map,
position: position,
title: title
// etc with rest
});
And then in the same for loop, I try to define an info window, simplified for reading:
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(this.title + '<br>' + this.address + '<br><a target="_blank" href="' + this.directions + '">Get Directions</a>');
infoWindow.open(map, this);
map.setCenter(this);
});
While it works exactly as I like it, linters are saying not to make a function inside the for loop. With that being said - is there a way I can move this outside the for loop and still get it to work effectively? Everything I've tried thus far has essentially turned into another for loop in one way or another, which still fires up the linter.
I feel like I'm missing something blatantly apparent here. Any thoughts or ideas to how I can properly apply this?
As a side note - all markers are in the KO vm viewModel.gMarkers(). Greatly appreciate any help, thanks!
Specifically the linter is complaining about the anonymous function google.maps.event.addListener(marker, 'click', function() {}; within the for loop. You could try putting it into its own function and calling it within the loop with the marker passed in.
var m, position, title, marker;
for (i = 0; i < markerData.length; i++) {
// Grab marker data so we only have to call it once
m = markerData[i];
// Define everything
position = new google.maps.LatLng(m.location.lat, m.location.lng);
title = m.title;
// etc etc
// Push all this info to the google maps marker
marker = new google.maps.Marker({
map: map,
position: position,
title: title
// etc with rest
});
doThis(marker);
}
function doThis(marker) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(this.title + '<br>' + this.address + '<br><a
target="_blank" href="' + this.directions + '">Get Directions</a>');
infoWindow.open(map, this); // Not sure where map is coming from
map.setCenter(this);
});
}
Related
so i create markers when a new document get inserted on the FSCollection like this.
i have this find variable.
cordenadasClientes = Clientes.find({}, {fields:{'metadata.latCliente': 1,'metadata.longCliente':
follow by this eachFunction.
var count = 0,
markers = [],
marker;
cordenadasClientes.forEach(function(){
var latitudCliente = cordenadasClientes[count].metadata.latCliente;
var longitudCliente = cordenadasClientes[count].metadata.longCliente;
var nombreCliente = cordenadasClientes[count].metadata.nombreCliente;
marker = new google.maps.Marker({
position: new google.maps.LatLng(latitudCliente ,longitudCliente),
map: map,
title: nombreCliente,
icon :'http://maps.google.com/mapfiles/marker_yellow.png',
})
count++;
markers.push(marker);
})
And its work pretty find, every time i create some document on Clientes Collection, a marker its inserted, so also have this markers array, so every time a new marker its created markers.push(marker); its execute, and thats woork nice to, but now im trying to do this
google.maps.event.addListener(markers, 'click', function() {
map.setZoom(8);
});
but dont work, so im trying to see how my markers array looks like so make this other function;
function arrayMarkers(element,index,array){
console.log(markers);
}
and calling that arrayMarkers function like this;
[markers].forEach(arrayMarkers);
and getting this Console.log;
im the index : 0 and the object [object Object],[object Object]
So i want to create markers sotring on a array and after using that markers on a eventListener, what im doing wrong?, seems to like event listener just work on 1 marker
example
i have 2 markers, so when i click on 1 marker its zoom perfectly, but when i click on the second marker its soom to the first marker
this is how my markers array looks;
[On, On]>
0: on
1: on
like if im nesting array on an array
and if i use
function arrayMarkers(element,index,array){
console.log(array);
}
i got this
[Array[2]]
>
0: Array[2]
>
0: On
1: On
Done By Creating this function
//Added nombreCliente as parameter
function myInfoWindow(marker2,map,nombreCliente,telefonoCliente,ubicacionCliente,facebookCliente){
var infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker2, 'click', function() {
for(var i=0;i<cordenadasClientes.length;i++){
infoWindow.setContent( "Informacion Cliente : <br/>" + "Dale Pa: " + nombreCliente + "<br/> Telefononos: " + telefonoCliente + "<br/> Ubicado en: " + ubicacionCliente + "<br/> No olvides Pasarte Pa' su Facebook: ' " + '<a href="#' + facebookCliente + '">' );
infoWindow.open(map, marker2);
}});
}
And calling it just before markers.push
myInfoWindow(marker2,map,nombreCliente,telefonoCliente,ubicacionCliente,facebookCliente);
I've seen other questions related to this and none of the solutions I saw seemed to help. Maybe I'm just overlooking something.
Any help would be appreciated.
I have a map that I'm loading upwards of 1000 markers. When a user performs a mouseover on the marker, I need the infowindow to display for that marker where the marker is.
The issue I'm having is that the same infowindow appears over the same marker no matter which marker I mouseover.
I provided a screenshot below that shows the map with the markers and an infowindow. So, no matter which marker I mouseover, that same infowindow is shown.
This is the code (gm is an instantiated google.maps object):
for (var i = 0; i < opts.LocationsData.length; i ++) {
var datum = opts.LocationsData[i];
var icon = new gm.MarkerImage(datum.map_pin_loc + datum.map_marker + '.svg',null, null, null, new google.maps.Size(31,51));
var loc = new gm.LatLng(datum.latitude, datum.longitude);
var zi = 500;
if(i>9)
{
datum.map_pin_icon = datum.map_pin_loc + 'dot1.svg';
icon = new gm.MarkerImage(datum.map_pin_icon,null, null, null, new google.maps.Size(8,8));
zi=450;
}
var marker = new gm.Marker({
position: loc,
/** title: datum.title != '' ? datum.title : datum.description, **/
icon: icon,
zIndex: zi,
map: map
});
marker.type = 'point';
marker.post_id = datum.pin_id;
marker.scrollAndAnimate = true;
/** (these are used elsewhere in my code for marker management and other purposes) **/
markers.push(marker);
markersLatLngObjs.push(loc);
var infowindow = new gm.InfoWindow({
content: '<strong>' + (datum.title != '' ? datum.title : datum.description) + '</strong>'
});
gm.event.addListener(marker, 'mouseover', function() {
infowindow.open(map,marker);
});
}
The pb is that the mouseover event handler is a closure referencing variables which are unique in the context of the calling function. Better move this part outside the loop to see clearer.
For example you can define a function such as :
function showInfo() {
// called in the context of a marker
var datum = opts.LocationsData[this.placeIndex];
var infowindow = new gm.InfoWindow({
content: '<strong>' + (datum.title != '' ? datum.title : datum.description) + '</strong>'
});
infowindow.open(map, this);
}
just before your loop, then tag the markers with a property placeIndex (for example) in your loop :
marker.placeIndex = i;
and finally bind the handler with :
gm.event.addListener(marker, 'mouseover', showInfo);
Edit: oops, my bad, forgot about the other references, same pb. You can probably replace the marker by 'this' within the handler. I updated the code.
I'm trying to refactor a google.maps.event.addListener call's anonymous function. Here is what I originally have, which works perfectly fine. Note: The initialize function is run through a loop in some other view, which creates these Truck views. Remember, this code works perfectly and manages to loop through all my markers and set the event listener accordingly.
FoodTruckFinder.Views.TruckView = Backbone.View.extend({
initialize: function(options) {
var marker = new google.maps.Marker({
map: options['map'],
animation: google.maps.Animation.DROP,
optimized: false, //stops marker from flashing
position: options['foodPos']//LatLng
});
var infoWindow = options['infoWindow'];
var self = this;
google.maps.event.addListener(marker, 'mouseover', function() {
// bounce once
marker.setAnimation(google.maps.Animation.BOUNCE);
marker.setAnimation(null);
var content = '<div><strong>'+this.model.get('applicant')+
'</strong><p>'+this.model.get('address')+
'</p><p>'+this.model.get('fooditems')+'</p></div>';
infoWindow.setContent(content);
infoWindow.open(this.map, marker);
});
}
})
This is the refactored code, which doesn't seem to work. My goal was to place the anonymous function into some other chunk of code because that would make it more readable.
FoodTruckFinder.Views.TruckView = Backbone.View.extend({
initialize: function(options) {
this.marker = new google.maps.Marker({
map: options['map'],
animation: google.maps.Animation.DROP,
optimized: false, //stops marker from flashing
position: options['foodPos']//LatLng
});
this.infoWindow = options['infoWindow'];
var populateMarkers = this.populateMarkers.bind(this);
google.maps.event.addListener(marker, 'mouseover', populateMarkers);
},
populateMarkers: function() {
this.marker.setAnimation(google.maps.Animation.BOUNCE);
this.marker.setAnimation(null);
var content = '<div><strong>'+this.model.get('applicant')+
'</strong><p>'+this.model.get('address')+
'</p><p>'+this.model.get('fooditems')+'</p></div>';
this.infoWindow.setContent(content);
this.infoWindow.open(this.map, marker);
}
})
This doesn't work. What happens is only one marker ends up showing up on the map (even though I should have many) and the callback doesn't do what it is supposed to with the infoWindow. In short, it doesn't work.
I was wondering if someone more experienced could see a big flaw in why this doesn't work.
I am not sure if that is your problem, but you are not using the scope correctly.
You are assigning var self = this but never use it in your anon function.
var content = '<div><strong>' + self.model.get('applicant') +
'</strong><p>' + self.model.get('address') +
'</p><p>' + self.model.get('fooditems')+'</p></div>';
Also, consider using a template engine to prevent XSS, and to gain more maintainability:
var tempalte = _.template([
'<div>',
'<strong><%- applicant %></strong>',
'<p><%- address %></p>',
'<strong><%- fooditems %></strong>',
'</div>'
].join(''));
var content = template(self.model.toJSON());
I am currently creating a bit of a Google Maps application using Javascript API v3. It's a map of results from a wordpress database, which dynamically populates the map, creating markers on the map, and on a sidebar the list of wordpress articles.
What I'm trying to do is the following :
when clicking on the link of the wordpress article on the sidebar, instead of going immediately on the article, it have to open the corresponding infowindow on the map. I tried to do it with JQuery, binding a click event on the link to open the infowindow, but unfortunately, it keeps opening the last infowindow created.
I do understand the issue here : JQuery evaluates the 'marker' variable only when the event is fired, thus using the last known value of the variable.
What I want to do is actually evaluates the 'marker' variable WHILE IN THE LOOP. And there I'm stuck. If anyone can help me on this one, I'll be really grateful.
Thanks for the time you'll take to answer me.
Here's a link to the app : http://88.191.128.36/buddypress/carte/
and here the function itself :
function setMarkers(map, markers) {
for (var i = 0; i < markers.length; i++) {
var sites = markers[i];
var siteLatLng = new google.maps.LatLng(sites[1], sites[2]);
if( sites[4] == '10'){
var MarkerImage = new google.maps.MarkerImage('http://dediope.inovawork.net/buddypress/wp-content/themes/TheSource/images/marker-hotel.png');
} else if (sites[4] == '9') {
var MarkerImage = new google.maps.MarkerImage('http://dediope.inovawork.net/buddypress/wp-content/themes/TheSource/images/marker-golf.png');
}
var marker = new google.maps.Marker({
position: siteLatLng,
map: map,
icon: MarkerImage,
title: sites[0],
html: '<div><b>' + sites[0] + '</b> <br /> Voir la fiche de ce lieu </div>'
});
marker_array[i] = marker ;
// THIS IS WHERE I NEED HELP :)
$j('#results_entry li .title:contains("' + sites[0] + '")').bind('click', function(){ infowindow.setContent( marker.html ); infowindow.open( map, marker ); }) ;
var contentString = '<div><b>' + sites[0] + '</b> <br /> Voir la fiche de ce lieu </div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
google.maps.event.addListener(marker, "click", function () {
infowindow.setContent(this.html);
infowindow.open(map, this);
});
}
}
PS : Sorry if I didn't explain very well, I'm french so my english isn't perfect :)
I finally found the solution thanks to this post :
Google Maps v3 opens the last infoWindow when a marker is clicked
The way to make it is to actually pass the object 'marker' and 'infowindow' to an external function and THEN bind the event. That way it binds the right marker and infowindow to the link.
Here the bit of code to show you how I did it, in case other people have the same issue as me:
// I REPLACED THAT
$j('#results_entry li .title:contains("' + sites[0] + '")').bind('click', function(){ infowindow.setContent( marker.html ); infowindow.open( map, marker ); }) ;
// BY THAT
BindLink(marker, sites[0], infowindow);
And i created a BindLink function OUTSIDE the function setmarkers() I had :
function BindLink( bmarker, titre, binfowindow ){
$j('#results_entry li .title:contains("' + titre + '")').bind('click', function(){
binfowindow.setContent( bmarker.html );
binfowindow.open( map, bmarker );
}) ;
}
Now it works perfectly fine ( except that I can't figure out to close the previously opened infowindow but that's another story ! )
So i have several markers appearing from an array, but i'm having a lot of difficulty setting the content of the InfoWindows that appear
I put the titles in which works great, but when I try to set the content, it doesn't set the content, but still shows the title.
What am I doing wrong?
for (index = 0; index < data.length; ++index) {
locationName = data[index].LocationName;
locationID = data[index].LocationID;
locationX = data[index].XCord;
locationY = data[index].YCord;
var infoContent = '<div><h3>' + data[index].LocationName + '</h3></div><div>' + data[index].LocationID + '</div>';
var mapLocation = new google.maps.LatLng(locationX,locationY);
var marker = new google.maps.Marker({ // Set the marker
position: mapLocation, // Position marker to coordinates
icon: image, //use our image as the marker
map: map, // assign the marker to our map variable
title: data[index].LocationName,
content: infoContent
//draggable:true //Have a guess what this does
});
// Allow each marker to have an info window
google.maps.event.addListener(marker, 'click', (function (marker, index) {
return function () {
infoWindow.setContent(infoContent);
infoWindow.setContent(this.title);
infoWindow.open(map, this);
}
})(marker, index));
var infoWindow = new google.maps.InfoWindow({
content: infoContent
}), marker, index;
}
You are calling setContent twice:
infoWindow.setContent(infoContent);
infoWindow.setContent(this.title);
I guess the last one should be removed.
Edit:
To get the correct infoWindow content, try moving the creation of the eventListener to a function:
// Allow each marker to have an info window
updateInfoWindowOnMarkerClick(marker, infoContent);
//Somewhere after the loop
function updateInfoWindowOnMarkerClick(marker, infoContent){
google.maps.event.addListener(marker, "click", function () {
infoWindow.setContent(infoContent);
infoWindow.open(map, this);
});
}
Have a look at JavaScript closure inside loops – simple practical example for more information about function scope.