Reputation: 25
My custom google maps code stopped working all of a sudden and I can't figure out why. If I paste the same exact code into a jsfiddle it works fine, however on my site it throws an error:
Uncaught TypeError: Object #<Object> has no method 'O'
or
Uncaught TypeError: Cannot call method 'unbindAll' of null
The pins are appearing on the map in the correct locations and respond to clicks appropriately (once) by bouncing up and down, however the popups do not pop up. What gives?
Upvotes: 1
Views: 712
Reputation: 28870
On your website, find the JavaScript code that handles the click
event on one of your markers. You'll find the code in the map.html
page itself:
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 9,
center: new google.maps.LatLng(37.75538, -122.201983),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
var marker, i, currentMarker = "null";
for (i = 0; i < locations.length; i++) {
marker = new MarkerWithLabel({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
draggable: false,
clickable: true,
map: map,
labelContent: locations[i][3],
labelAnchor: new google.maps.Point(22, 0),
labelClass: "maplabels", // the CSS class for the label
labelStyle: {opacity: 1.0}
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
// in case they open a new info window without closing the old one, stop animation
if (currentMarker != "null")
currentMarker.setAnimation(null);
marker.setAnimation(google.maps.Animation.BOUNCE);
infowindow.setContent(locations[i][0]);
infowindow.open(map, marker);
currentMarker = marker;
}
})(marker, i));
google.maps.event.addListener(infowindow, 'closeclick', function() {
currentMarker.setAnimation(null);
});
}
Now the actual code that handles the click is in the middle of that:
if (currentMarker != "null")
currentMarker.setAnimation(null);
marker.setAnimation(google.maps.Animation.BOUNCE);
infowindow.setContent(locations[i][0]);
infowindow.open(map, marker);
currentMarker = marker;
Use the JavaScript debugger in Chrome or your favorite browser to set a breakpoint on the first line of this code (the if
statement) by clicking in the left margin. Use the Sources tab in the developer tools to open the code.
If you aren't familiar with the JavaScript developer tools, here's an introduction to JavaScript debugging and a detailed introduction to the Chrome DevTools.
Now that you have the breakpoint set, click on one of your markers. It should stop on the line of code where you set the breakpoint.
Now use the Step Over command in the debugger to step through that code. On Windows, you can use the F10 key here. You'll see that the error happens when you try to execute this line:
infowindow.open(map, marker);
So what's wrong here? In the Chrome debugger, you can hover the mouse over any variable in the source code to see its current value.
If you look at the marker
variable it looks like something fairly plausible, with properties that indeed have to do with maps and markers and such.
But take a look at the map
variable. It looks like this:
Object {9: false, 16: false, 18: false, 27: false, 65: false}
That doesn't look much like a Google Maps API object, does it? In fact, some of those numbers sound very familiar. 65
is the character code for the letter 'a'
, 27
is Escape
, and 9
is the Tab
key.
It looks like somewhere else in your code, some other code has overwritten your global map
variable with an unrelated variable of the same name. In fact, the name makes some sense: the map
object is some sort of mapping (in the computer science sense, not the geographic sense) from character codes to booleans.
A simple fix would be to change the name of your map
variable, to gmap
or some other name that doesn't conflict with this other map
variable. Or even better, you could wrap all of this map code inside a function so that your map
variable is local to this function and won't be overwritten by a global variable elsewhere.
But it's also likely that the very existence of the other map
variable is a bug! There may be some function elsewhere in the code that meant to have that map
be a local variable, but simply forgot to use a var
on it so it became global.
While I've got you, you can simplify that marker creation code a little by getting rid of the function-that-returns-a-function in the event handler. You're doing that to get a closure for the marker variable, but this is a needlessly complicated way to do it. Instead, you can simply put the entire body of your for
loop in a function of its own. Calling that function will get you the closure you need without the extremely confusing function-returning-a-function.
Also, you don't need to use the string "null"
to indicate a nonexistent currentMarker
value.
And finally, you're setting an event listener on the infowindow for each marker, even though you have only one infowindow. You can set this event listener once.
Combining those ideas, you might end up with:
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 9,
center: new google.maps.LatLng(37.75538, -122.201983),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(
infowindow, 'closeclick', stopAnimation
);
var currentMarker;
for (i = 0; i < locations.length; i++) {
addMarker( locations[i] );
}
function addMarker( location ) {
var marker = new MarkerWithLabel({
position: new google.maps.LatLng(location[1], location[2]),
draggable: false,
clickable: true,
map: map,
labelContent: location[3],
labelAnchor: new google.maps.Point(22, 0),
labelClass: "maplabels", // the CSS class for the label
labelStyle: {opacity: 1.0}
});
google.maps.event.addListener(marker, 'click', function() {
stopAnimation();
marker.setAnimation(google.maps.Animation.BOUNCE);
infowindow.setContent(location[0]);
infowindow.open(map, marker);
currentMarker = marker;
});
}
function stopAnimation() {
currentMarker && currentMarker.setAnimation(null);
currentMarker = null;
}
}
initMap();
Upvotes: 4