title: Google Maps API V3: Simple Marker Cluster Not Showing Up
body: <p>I am developing a Web Based Application using PHP, MongoDB, Javascript, and Google Maps API V3.</p>
  
  <p>I was able to easily generate and display markers on a google map by converting the MongoDB array using json_encode. Here's an example map with markers and infowindow.</p>
  
  <p><a href="https://www.dropbox.com/s/lvsrrdokqcmkt51/InfoWindow.png" rel="nofollow">Markers and InfoWindow</a></p>
  
  <p>However, when I try to implement the Google Maps MarkerClusterer method, the markers disappears. I followed Google Map's "<a href="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/docs/examples.html" rel="nofollow" title="A Simple MarkerClusterer Example">A Simple MarkerClusterer Example</a>" as a guide.</p>
  
  <p>I also tried declaring a global cluster object, passing it an empty array, </p>
  
  <pre><code>var markerCluster = new MarkerClustrer(map, markers);
  </code></pre>
  
  <p>then using <code>markerCluster.addMarkers(markers, true);</code> as alternate method with no luck.</p>
  
  <p>It seems pretty simple but somehow, it is not displaying the markers. I also tried commenting out the whole infoWindow/OnClick event section so I don't think its related to that. Any help is greatly appreciated. </p>
  
  <p>PHP MongoDB Query:</p>
  
  <pre><code>&lt;?php
  
  // Connect to Mongo and set DB and Collection
  try
  {
      $mongo = new Mongo();
      $db = $mongo-&gt;selectDB('twitter');
      $collection = $db-&gt;selectCollection('tweets');
  }
  catch(MongoConnectionException $e)
  {
      die("Failed to connect to Twitter Database ". $e-&gt;getMessage());
  }
  
  // The hotspots array will contain the data that will be returned
  $tweets = array();
  
  // Return a cursor of tweets from MongoDB
  $cursor = $collection-&gt;find();
  
  // Try catch for catching whether there are tweets to display
  $count = 0;
  try 
  {
      $count = $cursor-&gt;count();
  } 
  catch (MongoCursorException $e) 
  {
      die(json_encode(array('error'=&gt;'error message:' .$e-&gt;getMessage())));
  }
  
  // Loops through the cursor again specifically for querying all geo locations
  // Unlike table display of tweets, this cursor is not limited by pages. 
  foreach($cursor as $id =&gt; $value)
  { 
      $mapLocations[] = array
      (
          'id'=&gt;$value['_id'],
          'screen_name'=&gt;$value['screen_name'],
          'name'=&gt;$value['name'],
          'tweet'=&gt;$value['tweet'],
          'hashtags'=&gt;$value['hashtags'],
          'lat'=&gt;$value['geo']['lat'],
          'long'=&gt;$value['geo']['long'],
          'date'=&gt;$value['date'],
          'img'=&gt;$value['img'],
          'specImg'=&gt;$value['specImg']
      );
  }
  // var_dump($mapLocations);
  ?&gt;
  </code></pre>
  
  <p>Javascript Function:</p>
  
  <pre><code>function initialize() 
  {
      // Converts MongoDB information to JSON, ready for Javascript
      var tweets = &lt;?php echo json_encode($mapLocations); ?&gt;;
  
      // Sets google maps options
      var myOptions = 
      {
          // Centers on Maui...
          center: new google.maps.LatLng(20.80362, -156.321716),
          zoom: 7,
          mapTypeId: google.maps.MapTypeId.TERRAIN
      };
  
      // Sets Marker Clusterer Options
      var mcOptions =
      {
          gridSize: 50, maxZoom: 15
      };
  
      // Generates Google Map and applies the defined options above.
      var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  
      // Infowindow for displaying information for onClick event  
      // Content must be inside the google.maps.event function 
      // Otherwise the same content will be entered on all markers    
      var infoWindow = new google.maps.InfoWindow({});
  
      var markerCluster = null;   // Initializes markerCluster
      var markers = [];           //Array needed to pass to MarkerClusterer
  
      // Loops through each tweet and draws the marker on the map.    
      for (var i = 0; i &lt; tweets.length; i++)
      {
          var tweet = tweets[i];
  
          if(tweet.lat != null || tweet.long != null) 
          {
              var myLatLng = new google.maps.LatLng(tweet.lat, tweet.long);
              //document.write(" Latitude: " + tweet.lat + " Longitude: " + tweet.long + " &lt;br&gt; ");
              var marker = new google.maps.Marker({ 
                  position: myLatLng,
                  //icon: "markers/flag.png",
                  //map: map,
              });
  
              markers.push(marker);
  
              google.maps.event.addListener(marker, 'click', (function(marker, i) 
              {
                  return function() 
                  {
                      // Generates a table for infoWindow
                      var content = "&lt;table class='popup'&gt;";
  
                      // Check if image exits, otherwise show no image icon
                      if(tweets[i].specImg != null) 
                      {
                          content += "&lt;tr&gt;&lt;th width=75 &gt;&lt;a href=" + tweets[i].specImg + "&gt;";
                          content += "&lt;img height=75 width=75 src=" + tweets[i].specImg + "&gt;&lt;/a&gt;";
                      }
                      else
                      {
                          content += "&lt;tr&gt;&lt;th width=75&gt;&lt;img height=75 width=75 src=images/noimage.jpg&gt;";
                      }
                      // Concatanate screen name and tweet
                      // Will work on trimming information
                      content += "&lt;/th&gt;&lt;td&gt;" + tweets[i].screen_name + " says...&lt;br&gt;"; 
                      content += "''" + tweets[i].tweet +  "''&lt;br&gt;";
                      content += "on " + tweets[i].date + "&lt;/td&gt;";
                      content += "&lt;/table&gt;";
  
                      // Zoom into marker on click
                      map.setZoom(15);
                      map.setCenter(marker.getPosition());
  
                      // Sets the infoWindow content to the marker
                      infoWindow.setContent(content);
                      infoWindow.open(map, marker);
                  }
              })(marker, i)); 
          }
      } 
      var markerCluster = new MarkerClusterer(map, markers);
  }
  </code></pre>
  
  <p>@Robbie: </p>
  
  <p>The JSONned $mapLocations becomes a multidimensional array but I simplified the $mapLocations to only store a 2D lat and long. The javascript source code becomes as follow. </p>
  
  <pre><code>var tweets = [{"lat":20.87179594,"long":-156.47718775},{"lat":20.87195633,"long":-156.47714356},{"lat":20.87138419,"long":-156.47719744},{"lat":21.3320704,"long":-157.8685716},{"lat":null,"long":null},{"lat":21.36509415,"long":-157.92824454},{"lat":21.3320825,"long":-157.8684742},{"lat":null,"long":null},{"lat":21.33673131,"long":-157.86824},{"lat":21.332507,"long":-157.86635342},{"lat":null,"long":null},{"lat":null,"long":null},{"lat":null,"long":null},{"lat":37.36520709,"long":-121.92386941},{"lat":37.2499758,"long":-121.86462506},{"lat":37.36278955,"long":-121.90521146},{"lat":null,"long":null},{"lat":37.36278955,"long":-121.90521146},{"lat":null,"long":null},{"lat":null,"long":null},{"lat":null,"long":null},{"lat":null,"long":null},{"lat":null,"long":null},{"lat":null,"long":null},{"lat":20.88944108,"long":-156.4761887},{"lat":37.36273157,"long":-121.90479984},{"lat":20.85102618,"long":-156.65936351},{"lat":20.88949978,"long":-156.4762491},{"lat":null,"long":null},{"lat":21.3320168,"long":-157.8685715},{"lat":null,"long":null},{"lat":null,"long":null},{"lat":null,"long":null}];
  </code></pre>