Google map api clustering with custom info balloon problem

Hi,

so i am trying to implement clustering and have custom info balloons (like i do without clustering). I have found some script that almost does what i want. It indeed clusters my map pins and even changes the colour to custom pin colours as before but it does not insert the custom text instead it just shows the last xml entry for all the pins. I assume it is not looping through properly somehow but i don’t know how to fix it

   <script type="text/javascript">
    //<![CDATA[

    var customIcons = {
      restaurant: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_blue.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      },
      bar: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      }
    };

    function load() {
      var cluster = [];
      var map = new google.maps.Map(document.getElementById("map"), {
        center: new google.maps.LatLng(47.6145, -122.3418),
        zoom: 13,
        mapTypeId: 'roadmap'
      });
var infowindow = new google.maps.InfoWindow();

      // Change this depending on the name of your PHP file
      downloadUrl("<?php bloginfo('stylesheet_directory'); ?>/phpsqlajax_genxml.php ", function(data) {
        var xml = data.responseXML;
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
          var name = markers[i].getAttribute("name");
          var address = markers[i].getAttribute("address");
          var type = markers[i].getAttribute("type");
          var point = new google.maps.LatLng(
              parseFloat(markers[i].getAttribute("lat")),
              parseFloat(markers[i].getAttribute("lng")));
          var html = "<b>" + name + "</b> <br/>" + address;
          var icon = customIcons[type] || {};
          var marker = new google.maps.Marker({
            map: map,
            position: point,
            icon: icon.icon,
            shadow: icon.shadow
          });
          google.maps.event.addListener(marker, 'click', (function(marker, i) {
                        return function() {
                            infowindow.setContent("Info on member here");
                            infowindow.open(map, marker);
                        }
                    })(marker, i));
          cluster.push(marker);
        }
        var mc = new MarkerClusterer(map,cluster);
      });
    }

    function bindInfoWindow(marker, map, infoWindow, html) {
      google.maps.event.addListener(marker, 'click', function() {
        infoWindow.setContent(html);
        infoWindow.open(map, marker);
      });
    }

    function downloadUrl(url, callback) {
      var request = window.ActiveXObject ?
          new ActiveXObject('Microsoft.XMLHTTP') :
          new XMLHttpRequest;

      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          request.onreadystatechange = doNothing;
          callback(request, request.status);
        }
      };

      request.open('GET', url, true);
      request.send(null);
    }

    function doNothing() {}

    //]]>
  </script>

This line

infowindow.setContent("Info on member here");

is where on my script i normally put

infowindow.setContent(html);

as this then inserts the html variable. But when i do this in the script above it just uses the last entry for everything.

any ideas how to fix this. I am hoping it is a simple fix getting the html variable to loop properly somehow.

thanks

Credit - http://stackoverflow.com/questions/11101765/integrate-markerclusterer-with-database-driven-google-map-v3

1 Like

Hi Noppy,

Any reason that you changed the code to stop using the bindInfoWindow() function? Using that would solve your problem.

As it stands, the problem with the current code is that you’re only capturing the values of marker and i within your closures:

google.maps.event.addListener(marker, 'click', (function(marker, i) {
  return function() {
    infowindow.setContent(html);
    infowindow.open(map, marker);
  }
})(marker, i));

Each handler is still using the value of html from the parent scope, which by the time they run is the last value from the loop.

I figured that would be where the problem lies but i don’t know how to write it back in. This was a piece of code i found on stack exchange and was closer than i had got as it does do the clustering.

I’ve tried adding in the marker bits to the bindInfoWindow() function but i am not sure what i need to do as i can’t get it to work.

any help would be appreciated

thanks

I was thinking something like this:

for (var i = 0; i < markers.length; i++) {
  
  // ...

  var marker = new google.maps.Marker({
    map: map,
    position: point,
    icon: icon.icon,
    shadow: icon.shadow
  });

  bindInfoWindow(marker, map, infoWindow, html);

  cluster.push(marker);
}

var mc = new MarkerClusterer(map,cluster);

thanks for the reply.
I’ve given it a go but i still can’t get it to work this is the code i now have which only shows 1 pin and doesn’t have a info balloon. I’ve tried a few changes but still not got it working. I’m not great with JS but i’ve had a look at the code inspector in FF and it says ‘infoWindow is not defined’ so i guess thats my starting point but if you have can see why that would be great. thanks

