I am trying to get the infowindows to populate with the Zomato API data, but I keep getting the last item in the object. I have tried a for loop with a closure and the for loop with "let" instead of "var", but this is not helping. Any suggestions that could push me forward would be greatly appreciated.
var map;
var markers = [];
var cuisines, name, establishment, locality, menu, photos, rating, infoContent;
var locations = [
{name: 'The Pub at Ghirardelli Square', latlng: {lat: 37.8063722222, lng: -122.4228888889}},
{name: 'The Irish Bank', latlng: {lat: 37.7902750000, lng: -122.4048472222}},
{name: 'Rogue San Francisco Public House', latlng: {lat: 37.8001440000, lng: -122.4104550000}},
{name: 'Chieftain Irish Restaurant & Pub', latlng: {lat: 37.7814900000, lng: -122.4051510000}},
{name: 'Kennedy\'s Irish Pub and Curry House', latlng: {lat: 37.8042510000, lng: -122.4156040000}},
{name: 'Murphy\'s Pub', latlng: {lat: 37.7901916667, lng: -122.4038472222}}
];
//create instance of a map from the Google Maps API
//Grab the reference to the "map" id to display the map
//Set the map options object properties
function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: 37.7884162,
lng: -122.4127457
},
zoom: 14
});
var infowindow = new google.maps.InfoWindow();
var marker;
for(var i = 0; i < locations.length; i++) {
(function() {
// get the position fronm the locations array
var position = locations[i].latlng;
var title = locations[i].name;
//create a marker per location and put into markers array
var marker = new google.maps.Marker({
map: map,
position: position,
title: title,
animation: google.maps.Animation.DROP
//id: i
});
//push the marker to our array of markers
markers.push(marker);
//extend the boundaries of the map for each marker
marker.addListener('click', function() {
populateInfoWindow(this, infowindow);
infowindow.setContent(infoContent);
});
})(i);//end of closure
}//end of for loop
}; //end initMap()
function populateInfoWindow(marker, infowindow) {
//check to make sure the infowindow is not already opened in this marker
if (infowindow.marker != marker) {
infowindow.marker = marker;
infowindow.setContent('<div>' + marker.title + '</div>' + marker.infoContent);
infowindow.open(map, marker);
//Make sure the marker property is cleared if the infowindow is closed
infowindow.addListener('closeclick', function() {
infowindow.setMarker = null;
});
}
}// end of populateInfoWindow
$.ajax({
method: "GET",
crossDomain: true,
url: "https://developers.zomato.com/api/v2.1/search?count=6&lat=37.79161&lon=-122.42143&establishment_type=6",
dataType: "json",
async: true,
headers: {
"user-key": "0a661374a6b58eb2fa84142d27fe81ca"
},
success: function(data) {
var pubs = [];
pubs = data.restaurants;
for(var j = 0; j < pubs.length; j++) {
(function(val) {
infoContent = "<div class='name'>" + "Pub: " + pubs[j].restaurant.name + "</div>" + "\n" + "<div class='cuisines'>" + pubs[j].restaurant.cuisines + "</div>";
})(j);
}
},
error: function() {
infoContent = "<div>Sorry, data is not coming through. Refresh and try again.</div>";
}
});//end of $.ajax call
<!doctype html>
<html class="no-js" lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Map</title>
<link rel="stylesheet" href="css/foundation.css">
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<div class="grid-container">
<div class="grid-x grid-padding-x">
<div class="large-12 cell">
</div>
</div>
<div class="grid-x grid-padding-x">
<div class="large-12 cell">
<div class="callout">
<div id="map" class="flex-video">
<iframe width="420" height="315" src="" frameborder="0" allowfullscreen></iframe>
</div>
</div>
</div>
</div>
</div>
<script src="js/vendor/jquery.js"></script>
<script src="js/vendor/what-input.js"></script>
<script src="js/vendor/foundation.js"></script>
<script src="js/map.js"></script>
<script async deter src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBS6v85DRLDI_VKGgNdgQ6EVzDxJfZZOF8&ve&3&libraries=places,drawing&callback=initMap">
</script>
</body>
</html>
The indicated line below is wrong, remove it and your code works:
marker.addListener('click', function() {
populateInfoWindow(this, infowindow);
// infowindow.setContent(infoContent); <<<<<<<<<<<< REMOVE
});
proof of concept fiddle
code snippet:
var map;
var markers = [];
var cuisines, name, establishment, locality, menu, photos, rating, infoContent;
var locations = [
{name: 'The Pub at Ghirardelli Square', latlng: {lat: 37.8063722222, lng: -122.4228888889}},
{name: 'The Irish Bank', latlng: {lat: 37.7902750000, lng: -122.4048472222}},
{name: 'Rogue San Francisco Public House', latlng: {lat: 37.8001440000, lng: -122.4104550000}},
{name: 'Chieftain Irish Restaurant & Pub', latlng: {lat: 37.7814900000, lng: -122.4051510000}},
{name: 'Kennedy\'s Irish Pub and Curry House', latlng: {lat: 37.8042510000, lng: -122.4156040000}},
{name: 'Murphy\'s Pub', latlng: {lat: 37.7901916667, lng: -122.4038472222}}
];
//create instance of a map from the Google Maps API
//Grab the reference to the "map" id to display the map
//Set the map options object properties
function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: 37.7884162,
lng: -122.4127457
},
zoom: 14
});
var infowindow = new google.maps.InfoWindow();
var marker;
for (var i = 0; i < locations.length; i++) {
(function() {
// get the position fronm the locations array
var position = locations[i].latlng;
var title = locations[i].name;
//create a marker per location and put into markers array
var marker = new google.maps.Marker({
map: map,
position: position,
title: title,
animation: google.maps.Animation.DROP,
infoContent: "there is no infoContent!"
//id: i
});
//push the marker to our array of markers
markers.push(marker);
//extend the boundaries of the map for each marker
marker.addListener('click', function() {
populateInfoWindow(this, infowindow);
});
})(i); //end of closure
} //end of for loop
}; //end initMap()
function populateInfoWindow(marker, infowindow) {
//check to make sure the infowindow is not already opened in this marker
if (infowindow.marker != marker) {
infowindow.marker = marker;
infowindow.setContent('<div>' + marker.title + '</div>' + marker.infoContent);
infowindow.open(map, marker);
//Make sure the marker property is cleared if the infowindow is closed
infowindow.addListener('closeclick', function() {
infowindow.setMarker = null;
});
}
} // end of populateInfoWindow
$.ajax({
method: "GET",
crossDomain: true,
url: "https://developers.zomato.com/api/v2.1/search?count=6&lat=37.79161&lon=-122.42143&establishment_type=6",
dataType: "json",
async: true,
headers: {
"user-key": "0a661374a6b58eb2fa84142d27fe81ca"
},
success: function(data) {
var pubs = [];
pubs = data.restaurants;
for (var j = 0; j < pubs.length; j++) {
(function(val) {
infoContent = "<div class='name'>" + "Pub: " + pubs[j].restaurant.name + "</div>" + "\n" + "<div class='cuisines'>" + pubs[j].restaurant.cuisines + "</div>";
})(j);
}
},
error: function() {
infoContent = "<div>Sorry, data is not coming through. Refresh and try again.</div>";
}
}); //end of $.ajax call
google.maps.event.addDomListener(window, "load", initMap);
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map"></div>
The discovery to this answer is a good exercise in appreciating scope. I also discovered that my data object could ride the same iterator from the for loop for the markers.
//create instance of a map from the Google Maps API
//Grab the reference to the "map" id to display the map
//Set the map options object properties
function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: 37.7884162,
lng: -122.4127457
},
zoom: 14
});
var marker;
//$.ajax call
$.ajax({
method: "GET",
crossDomain: true,
url: "https://developers.zomato.com/api/v2.1/search?count=6&lat=37.79161&lon=-122.42143&establishment_type=6",
dataType: "json",
async: true,
headers: {
"user-key": "0a661374a6b58eb2fa84142d27fe81ca"
},
success: function(data) {
passZomatoData(data);
},
error: function() {
infoContent = "<div>Sorry, data is not coming through. Refresh and try again.</div>";
}
});//end of $.ajax call
//function passZomatoData()
function passZomatoData(data) {
var infowindow = new google.maps.InfoWindow();
pubs = data.restaurants;
console.log(data);
for(var i = 0; i < locations.length; i++) {
(function() {
// get the position fronm the locations array
var position = locations[i].latlng;
var title = locations[i].name;
var cuisine = pubs[i].restaurant.cuisines;
var address = pubs[i].restaurant.location.address;
console.log(address);
//create a marker per location and put into markers array
var marker = new google.maps.Marker({
map: map,
position: position,
title: title,
cuisine: cuisine,
address: address,
animation: google.maps.Animation.DROP
});
//push the marker to our array of markers
markers.push(marker);
//extend the boundaries of the map for each marker
marker.addListener('click', function() {
populateInfoWindow(this, infowindow);
infowindow.setContent('<div><b>Pub name:<b> ' + marker.title + '</div><div><b>Address:<b> ' + marker.address + '</div><div><b>Cuisine:<b> ' + marker.cuisine + '</div>');
});
})(i);//end of closure
}//end of for loop
}
}; //end initMap()
function populateInfoWindow(marker, infowindow) {
//check to make sure the infowindow is not already opened in this marker
if (infowindow.marker != marker) {
infowindow.marker = marker;
//infowindow.setContent('<div>' + marker.title + '</div>' + marker.infoContent);
infowindow.open(map, marker);
//Make sure the marker property is cleared if the infowindow is closed
infowindow.addListener('closeclick', function() {
infowindow.setMarker = null;
});
}
}// end of populateInfoWindow
Related
I have a google map which loads results on page load which is fine but I have an ajax search form which updates the results by ajax in a separate div but it doesn't update the map. I am trying to figure out how to update the map when the ajax call is completed but I am stuck. Any help would be greatly appreciated!
Here is the code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<script src="https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js"></script>
<script>
$(document).ready(function() {
var markersInfo = $('.ia-card').map(function() {
var info = {
id: $(this).data('map-id'),
address: $(this).data('map-address'),
title: $(this).data('map-title'),
price: $(this).data('map-price'),
latitude: $(this).data('map-latitude'),
longitude: $(this).data('map-longitude'),
html: "<img src=" + $(this).data('map-image') + ">",
link: $(this).data("map-link"),
contentHtml: "<div class='image'>" + "<img src=" + $(this).data('map-image') + ">" + "</div>" + '<b>' + $(this).data('map-title') + '</b><br>' + "<div class='changeprice'><div style='display: none;' class='currency-selector'></div>" + $(this).data('map-price') + "</div>" + "<br><a href='" + $(this).data("map-link") + "'>More>></a>"
};
return info;
}).get();
var distinctMarkerInfo = [];
markersInfo.forEach(function(item) {
if (!distinctMarkerInfo.some(function(distinct) {
return distinct.id == item.id;
})) distinctMarkerInfo.push(item);
});
initGoogleMap(distinctMarkerInfo);
// GMAP ON SEARCH RESULTS PAGE
function initGoogleMap(markersInfo) {
var mapOptions = {
// zoom: 2,
// center: new google.maps.LatLng(53.334430, -7.736673)
},
bounds = new google.maps.LatLngBounds(),
mapElement = document.getElementById('stm_map_results'),
map = new google.maps.Map(mapElement, mapOptions);
markerList = []; // create an array to hold the markers
var geocoder = new google.maps.Geocoder();
var iconBase = '../assets/images/';
$.each(markersInfo, function(key, val) {
var marker = new google.maps.Marker({
//map: map,
position: {lat: parseFloat(val.latitude), lng: parseFloat(val.longitude)},
title: val.title,
icon: iconBase + 'single.png',
info: new google.maps.InfoWindow({
content: val.contentHtml
})
});
markerList.push(marker); // add the marker to the list
google.maps.event.addListener(marker, 'click', function() {
marker.info.open(map, marker);
});
loc = new google.maps.LatLng(val.latitude, val.longitude);
bounds.extend(loc);
});
map.fitBounds(bounds);
map.panToBounds(bounds);
var markerCluster = new MarkerClusterer(map, markerList, {
imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'
});
};
});
</script>
<div id="stm_map_results" style="width:100%; height:600px;"></div>
Since you are displaying markers via MarkerClusterer i would propose the following solution to update the map.
once the data is retrieved, clear the existing markets from map using
MarkerCluster.clearMarkers function
initialize a MarkerCluster with a new data
The below example demonstrates how to "refresh" markers on the map:
function placeMarkers(data){
var markers = data.map(function (item, i) {
return new google.maps.Marker({
position: { lat: item.lat, lng: item.lng }
});
});
//1.clear existing markers
if (markerCluster)
markerCluster.clearMarkers();
//2.init marker cluster
markerCluster = new MarkerClusterer(map, markers,
{ imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m' });
}
Demo
I am trying to generate Google Map markers with Wikipedia AJAX data in the infowindow using a for loop. I think there is a timing issue occurring, but after several weeks I cannot figure out how to resolve it. When I hardcode an identifier into the for loop to replace i (2 for example), the code works just fine...but when I use i, I get errors saying 'cannot read property [whatever] of undefined. I've played around with setTimeout and callbacks, but I can't seem to figure it out.
Here is my code:
var map;
var marker;
var infowindow;
var wikiURL;
var i;
var text;
var venueInfo;
var markers = [];
var markerNames = [];
var wikiURLs = [];
var venueArray = [];
//The Model - Pro/Collegiate Stadiums in PGH, Pa.
var venues = [
{
name: "PNC Park",
lat: 40.446855,
lng: -80.0056666
},
{
name: "Heinz Field",
lat: 40.4466765,
lng: -80.01576
},
{
name: "PPG Paints Arena",
lat: 40.439593,
lng: -79.989338
},
{
name: "Highmark Stadium",
lat: 40.4362358,
lng: -80.00959209999999
},
{
name: "Peterson Events Center",
lat: 40.443828,
lng: -79.962283
}
];
//marker creator
function createMarker(){
for (i=0; i <= venues.length; i++){
wikiURL = 'http://en.wikipedia.org/w/api.php?action=opensearch&search=' +venues[i].name+ '&format=json&callback=wikiCallback';
wikiURLs.push(wikiURL);
$.ajax ({
url: wikiURL,
dataType: "jsonp",
success: function(data){
text = data[2];
venueInfo = text[0];
console.log(venueInfo);
marker = new google.maps.Marker({
position: {lat: venues[i].lat, lng: venues[i].lng},
map: map,
draggable: false,
content: '<h2>'+venues[i].name+'</h2><p>'+venueInfo+'</p>'
});
markerNames.push(venues[i].name);
markers.push(marker);
infowindow = new google.maps.InfoWindow({
content: this.content
});
marker.addListener('click', function(){
infowindow.setContent(this.content);
infowindow.open(map, this);
});
}
});
}
}
//Map Initializer
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.446855, lng: -80.0056666},
zoom: 14,
mapTypeId: 'satellite'
});
//viewmodel();
createMarker();
}
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' href='css/bootstrap-theme.min.css'>
<link rel='stylesheet' href='css/main.css'>
</head>
<body>
<nav>
</nav>
<container>
<div id='map'>
</div>
</container>
<script type='text/javascript' src='js/jquery-3.2.1.min.js'></script>
<script type='text/javascript' src='js/knockout-3.4.2.js'></script>
<script type='text/javascript' async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyA_WObUiYD7YpoYufR84re1LZHAJeAGXkY&v=3&callback=initMap">
</script>
<script type='text/javascript' src='js/app.js'></script>
</body>
As #jeff carey said, fix your loop and move your ajax code to separate function
function doAjax(i){
wikiURL = 'http://en.wikipedia.org/w/api.php?action=opensearch&search=' +venues[i].name+ '&format=json&callback=wikiCallback';
wikiURLs.push(wikiURL);
$.ajax ({
url: wikiURL,
dataType: "jsonp",
success: function(data){
text = data[2];
venueInfo = text[0];
marker = new google.maps.Marker({
position: {lat: venues[i].lat, lng: venues[i].lng},
map: map,
draggable: false,
content: '<h2>'+venues[i].name+'</h2><p>'+venueInfo+'</p>'
});
markerNames.push(venues[i].name);
markers.push(marker);
infowindow = new google.maps.InfoWindow({
content: this.content
});
marker.addListener('click', function(){
infowindow.setContent(this.content);
infowindow.open(map, this);
});
}
});
}
function createMarker(){
for (i=0; i < venues.length; i++){
doAjax(i);
}
}
You have a common problem caused by calling an asynchronous function inside a loop. One way to fix the issue (i is past the end of the input array when the callback functions run) is with a Immediately-Invoked Function Expression (IIFE) which holds closure on the i variable, so when the callback function is executed, it has the "correct" value:
success: (function(i) {
return function(data) {
text = data[2];
venueInfo = text[0];
console.log(venueInfo);
marker = new google.maps.Marker({
position: {
lat: venues[i].lat,
lng: venues[i].lng
},
map: map,
draggable: false,
content: '<h2>' + venues[i].name + '</h2><p>' + venueInfo + '</p>'
});
markerNames.push(venues[i].name);
markers.push(marker);
infowindow = new google.maps.InfoWindow({
content: this.content
});
marker.addListener('click', function() {
infowindow.setContent(this.content);
infowindow.open(map, this);
});
}
}(i))
proof of concept fiddle
(working) code snippet:
var map;
var marker;
var infowindow;
var wikiURL;
var i;
var text;
var venueInfo;
var markers = [];
var markerNames = [];
var wikiURLs = [];
var venueArray = [];
//The Model - Pro/Collegiate Stadiums in PGH, Pa.
var venues = [{
name: "PNC Park",
lat: 40.446855,
lng: -80.0056666
},
{
name: "Heinz Field",
lat: 40.4466765,
lng: -80.01576
},
{
name: "PPG Paints Arena",
lat: 40.439593,
lng: -79.989338
},
{
name: "Highmark Stadium",
lat: 40.4362358,
lng: -80.00959209999999
},
{
name: "Peterson Events Center",
lat: 40.443828,
lng: -79.962283
}
];
//marker creator
function createMarker() {
for (i = 0; i < venues.length; i++) {
wikiURL = 'https://en.wikipedia.org/w/api.php?action=opensearch&search=' + venues[i].name + '&format=json&callback=wikiCallback';
wikiURLs.push(wikiURL);
$.ajax({
url: wikiURL,
dataType: "jsonp",
success: (function(i) {
return function(data) {
text = data[2];
venueInfo = text[0];
console.log(venueInfo);
marker = new google.maps.Marker({
position: {
lat: venues[i].lat,
lng: venues[i].lng
},
map: map,
draggable: false,
content: '<h2>' + venues[i].name + '</h2><p>' + venueInfo + '</p>'
});
markerNames.push(venues[i].name);
markers.push(marker);
infowindow = new google.maps.InfoWindow({
content: this.content
});
marker.addListener('click', function() {
infowindow.setContent(this.content);
infowindow.open(map, this);
});
}
}(i))
});
}
}
//Map Initializer
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: 40.446855,
lng: -80.0056666
},
zoom: 14,
mapTypeId: 'satellite'
});
//viewmodel();
createMarker();
}
html,
body,
#map {
height: 100%;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<container>
<div id='map'>
</div>
</container>
<script type='text/javascript' async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
I have the following Ajax request on a select drop down change which simply gets the records from the controller, Loop through each one and get the latitude | longitude and pushes it to an array.
Then in the same ajax success i pass that lat and lng array to google map.
But the map doesn't shows up..
$(document).ready(function() {
$('.selectCity').change(function() {
var city = $(this).val();
$.ajax({
type: 'GET',
url: '/riders/location/track',
data: {
'city': city
},
success: function(data) {
var lat = [];
var lng = [];
//Get Locations and push it to lat and lng
$.each(data, function(index, value) {
$.each(value, function(index1, value1) {
console.log(value1.rider_location.lat);
lat.push(value1.rider_location.lat);
lng.push(value1.rider_location.lng);
});
});
//Google Map
google.maps.event.addDomListener(window, 'load', init);
function init() {
var locations = [
['Rider', lat, lng]
];
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: new google.maps.LatLng(lat, lng),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
var marker, i;
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
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(locations[i][0]);
infowindow.open(map, marker);
}
})(marker, i));
}
}
}
});
});
});
Plus please suggest best practice also.
Of course I can make my comment above as an answer.
You can also listen to the "google-maps-ready"-event in the script-url by using the callback-parameter (HTML):
<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?libraries=geometry,places&callback=initialize">
</script>
JS:
// In this way you have to define a function called initialize which should be defined globally otherwise it can not be found by the google-library.
// unfortunately this map-variable is defined globally here but you can also wrap the whole code below by using an IIFE.
var map;
function initialize() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
// you might set a center here or wait untill you have got some markers fetched via ajax, you can then use the first/last or some other marker respecetive it's position(lat,long) to set as "starting point"
//center: {lat: LAT, lng: LONG }
mapTypeId: google.maps.MapTypeId.ROADMAP
});
}
// Although I have no access to your website to test this code below, it might be done in this way:
$(document).ready(function () {
$('.selectCity').change(function () {
var city = $(this).val();
$.ajax({
type: 'GET',
url: '/riders/location/track',
data: {
'city': city
},
success: function (data) {
var positions = [];
//Get Locations and push it to lat and lng
// you can also use just one array to insert all locations and "labels" into
$.each(data, function (index, value) {
$.each(value, function (index1, value1) {
console.log(value1.rider_location.lat);
positions.push({
lat: value1.rider_location.lat,
lng: value1.rider_location.lng,
content: 'Rider' // do you get some text with each location?
});
});
});
// set "starting point" afterwards
map.setCenter({
lat: positions[0].lat,
lng: positions[0].lng
});
var infowindow = new google.maps.InfoWindow();
var marker,
i;
for (i = 0; i < positions.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(positions[i].lat, positions[i].lng),
map: map
});
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infowindow.setContent(positions[i].content);
infowindow.open(map, marker);
}
}) (marker, i));
}
}
});
});
});
Hope it helps!
So, what I need is very simple, I need to put markers in a map, I get the data from a JSON I built using PHP. I looked up all other questions(really) about Google Maps markers not showing up, and none of them worked for me. I can't find the flaw in my code.
The JSON is like this (but 58 items long), 'id' is unimportant:
[
{
"id": "2",
"lat": "-49.217290",
"lon": "-16.416160",
"tit": "Heinz",
"desc": "18 Machines"
},
{
"id": "3",
"lat": "-49.235455",
"lon": "-16.676926",
"tit": "Warehouse",
"desc": "10 Machines"
}
]
I'm new here, sorry if I do something wrong. My code is bellow:
<div id="map" class="height-400"></div>
<script>
var map;
var myLatLon = {lat: -16.398293, lng: -48.965098};
var markers = [];
$.ajax({
dataType:'json',
url: "contents/map_data.php",
success: function(data){
markers = data;
}
});
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: myLatLon,
zoom: 4,
//disableDefaultUI: true,
});
var i= 0;
$.each(markers, function(i, item) {
if(typeof item == 'object') {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(parseFloat(item.lat),parseFloat(item.lon)),
map: map,
title: item.titulo,
label: item.desc
});
marker.setMap(map);
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(item.desc);
infowindow.open(map, marker);
}
})(marker, i));
i=i+1;
}
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=MY_SECRET_KEY&callback=initMap" async defer></script>
Markers variable is an empty array, cause the AJAX request has not returned yet. You should either move your code inside success callback or invoke it from success callback.
Try something like:
<div id="map" class="height-400"></div>
<script>
var map;
var myLatLon = {lat: -16.398293, lng: -48.965098};
var markers = [];
$.ajax({
dataType:'json',
url: "contents/map_data.php",
success: function(data){
markers = data;
initMap();
}
});
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: myLatLon,
zoom: 4,
//disableDefaultUI: true,
});
var i= 0;
$.each(markers, function(i, item) {
if(typeof item == 'object') {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(parseFloat(item.lat),parseFloat(item.lon)),
map: map,
title: item.titulo,
label: item.desc
});
marker.setMap(map);
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(item.desc);
infowindow.open(map, marker);
}
})(marker, i));
i=i+1;
}
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=MY_SECRET_KEY&callback=initMap" async defer></script>
I am plotting addresses and having an issue with the infowindow showing the right content everytime. Sometimes it shows the right content in the infowindow when clicked and sometimes it shows the wrong information for that map pin.
var map = null;
var markersArray = [];
var markers = [];
var openedInfoWindow ="";
var geocoder = new google.maps.Geocoder();
function initialize() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(64.85599578876611, -147.83363628361917),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("mapInfoManual"),
mapOptions);
google.maps.event.addListener(map, 'zoom_changed', function() {
zoomChangeBoundsListener = google.maps.event.addListener(map, 'bounds_changed', function(event) {
if (this.getZoom() > 20) // Change max/min zoom here
this.setZoom(18);
google.maps.event.removeListener(zoomChangeBoundsListener);
});
});
addMarker();
}
function addMarker() {
var bounds = new google.maps.LatLngBounds();
for(i=0; i<markersArray.length; i++)
{
CodeAddress(markersArray[i]['address']);
var mytitle = (markersArray[i]['title']);
var myaddress = (markersArray[i]['displayaddress']);
var linkurl = (markersArray[i]['linkurl']);
}
setTimeout(function()
{
for(i=0; i<markers.length; i++)
{
var point = new google.maps.LatLng(markers[i]['lat'], markers[i]['lng']);
var marker = new google.maps.Marker({
position: point,
map: map
});
bounds.extend(point);
var infoWindowContent = "<div style='padding:2px;'><div style='margin-bottom:5px;font-weight:700;color:#033551;'>"+ mytitle +"</div><div style='margin-bottom:5px;'>" + myaddress + "</div><div><a href='" + linkurl + "/'>More Details</a></div></div>";
openInfoWindow(marker,infoWindowContent)
}
map.fitBounds(bounds);
},2500);
}
// Address To Marker
function CodeAddress(address)
{
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
markers.push({
'lat':lat,
'lng':lng,
'address':address
});
}
});
}
//Info Window
function openInfoWindow(marker,infoWindowContent)
{
var infowindow = new google.maps.InfoWindow({
content: '<div class="cityMapInfoPop">'+infoWindowContent+'</div>'
});
google.maps.event.addListener(marker, 'click', function() {
if(openedInfoWindow !="")
{
openedInfoWindow.close()
}
infowindow.open(map,marker);
openedInfoWindow = infowindow;
});
}
Variables that I pass in:
<script type="application/javascript">
markersArray.push({
"title":'<?php echo $maptitle;?>',
"address":'<?php echo $markerAddress;?>',
"displayaddress":'<?php echo $displayAddress;?>',
"linkurl":'<?php echo $addressUrl;?>'
});
</script>
Your issue is that geocoding is asynchronous. You loop through calling the geocoder on all your addresses, but the order the results are returned in is not predictable.
use function closure to associate the marker with the infowindow
use function closure to associate the address with the marker
use the results of the geocoder inside its callback function.
Note that if you have more that approximately 10 markers in your array you will run into the quota/rate limit of the geocoder.
proof of concept fiddle
code snippet:
var map = null;
var markersArray = [];
var markers = [];
var openedInfoWindow = "";
var geocoder = new google.maps.Geocoder();
var bounds = new google.maps.LatLngBounds();
markersArray.push({
"title": 'marker 0',
"address": 'New York,NY',
"displayaddress": 'New York, NY',
"linkurl": 'http://google.com'
});
markersArray.push({
"title": 'marker 1',
"address": 'Boston, MA',
"displayaddress": 'Boston, MA',
"linkurl": 'http://yahoo.com'
});
markersArray.push({
"title": 'marker 2',
"address": 'Newark,NJ',
"displayaddress": 'Newark, NJ',
"linkurl": 'http://mapquest.com'
});
google.maps.event.addDomListener(window, "load", initialize);
function initialize() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(64.85599578876611, -147.83363628361917),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("mapInfoManual"),
mapOptions);
google.maps.event.addListener(map, 'zoom_changed', function() {
zoomChangeBoundsListener = google.maps.event.addListener(map, 'bounds_changed', function(event) {
if (this.getZoom() > 20) // Change max/min zoom here
this.setZoom(18);
google.maps.event.removeListener(zoomChangeBoundsListener);
});
});
addMarker();
}
function addMarker() {
var bounds = new google.maps.LatLngBounds();
for (i = 0; i < markersArray.length; i++) {
CodeAddress(markersArray[i]);
}
}
// Address To Marker
function CodeAddress(markerEntry) {
var mytitle = (markerEntry['title']);
var myaddress = (markerEntry['displayaddress']);
var linkurl = (markerEntry['linkurl']);
geocoder.geocode({
'address': markerEntry['address']
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map
});
bounds.extend(marker.getPosition());
var infoWindowContent = "<div style='padding:2px;'><div style='margin-bottom:5px;font-weight:700;color:#033551;'>" + mytitle + "</div><div style='margin-bottom:5px;'>" + myaddress + "</div><div><a href='" + linkurl + "/'>More Details</a></div></div>";
openInfoWindow(marker, infoWindowContent);
markers.push(marker);
map.fitBounds(bounds);
} else {
alert("geocode failed: " + status);
}
});
}
//Info Window
function openInfoWindow(marker, infoWindowContent) {
var infowindow = new google.maps.InfoWindow({
content: '<div class="cityMapInfoPop">' + infoWindowContent + '</div>'
});
google.maps.event.addListener(marker, 'click', function() {
if (openedInfoWindow != "") {
openedInfoWindow.close();
}
infowindow.open(map, marker);
openedInfoWindow = infowindow;
});
}
html,
body,
#mapInfoManual {
height: 500px;
width: 500px;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?ext=.js"></script>
<div id="mapInfoManual" style="border: 2px solid #3872ac;"></div>
Since you didn't provide a working JSFiddle, it was rather difficult to figure out what your problem is. That said, you can look at this JSFiddle that I made for you to review what I'm doing, vs what you're doing.
Why are you using setTimeout() to place your markers? Also, you may have better results if you create an individual infoWindow per marker, instead of using a "global" infoWindow (which is what it looks like you're doing).
If you edit your post to add a working example of your problem, I can help further.
window.places = [{
title: "foo",
address: {
lat: parseFloat("64.85599578876611"),
lng: parseFloat("-147.83363628361917")
},
displayAddress: "101 BLVD",
linkURL: "google.com"
}, {
title: "bar",
address: {
lat: parseFloat("62.85599578876611"),
lng: parseFloat("-147.83363628361917")
},
displayAddress: "202 BLVD",
linkURL: "images.google.com"
}, ]
function initialize() {
"use strict";
var myLatlng = new google.maps.LatLng(window.places[0].address.lat, window.places[0].address.lng),
mapOptions = {
zoom: 4,
center: myLatlng
};
window.map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
$.each(window.places, function(i) {
var infowindow = new google.maps.InfoWindow({
content: "<div style='padding:2px;'><div style='margin-bottom:5px;font-weight:700;color:#033551;'>" + window.places[i].title + "</div><div style='margin-bottom:5px;'>" + window.places[i].displayAddress + "</div><div><a href='" + window.places[i].linkURL + "/'>More Details</a></div></div>"
}),
marker = new google.maps.Marker({
position: new google.maps.LatLng(window.places[i].address.lat, window.places[i].address.lng),
map: window.map,
title: window.places[i].title
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(window.map, marker);
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
<div id="map-canvas"></div>