Javascript closure not working with google maps V3 - javascript

Would somebody please advise me as to what I'm doing wrong with this piece of code?
I am currently using a simple JSON file to provide data for info windows using the Google maps V3 API. I am aware of the concept of closures but cannot seem to understand why the info windows are still displaying the last result on click.
Here is my JSON file:
{ "markers": [
{
"lat": 51.5001524,
"lng": -0.1262362,
"firstName": "nameOne"
},
{
"lat": 55.8656274,
"lng": -4.2572227,
"firstName": "nameTwo"
},
{
"lat": 43.834526782236814,
"lng": -37.265625,
"firstName": "nameThree"
}
] }
Here is my JS:
(function(){
function initialize() {
var latlng = new google.maps.LatLng(51.5001524, -0.1262362)
var myOptions = {
zoom: 3,
center: latlng,
mapTypeId: google.maps.MapTypeId.TERRAIN
}
var map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
function parseJson(){
$.ajax({
url: 'assets/js/markers.json',
dataType: 'json',
success: function(data) {
processMarkers(data)
},
error: function (data) {
console.log('fail')
}
})
}
function processMarkers(data){
var totalMarkers = data.markers.length;
for(i=0;i<totalMarkers;i++){
var latitude = data.markers[i].lat;
var longditude = data.markers[i].lng;
var putMarker = new google.maps.LatLng(latitude, longditude);
var thisMarker = new google.maps.Marker({
position: putMarker,
map: map
});
var firstName = data.markers[i].firstName;
var infoWindow = new google.maps.InfoWindow({
position: putMarker,
content: firstName
});
new google.maps.event.addListener(
thisMarker,
'click',
buildHandler(map, thisMarker));
}
function buildHandler(map, marker){
return function(){
infoWindow.open(map, marker);
};
}
}
parseJson();
}
$(document).ready(function(){
initialize();
});
})();
Any help would be greatly appreciated.
Cheers

infoWindow is some var in the processMarkers scope. That iterates over the same infoWindow over and over for every marker, orphaning it after the last iteration (and leaving it set to the final marker). The orphan cannot die because it's captured in the closure of your click handler. I do not know the google api well enough to predict what's supposed to happen on .open(). But infoWindow doesn't look good at that point...
EDIT: In fact, it seems to me that every infoWindow but the last falls victim to the garbage collector. Or is it referenced somewhere? I cannot make it out.
EDIT: Remember, JS does NOT have {} scopes (like eg C). It only has functional scopes !! In other words, simply pass infoWndow into your buildHandler().

Related

How to use Pagination in Google Maps and Ajax