<script type="text/javascript">
    //<![CDATA[

    var customIcons = {
     jellyfish: {
        icon: \'http://labs.google.com/ridefinder/images/mm_20_purple.png\',
        shadow: \'http://labs.google.com/ridefinder/images/mm_20_shadow.png\'
      },
      turtles: {
        icon: \'http://labs.google.com/ridefinder/images/mm_20_red.png\',
        shadow: \'http://labs.google.com/ridefinder/images/mm_20_shadow.png\'
      },
      baskingshark: {
        icon: \'http://labs.google.com/ridefinder/images/mm_20_yellow.png\',
        shadow: \'http://labs.google.com/ridefinder/images/mm_20_shadow.png\'
      }
    };

    function load() {
      var cluster = [];
      var map = new google.maps.Map(document.getElementById("map"), {
        center: new google.maps.LatLng(54.559322, -4.174804),
        zoom: 5,
        mapTypeId: \'roadmap\'
      });
var infowindow = new google.maps.InfoWindow();

var species = "'.$_GET['lg'].'"
var sightdate = "'.$_GET['dt'].'"

      // Change this depending on the name of your PHP file
      downloadUrl("map_data_cluster.php?search=&lg="+species+"&dt="+sightdate, function(data) {
        var xml = data.responseXML;
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
          var name = markers[i].getAttribute("name");
          var address = markers[i].getAttribute("address");
          var type = markers[i].getAttribute("type");
          
          var spec = markers[i].getAttribute(\'spec\');
          var DateSighting = markers[i].getAttribute(\'DateSighting\');
          var html = \'<b>\' + name + \'</b> reported seeing \' + spec +\' here<br/>\' + DateSighting + \'</b>\' ;
          var point = new google.maps.LatLng(
              parseFloat(markers[i].getAttribute("lat")),
              parseFloat(markers[i].getAttribute("lng")));
          
          var icon = customIcons[type] || {};
          var marker = new google.maps.Marker({
            map: map,
            position: point,
            icon: icon.icon,
            shadow: icon.shadow
          });
          
  

  bindInfoWindow(marker, map, infoWindow, html);

  cluster.push(marker);
}

var mc = new MarkerClusterer(map,cluster);
      });
    }

    function bindInfoWindow(marker, map, infoWindow, html) {
      google.maps.event.addListener(marker, \'click\', function() {
        infoWindow.setContent(html);
        infoWindow.open(map, marker);
      });
    }

    function downloadUrl(url, callback) {
      var request = window.ActiveXObject ?
          new ActiveXObject(\'Microsoft.XMLHTTP\') :
          new XMLHttpRequest;

      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          request.onreadystatechange = doNothing;
          callback(request, request.status);
        }
      };

      request.open(\'GET\', url, true);
      request.send(null);
    }

    function doNothing() {}

    //]]>
  </script>`

Where you’re calling bindInfoWindow() you’re trying to pass infoWindow rather than infowindow. JavaScript variable names are case sensitive, so the two are not the same.

Also, in the code you posted above, I’ve noticed some odd escaping which will break your code, eg:

var spec = markers[i].getAttribute(\'spec\');

You should only escape quote marks when you need them to appear within a string, eg:

var msg = 'Hello, I\'m pleased to meet you';

Escaping opening/closing quote marks will cause you problems.

:grin: thank you would never have spotted that.

seems to be working http://www.mcsuk.org/sightings/map/cluster.php

Sorry to confuse the issue as the escape bits are because this is all contained in a PHP string that is output into the header template.

Many thanks for your help, much appreciated. There was another chap on here that i helped get the basic maps working who will be interested in this so i’ll pass it on to him too.

This is what the working code now looks like (php included). Now i just have to have a play to see if i can shoe-horn polygons and lines in there too … eeeek!

<? 
// define an additional style sheets or scripts for this page to be used in the page template
$css = "
<script type='text/javascript' src='http://maps.googleapis.com/maps/api/js?sensor=false'></script>
<script type=\"text/javascript\" src=\"http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/src/markerclusterer.js\"></script>";
$css .=  '<script type="text/javascript">
    //<![CDATA[

    var customIcons = {
     jellyfish: {
        icon: \'http://labs.google.com/ridefinder/images/mm_20_purple.png\',
        shadow: \'http://labs.google.com/ridefinder/images/mm_20_shadow.png\'
      },
      turtles: {
        icon: \'http://labs.google.com/ridefinder/images/mm_20_red.png\',
        shadow: \'http://labs.google.com/ridefinder/images/mm_20_shadow.png\'
      },
      baskingshark: {
        icon: \'http://labs.google.com/ridefinder/images/mm_20_yellow.png\',
        shadow: \'http://labs.google.com/ridefinder/images/mm_20_shadow.png\'
      }
    };

    function load() {
      var cluster = [];
      var map = new google.maps.Map(document.getElementById("map"), {
        center: new google.maps.LatLng(54.559322, -4.174804),
        zoom: 5,
        mapTypeId: \'roadmap\'
      });
var infowindow = new google.maps.InfoWindow();

var species = "'.$_GET['lg'].'"
var sightdate = "'.$_GET['dt'].'"

      // Change this depending on the name of your PHP file
      downloadUrl("map_data_cluster.php?search=&lg="+species+"&dt="+sightdate, function(data) {
        var xml = data.responseXML;
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
          var name = markers[i].getAttribute("name");
          var address = markers[i].getAttribute("address");
          var type = markers[i].getAttribute("type");
          
          var spec = markers[i].getAttribute(\'spec\');
          var DateSighting = markers[i].getAttribute(\'DateSighting\');
          var html = \'<b>\' + name + \'</b> reported seeing \' + spec +\' here<br/>\' + DateSighting + \'</b>\' ;
          var point = new google.maps.LatLng(
              parseFloat(markers[i].getAttribute("lat")),
              parseFloat(markers[i].getAttribute("lng")));
          
          var icon = customIcons[type] || {};
          var marker = new google.maps.Marker({
            map: map,
            position: point,
            icon: icon.icon,
            shadow: icon.shadow
          });
          
  

  bindInfoWindow(marker, map, infowindow, html);

  cluster.push(marker);
}

var mc = new MarkerClusterer(map,cluster);
      });
    }

    function bindInfoWindow(marker, map, infowindow, html) {
      google.maps.event.addListener(marker, \'click\', function() {
        infowindow.setContent(html);
        infowindow.open(map, marker);
      });
    }

    function downloadUrl(url, callback) {
      var request = window.ActiveXObject ?
          new ActiveXObject(\'Microsoft.XMLHTTP\') :
          new XMLHttpRequest;

      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          request.onreadystatechange = doNothing;
          callback(request, request.status);
        }
      };

      request.open(\'GET\', url, true);
      request.send(null);
    }

    function doNothing() {}

    //]]>
  </script>';
?>

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.