Question

Simply, I seem to be able to write code that either creates a clickable marker for a pop-up infoWindow OR gets the bounds of the returned markers and resets the map extent and zoom levels. I can't seem to combine the two. My example below will nicely set the extent of the map to the results of the query. But I don't quite know how to include the addListener event to the marker given how my loop is structured, and that in the var mapOptions, I set center: gbounds.getCenter(). These two issues seem to complicate my ability to add events to the map or marker.

    <cfquery name="myquery" datasource="xxxx">
       SELECT name, lat, long
       FROM tblMain
    </cfquery>

    <cfset bridgeCoord=arrayNew(1)>

    <cfloop query="myquery">
   <cfset bridge[CurrentRow] = structNew()>
   <cfset bridge[CurrentRow].lat=lat>
       <cfset bridge[CurrentRow].long=longX>
          <cfset bridge[CurrentRow].name=name>
     </cfloop>



     <script>
       $(document).ready(function() {
       var gbounds = new google.maps.LatLngBounds();
        var markers = [];


       <cfloop index="mi" array="#bridge#">
           <cfoutput> 
               //make the point
               var point = new google.maps.LatLng(#mi.lat#,#mi.long#);
               gbounds.extend(point);
               //make the marker
               var marker = new google.maps.Marker({position: point, title:"#mi.name#"});
               markers[markers.length] = marker; 
            </cfoutput>
       </cfloop>

              var mapOptions = {
                    zoom:3,
                    mapTypeControl: true,
                    mapTypeControlOptions: {
                    style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
                       },
                     mapTypeId:google.maps.MapTypeId.ROADMAP,
                     center:gbounds.getCenter()
                        };



        var map = new google.maps.Map(document.getElementById('myMap'), mapOptions);

           map.fitBounds(gbounds);

           for(var i=0; i<markers.length; i++) markers[i].setMap(map);

      });

fyi, I've also tried organizing part of the code, like below. this works great for adding the click event to the marker but then I can't seem to use my center:gbounds.getCenter() or map.fitBounds() elements b/c the mapOptions get set first and passed to the new map variable and gbounds hasn't been defined by that point. Hardcoding lat/long to center: seems to just keep it there.

       function initialize() {

    var gbounds = new google.maps.LatLngBounds();    


  var myOptions = {
    zoom: 4,
    center: new google.maps.LatLng(39.0,-94.1),
    mapTypeControl: true,
    mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
    navigationControl: true,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  map = new google.maps.Map(document.getElementById("myMap"),
                                myOptions);

  google.maps.event.addListener(map, 'click', function() {
        infowindow.close();
        });

  // Add markers to the map
  // Set up three markers with info windows 

    <cfloop index="mi" array="#bridge#">
        <cfoutput>

             //make the point
               var point = new google.maps.LatLng(#mi.lat#,#mi.long#);
            gbounds.extend(point);
            //make the marker
               var marker = createMarker(point, "#mi.name#", "#mi.name#")

        </cfoutput>
    </cfloop>


}
 map.fitBounds(gbounds);;

function createMarker(latlng, tip, html) {
    var contentString = html;
    var marker = new google.maps.Marker({
        position: latlng,
        title: tip,
        map: map,
        });

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


var infowindow = new google.maps.InfoWindow(
  { 
    size: new google.maps.Size(150,50)
  });

UPDATE 10/12: Got it to work. There is indeed a typo in Tyler's code but it's minor. I'm not sure how well I can take this code and expand on it since I'm not very versed in jQuery but this is a start. One thing it doesn't do that I'm struggling with is how to deal w/the map when zero markers are returned. It is possible in my query that no records can be returned. What happens is that the map draws but it is centered and zoomed in the middle of the ocean. I figured it should default to the center I set up (center: new google.maps.LatLng(39, -94.1) but it doesn't.

Replace: 

var $markers = $container.find(".map-marker");

with

var $markers = $container.find(".mapMarker");
Was it helpful?

Solution

EDIT

I actually just dealt with this a month or so ago, here is some modified code from what worked for me to make it more like yours.

Google Maps API v3 and jQuery 1.4.2 (though this should prolly work with any version of jQuery, and porting it to strait javascript or another library should be cake)

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>

<cfquery name="mi" datasource="xxxx">
SELECT name, lat, long, content
FROM tblName
</cfquery>

<ul id="mapMarkers">
<cfoutput query="mi">
    <li class="mapMarker" data-latitude="#mi.lat#" data-longitude="#mi.long#">
        <div class="info-window">
        <h1 class="name">#mi.name#</a></h1>
        <div class="content">#mi.content#</div>
        </div>
    </li>
</cfoutput>
</ul>
<div id="map"></div>

<script type="text/javascript">
$(function() {
    var $container = $("#mapMarkers");

    var $map = $("#map");
    var $markers = $container.find(".map-marker");

    var bounds = new google.maps.LatLngBounds();
    var infowindow = new google.maps.InfoWindow({
        maxWidth: 300
    });

    var gmap = new google.maps.Map($map[0], {
        zoom: 8
        , mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    $markers.each(function(){
        $this = $(this);
        var latitude = $this.attr("data-latitude");
        var longitude = $this.attr("data-longitude");
        var content = $this.find(".info-window").remove().html();
        var latlng = new google.maps.LatLng(latitude, longitude);

        bounds.extend(latlng);

        var marker = new google.maps.Marker({
            position: latlng
            , map: gmap
        });

        google.maps.event.addListener(marker, 'click', function() {
            infowindow.setContent(content);
            infowindow.open(this.map, this);
        });

        google.maps.event.addListener(gmap, 'click', function() {
            infowindow.close();
        });

        $this.click(function(e, el) {
            e.preventDefault();

            infowindow.setContent(content);
            infowindow.open(gmap, marker);
        })
    });

    if($markers.length > 1)
        gmap.fitBounds(bounds);
    else
        gmap.setCenter(bounds.getCenter());

    $container.hide();
});
</script>

END EDIT

First you have to move the map and mapOptions to the top. Then inside your loop just add the addListener to the map for the marker:

<cfloop index="mi" array="#bridge#">
   <cfoutput> 
       //make the point
       var point = new google.maps.LatLng(#mi.lat#,#mi.long#);
       gbounds.extend(point);
       //make the marker
       var marker = new google.maps.Marker({position: point, title:"#JSStringFormat(mi.name)#", map:map});
       google.maps.event.addListener(marker, 'click', function() {
           infowindow.setContent("#JSStringFormat(mi.content)#");
           infowindow.open(this.map, this);
       });
       markers[markers.length] = marker; 
    </cfoutput>
</cfloop>

Things to note:

I added JSStringFormat to the name and content variables.

There is a map option in the marker creation that you can just add "map:map" to it so you don't have to run the for loop at the bottom.

Also, since you are now creating the map ahead of the markers you will move the zoom and center options to the bottom.

if(markers.length > 1)  
    map.fitBounds(gbounds);  
else  
    map.setCenter(gbounds.getCenter());  

Also once last thing:

Instead of

markers[markers.length] = marker;

You can use this

markers.push(marker); 

OTHER TIPS

I'm not sure what the problem is but you may find it easier to debug (and extend) if you untangle your JavaScript and ColdFusion code. You could write all the map logic in JS and then use CF to create the data (array of lat/lng/title) that the JS will process.

<script>
// Data For Map Logic
var points = [];
<cfloop query="...">
  <cfoutput>
    points.push({lat: #db_lat#, lng: #db_lng#, etc...});
  </cfoutput>
</cfloop>

// Logic for setting map extent and creating pop-ups
for (var i = 0; i < points.length; i++) {
  // do your magic
}
</script>

Using this approach you could completely eliminate CF and the database during testing by hard-coding the points array.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top