Question

I have a Google Map API v3 map object on a page that uses MarkerClusterer. I have a function that need to run when we click on the map to it is registered as:

google.maps.event.addListener(map, 'click', function (event) {
    CallMe(event.latLng);
});

So my problem is as follows: When I click on a cluster of MarkerClusterer instead of behaving like a marker and not raise the click event on the map but only the one from the marker it calls the click from the map.

To test this I have generated an alert from the markerclusterer click:

google.maps.event.addListener(markerClusterer, "clusterclick", function (cluster) {
    alert('MarkerClusterer click event');
}); 

So the clusterclick rises after the click event of map object. I then can't remove the listener of map object as a solution. Is there any way to test if there was a clusterer click in the click event of the map? Or a way to replicate the marker behaviour and do not raise the click event of map when clustererclick is called? Google and documentation didn’t help me.

Thx

Was it helpful?

Solution

Here is something that works but I'm still open to other better answers.

I use a setTimeout to relay the map click event to be the last thing javascript should execute and check with a boolean if clustererclick was raised before with something like this :

google.maps.event.addListener(map, 'click', function (event) {
    setTimeout(function () {
        if (!clusterClicked) {
            CallMe(event.latLng);
            alert('Map click executed');
        }
        else {
            clusterClicked = false;
            alert('ClusterClicked map click not executed');
        }
    }, 0);
});

google.maps.event.addListener(markerClusterer, "clusterclick", function (cluster) {
    clusterClicked = true;
}); 

OTHER TIPS

I had same problems and the solution i ended up with:

ClusterIcon.prototype.onAdd = function() {
    this.div_ = document.createElement('DIV');
    if (this.visible_) {
        var pos = this.getPosFromLatLng_(this.center_);
        this.div_.style.cssText = this.createCss(pos);
        this.div_.innerHTML = this.sums_.text;
    }

    var panes = this.getPanes();
    panes.overlayMouseTarget.appendChild(this.div_);

    var that = this;
    google.maps.event.addDomListener(this.div_, 'click', function(e) {
        =======> e.stopImmediatePropagation(); //<====================
        that.triggerClusterClick();
    });
};

I hate doing this but in other hand it's normal to "extend" external libraries?

I found another solution that may work. Find the following code inside markerclusterer.js:

google.maps.event.addDomListener(this.div_, 'click', function() {
  that.triggerClusterClick();
});

and change it to:

google.maps.event.addDomListener(this.div_, 'click', function(ev) {
  ev.cancelBubble = true;
  if (ev.stopPropagation) {
    ev.stopPropagation();
  }
  that.triggerClusterClick();
});

According to Martin Matysiak of Google "this is called event propagation, the event always "bubbles" up in the DOM hierarchy. You can stop this from happening with [that] code."

See: https://groups.google.com/forum/#!topic/google-maps-js-api-v3/PGeNrzv_SAs

I used this method, inspired by the other answers, but without copy-pasting library code or changing the library itself:

originalOnAdd = ClusterIcon.prototype.onAdd;
ClusterIcon.prototype.onAdd = function() {
    originalOnAdd.call(this);

    google.maps.event.addDomListener(this.div_, 'click', function (ev) {
        ev.cancelBubble = true;
        if (ev.stopPropagation)
            ev.stopPropagation();
    });
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top