I have an api where is pagination because of a lot of data. Now I am trying to do Google Maps where I use API to get lat and lng from database. I still get just first page of API Data. What's wrong with my code ? What should I change. Please help. I will be glad to you.
Hi. I have an api where is pagination because of a lot of data. Now I am trying to do Google Maps where I use API to get lat and lng from database. I still get just first page of API Data. What's wrong with my code ? What should I change. Please help. I will be glad to you.
<script>
function initMap(map) {
var start_point = new google.maps.LatLng(27.772321, 1.803125);
// Creating a new map
var map = new google.maps.Map(document.getElementById("companies-map"), {
center: start_point,
zoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
function setMarkerPoints(map) {
var bounds = new google.maps.LatLngBounds();
var mc = [];
var infoWindow = new google.maps.InfoWindow();
url = '/api/companies/map/',
$.ajax({
type: "GET",
url: url,
dataType: "json",
success: function(data, pagination) {
$.each(data.results, function(marker, data) {
var latLng = new google.maps.LatLng(data.point.latitude, data.point.longitude);
bounds.extend(latLng);
// Creating a marker and putting it on the map
var marker = new google.maps.Marker({
position: latLng,
animation: google.maps.Animation.DROP,
map: map,
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent('' + data.name + '<br>' + data.name);
infoWindow.open(map, marker);
});
mc.push(marker);
});
if (pagination.hasNextPage) {
pagination.nextPage();
};
new MarkerClusterer(map, mc, {
imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'
});
},
error: function(data) {
console.log('Please refresh the page and try again');
}
});
//END MARKER DATA
// end loop through json
}
setMarkerPoints(map);
}
google.maps.event.addDomListener(window, 'load', renderGoogleMap);
renderGoogleMap();
</script>
THANK YOU SO MUCH
You need to create a PlaceSearchPagination object in order to access additional pages. The object is created via a callback function.
https://developers.google.com/maps/documentation/javascript/places#place_search_responses
Take a look at the Accessing Additional Results section, specifically under the comments "// Create the places service" and "// Perform a nearby search.".

Google maps stop showing points v3

Hi i have trouble to find what case a problem to showing the way point on goggle maps as there were no changes in the code for a wile. way point stop showing about last week. im not familiar with google api
var map = null;
var markerArray = []; //create a global array to store markers
var myPoints =
[ [52.664167, -8.509825,' HQ','favicon.ico'] ,[52.836346, -6.913117,'point 1','http://maps.google.com/mapfiles/ms/icons/red.png ' ],[52.836202, -6.912101,'point2','http://maps.google.com/mapfiles/ms/icons/red.png ' ]];
function initialize() {
var myOptions = {
zoom:7,
center: new google.maps.LatLng(53.112, -7.448),
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map"), myOptions);
var mcOptions = {
gridSize: 30,
maxZoom: 15
};
var mc = new MarkerClusterer(map, [], mcOptions);
google.maps.event.addListener(map, 'click', function() {
infowindow.close();
});
// Add markers to the map
// Set up markers based on the number of elements within the myPoints array
for(var i=0; i<myPoints.length; i++){
createMarker(new google.maps.LatLng(myPoints[i][0], myPoints[i][1]), myPoints[i][2], myPoints[i][3]);
}
mc.addMarkers(markerArray , true);
}
var infowindow = new google.maps.InfoWindow({
size: new google.maps.Size(150, 50)
});
function createMarker(latlng, html, icons) {
var contentString = html;
var links = icons;
var marker = new google.maps.Marker({
position: latlng,
map: map,
icon: links ,
zIndex: Math.round(latlng.lat() * -100000) << 5
});
// marker.setAnimation(google.maps.Animation.BOUNCE);
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map, marker);
});
markerArray.push(marker); //push local var marker into global array
}
window.onload = initialize;
<script src="https://maps.googleapis.com/maps/api/js?v=3"
type="text/javascript"></script>
<div id="map" style="width: 800px; height: 750px;" ></div>
Any suggestions?
It seems that you are using MarkerClusterer which is a part of google maps utility library, which was moved recently. Somebody probably referenced the library straight from code.google.com/svn/... in your project, where it's not available anymore and that's why it's broken. You need to find all libraries which are referenced from https://google-maps-utility-library-v3.googlecode.com/svn and replace then with your own links.
Check this SO question, user had very similar issues to yours.
Also! check this question and answers on SO!!, there are users who experienced issues with the same library, to get more information. Read all answers, as replacing https://google-maps-utility-library-v3.googlecode.com/svn with https://rawgit.com/googlemaps/... is not a correct solution, you should download the library assets into your project and reference them from there or use CDN (but not git!).

Google Map infowindow showing last value of loop

I have used for loop to display the markers and info window. But the infowindow showing only the last value of the loop.
Here is the code im using.
function initialize()
{
try
{
var geocoder;
var map;
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(41.511770, -72.809520);
var mapOptions = {
center: latlng,
zoom: 9,
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var markers = JSON.parse('[{"address":"40C Leslie Road,Bridgeport,CT","Description":"Bridgeport - 82 Unit Community"},{"address":"56 Ironwood Road,West Hartford,CT","Description":"West Hartford - 45 Unit Community"}]');
var infoWindow = new google.maps.InfoWindow();
// var address;
for (i = 0; i < markers.length; i++)
{
var address = markers[i];
geocoder.geocode({ 'address': address.address }, function (results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
//map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
icon:'Images/pin.png',
position: results[0].geometry.location
});
google.maps.event.addListener(marker, "click", function (e)
{
infoWindow.setContent("<div style='border:0px solid red;height:auto;;width:auto;'>" + address.Description + "</div>");
infoWindow.open(map, marker);
});
}
else {
//alert("Geocode was not successful for the following reason: " + status);
}
});
// map.setCenter(new google.maps.LatLng(41.511770, -72.809520))
}
}
catch (ex)
{
alert(ex.message);
}
}
google.maps.event.addDomListener(window, "load", initialize);
Please help me.
Thanks,
Venkat.
The problem is that geocoder.geocode is an asynchronous function. In other words, your execution moves away from the for loop before your requests has finished retrieving the values. Thus, you will be getting same address values, because it is the last value of the for loop when it had finished and you are placing everything to the same var address = ... variable.
To fix this, you need to wrap your geocoder.geocode request inside a self-executing anonymous function. As a result, your code works properly, because var address = ... is defined in it's own scope, together with the requests. See example below:
...
// Start of self-executing anonymous function
(function() {
var address = markers[i];
...
and:
...
// End of self-executing anonymous function
})();
// map.setCenter(new google.maps.LatLng(41.511770, -72.809520))
...
JS FIDDLE EXAMPLE (Remember to activate your icon image, I disabled it in that code.)
For further reading, I recommend self executing anonymous functions.
Cheers.

Populating google map with markers JSON

