I've been working on this forever, and I am so close! First time using CustomMarker and MarkerCluster.
The following javascript works perfectly, except the infowindows are all open, when the page loads. I want them to open on click of the marker.
<script>
function initMap() {
var newYork = {lat: 40.7127837, lng: -74.00594130000002};
var map = new google.maps.Map(document.getElementById("user-matches-map"), {
zoom: 12,
center: new google.maps.LatLng(newYork),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var markers = []
var matches = $.getJSON('get_json_matches', function(matches){
var matches = matches
for(i=0; i < matches.length; i++) {
//console.log(matches[i])
var firstName = matches[i][1]
var lat = matches[i][4]
var lng = matches[i][5]
var slugUrl = matches[i][6]
//get the user's image, and if it's missing, call the correct image path
if(matches[i][0] === "thumb/missing.png") {
var image = "http://localhost:3000/assets/medium/missing-e38aa1831b278c511eff9812efc6fda028d46b3b94f71cc88c3e0ba0e99ff19e.png"
} else {
var image = "http://" + location.host + matches[i][0];
}
//if the user has lat lng, plot them on the map
if (lat != null) {
var contentString = '<div>'+'<h1>Hello '+ firstName +'</h1>'+'</div>'
var infowindow = new google.maps.InfoWindow({
content: contentString
});
marker = new CustomMarker(
new google.maps.LatLng(lat, lng),
map,
image,
firstName,
contentString)
marker.info = new google.maps.InfoWindow({
content: contentString
});
google.maps.event.addListener(marker, 'click', (function (marker, i) {
infowindow.open(map, marker);
}
)(marker, i));
markers.push(marker);
}
}
var markerCluster = new MarkerClusterer(map, markers,
{imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'});
});
}
initMap();
function CustomMarker(latlng, map, imageSrc, firstName, contentString) {
this.latlng_ = latlng;
this.imageSrc = imageSrc;
this.firstName = firstName
$(this).on('click', function (event) {
console.log('click')
});
// Once the LatLng and text are set, add the overlay to the map. This will
// trigger a call to panes_changed which should in turn call draw.
this.setMap(map);
}
CustomMarker.prototype = new google.maps.OverlayView();
CustomMarker.prototype.draw = function () {
// Check if the div has been created.
var div = this.div_;
if (!div) {
// Create a overlay text DIV
div = this.div_ = document.createElement('div');
// Create the DIV representing our CustomMarker
div.className = "customMarker"
var img = document.createElement("img");
img.src = this.imageSrc;
div.appendChild(img);
google.maps.event.addDomListener(marker, "click", function (event) {
google.maps.event.trigger(me, "click");
});
// Then add the overlay to the DOM
var panes = this.getPanes();
panes.overlayImage.appendChild(div);
}
// Position the overlay
var point = this.getProjection().fromLatLngToDivPixel(this.latlng_);
if (point) {
div.style.left = point.x + 'px';
div.style.top = point.y + 'px';
}
};
CustomMarker.prototype.remove = function () {
// Check if the overlay was on the map and needs to be removed.
if (this.div_) {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
};
//create a prototype of the image marker
CustomMarker.prototype.getPosition = function () {
return this.latlng_;
};
</script>
Why are the infowindows open on load, if they are in an eventListener function?
Please let me know if you need more details. Thanks!
As mentioned in the comments, you've created an Immediately-Invoked Function Expression (IIFE)
From wikipedia.org:
An immediately-invoked function expression (or IIFE, pronounced "iffy") is a JavaScript programming language idiom which produces a lexical scope using JavaScript's function scoping. Immediately-invoked function expressions can be used to avoid variable hoisting from within blocks, protect against polluting the global environment and simultaneously allow public access to methods while retaining privacy for variables defined within the function.
The part where the click handler for the marker is added, your script does the following:
Create an anonymous function, passing it the current marker
(and index i
) and immediately execute it:
(function (marker, i) { infowindow.open(map, marker); })(marker, i)
The result of this IIFE (undefined
) is than used as the click handler for the marker:
google.maps.event.addListener(marker, 'click', undefined);
Unless you can switch to ES6 and let
you will have to use an IIFE to prevent scoping issues:
Javascript infamous Loop issue?
JavaScript closure inside loops – simple practical example
To make your script work, you have to change this part:
google.maps.event.addListener(marker, 'click', (function (marker, i) {
infowindow.open(map, marker);
})(marker, i));
To:
google.maps.event.addListener(marker, 'click', (function (marker) { // I've removed the index because it is unused
return function() { infowindow.open(map, marker); };
})(marker));