I am trying to populate a google map with markers. The information for each marker is contained in this array:
[{"id":"1","name":"toler","lng":"110.33929824829102","lat":"-7.779369982234709","created_at":"2014-02-21 16:19:28","updated_at":"2014-02-21 16:19:28"},{"id":"2","name":"hallo :)","lng":"110.36865234375","lat":"-7.797738383377609","created_at":"2014-02-21 16:19:49","updated_at":"2014-02-21 16:19:49"}]
However, my map does not show the markers. I am using this code in my javascript:
getLocations();
function getLocations() {
alert('hello');
$.ajax({
type: "GET",
url: "http://localhost:8888/public/test",
dataType: "jsonp",
success: function(json){
$.each(json, function(i, entry){
PlotMarker(json[i].lat, json[i].long);
});
},
error: function(err){
console.log(err);
}
});
}
function PlotMarker(lat, long){
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, long),
map: map,
draggable: false,
animation: google.maps.Animation.DROP
});
markerLocations.push(marker);
}
Is there any way to fix this issue? Calling this url
http://localhost:8888/public/test
returns the JSON shown above.
Any help would be greatly appreciated.
Thanks.
EDIT:
function initialize() {
var markers = [];
var latLng = new google.maps.LatLng(-7.8,110.3666667);
var map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 13,
center: latLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
}
Declare your map variable outside of the initialize function. It's the only way that other functions will be able to see it:
var map;
function initialize() {
var markers = [];
var latLng = new google.maps.LatLng(-7.8,110.3666667);
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 13,
center: latLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
}
Try changing:
PlotMarker(entry.location.lat, entry.location.lng);
to:
PlotMarker(entry.lat, entry.lng);
Try changing this:
PlotMarker(entry.location.lat, entry.location.lng);
To:
PlotMarker(json[i].lat, json[i].lng);
I think it's because of the outer []'s.
The main problem is that getLocations() is called before initialize() is started. You have to comment out getLocations(); and move it to the end of initialize() function.
That is not enough: map definition has to be moved outside of initialize() function and should not be redefined inside initialize() function.
markerLocations, used in PlotMarker(), is not defined. Should be defined as global like map
var map;
var markerLocations = [];
function initialize() {
...
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 13,
center: latLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
...
getLocations();
}
PlotMarker() has to be called like:
PlotMarker(entry.lat, entry.lng);
Are you ever calling your initialize function? Call it right when the page loads.
google.maps.addDomListener(window, 'load', initialize);
as shown here.
What is the sequence of those functions? Which do you call first, and next?
I have encountered this kind of problem and what happens is, the map has not finished loading all the tiles so the markers could not be placed on those and so they do not appear. But when you check in the console, the marker objects are there.
This is how I solved it:
google.maps.event.addListener(map, 'tilesloaded', function() {
plotMarkers();
google.maps.event.clearListeners(map, 'tilesloaded');
});
It assures the map tiles are completely loaded before plotting the markers. In this case, the markers will surely be visible.

Automatically opening marker info pane on google map

I've created a custom map with most things I want on it (custom icon and custom info bubble), however I can't find a solution to automatically open the markers info window on load, I've done alot of searching but can't seem to find anything the code I have so far is as follows, any help would be much appreciated:
function initialize() {
var myLatlng = new google.maps.LatLng(54.325109,-2.742226);
var myOptions = {
zoom: 15,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var countries = [
{
title:'Remedy',
lat:54.3210,
lon:-2.7438,
content:"<h2>Remedy</h2><p>address, <br />location, <br />postcode</p> <p><b>T:</b> 07595 153 835 <br /><b>E:</b> <a href='mailto:email'>email</a></p>"
}
];
for (var i = 0; i < countries.length; i++) {
var c = countries[i];
c.marker = new google.maps.Marker({
position: new google.maps.LatLng(c.lat, c.lon),
map: map,
icon: '/wp-content/themes/remedy/display_images/google_map_icon.png',
title: c.title});
c.infowindow = new google.maps.InfoWindow({content: c.content});
google.maps.event.addListener(c.marker, 'click', makeCallback(c));
}
function makeCallback(country) {
return function () {
country.infowindow.open(map, country.marker);
};
}
infowindow.open(map, marker);
}
Maybe it's not working because you just created the instance of the Map and didn't wait for the complete load of the map to open the InfoWindow.
Try something like this:
google.maps.event.addListenerOnce(map, 'tilesloaded', function(event) {
infowindow.open(map, marker);
});
According to the reference:
http://code.google.com/intl/en/apis/maps/documentation/javascript/reference.html#Map
tilesloaded - This event is fired when the visible tiles have finished loading.
Hmm, inforwindow does not refer to anything in your code, which is why it is not working.
Since you have one country in the list as of now you can do a quick test and intialize the infowindow variable with an actual info window, or better yet also since you have 1 item in the list, just define c to be outside the loop so you can access it and then open the popup passing it the map and the marker, something like this (assuming c has been defined outside the loop)
c.infowindow.open(map, c.marker);
var infowindow = new google.maps.InfoWindow({
content: "Test Route",
position: new google.maps.LatLng(38.8709866, -77.208055),
});
infowindow.open(map);

Categories