Search code examples
javascriptruby-on-railsgoogle-maps-api-3google-maps-markersruby-on-rails-2

Google Maps API v3 Markers only load sometimes


I have a map-making tool that is built with the Google Maps API V3. It allows users to enter two or more locations and produce a map and route. I also have a checkbox that, when clicked, shows markers indicating nearby points of interest.

When I first built the tool, I think it worked well every time. Recently, though, I've noticed that the markers do not always appear when the checkbox is clicked. The map and routing work fine, but the markers only work occasionally. This error seems to occur when they don't work:

Uncaught ReferenceError: map is not defined

It references a section of the "cmarkers" section of javascript (see below).

Background detail: This is part of a Rails web app and a webpage / layout called "Itineraries". When you land on the itineraries webpage and click on the "Map Maker" icon, the map-making tool appears. It's loaded in an i-frame, it's called "map.html.erb", and the map view lives in /views/itineraries. All of the javascript for the map maker lives in the Itineraries layout file, however.

Based on reviewing these posts, I think it might be something in the way that I've ordered or initialized the code, and I think the main culprit is likely in that "cmarkers" section of the code.

I've tried several different changes, but each has either not worked or stopped the map from initializing. Here is the javascript; please note that the API key and other small sections are redacted. Below it is the code for the markers.

        <script src="https://maps.googleapis.com/maps/api/js?key=MYAPIKEY&sensor=false"></script>
    <script type='text/javascript'> 
    $(function(){
        var directionsDisplay;
        var map;            

        function overlaysClear() {
          if (markersArray) {
            for( var i = 0, n = markersArray.length; i < n; ++i ) {
              markersArray[i].setVisible(false);
            }
          }
        }

        function overlaysShow() {
          if (markersArray) {
            for( var i = 0, n = markersArray.length; i < n; ++i ) {
              markersArray[i].setVisible(true);
            }
          }
        }

        $("#showmapview").click(function() {
        overlaysClear();
        $('#mapeach').attr('checked', false);
        });

        $('#mapeach').change(function() {
         if( $('#mapeach').attr("checked")) {
                  overlaysShow();
                  }
                  else  {
                  overlaysClear();
                  }
        });
        cmarkers();

        google.maps.event.addDomListener(window, 'load', initialize); 
    });

    var directionsService = new google.maps.DirectionsService();
        var markersArray = [];
        var arrInfoWindows = null;

    function initialize() {
          var rendererOptions = {
          draggable: true,
          panel:document.getElementById('directions_panel')
         };

          directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
          var chicago = new google.maps.LatLng(41.850033, -87.6500523);
              var mapOptions = {
              zoom: 6,
              center: chicago,
              mapTypeId: google.maps.MapTypeId.ROADMAP
            }
          map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);

          directionsDisplay.setMap(map);
        }

        function calcRoute() {

            var start = document.getElementById("start").value;
            var end = document.getElementById("end").value;
            var waypts = [];
          var checkboxArray = document.getElementById("waypoints");
          for (var i = 0; i < checkboxArray.length; i++) {
             waypts.push({
                  location:checkboxArray[i].value,
                  stopover:true
              });
         }

          var request = {
              origin: start,
              destination: end,
              waypoints: waypts,
              optimizeWaypoints: optimize,
              travelMode: google.maps.TravelMode.DRIVING
          };
          directionsService.route(request, function(response, status) {
            if (status == google.maps.DirectionsStatus.OK) {
              directionsDisplay.setDirections(response);
              var route = response.routes[0];
            }    
          });
        }; 

        function cmarkers() {
                    $.getJSON( "/mapeach.js", {}, function( data ) {
                    $.each( data, function( i, item ) {
                    var loc = item.mainlocation;
                    $("#markers").append('<li><a href="#" rel="' + i + '">' + loc.nickname + '</a></li>');
                    var marker = new google.maps.Marker({
                    position: new google.maps.LatLng(+loc.latitude, +loc.longitude),
                    map: map,
                    title: loc.nickname,
                    });
                    markersArray.push(marker);

                      var infowindow = new google.maps.InfoWindow({
                            content: '<a class="clink" href="/spots/'+ loc.id +'/'+ loc.nickname +'" target="_blank">'+ loc.nickname +'</a>'
                            });

                    google.maps.event.addListener(marker, 'click', function() {
                         if (arrInfoWindows != null) { 
                            arrInfoWindows.close(); 
                        } 
                        infowindow.open(map,marker);
                        arrInfoWindows = infowindow;
                        });
                      });
                    });
                };  
    </script>

The mapeach.js file is formatted as below:

[{"mainlocation":{"latitude":"40.706352","nickname":"First Location","id":100000,"longitude":"-73.987650"}},{"mainlocation":{"latitude":"34.061148","nickname":"Second Location","id":100001,"longitude":"-118.273067"}}]

Solution

  • I was able to solve this problem by moving the cmarkers code inside the initialize. I think that the javascript wasn't making clear that the map variable in the initialize was also the map variable in the cmarkers function (sorry if the language isn't precise; I'm not great in js). See below:

    function initialize() {
                  var rendererOptions = {
                  draggable: true,
                  panel:document.getElementById('directions_panel')
                 };
    
              directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
              var chicago = new google.maps.LatLng(41.850033, -87.6500523);
                  var mapOptions = {
                  zoom: 6,
                  center: chicago,
                  mapTypeId: google.maps.MapTypeId.ROADMAP
                }
              map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
    
              directionsDisplay.setMap(map);
    
              cmarkers();
              function cmarkers() {
                    $.getJSON( "/mapeach.js", {}, function( data ) {
                    $.each( data, function( i, item ) {
                    var loc = item.mainlocation;
                    $("#markers").append('<li><a href="#" rel="' + i + '">' + loc.nickname + '</a></li>');
                    var marker = new google.maps.Marker({
                    position: new google.maps.LatLng(+loc.latitude, +loc.longitude),
                    map: map,
                    title: loc.nickname,
                    });
                    markersArray.push(marker);
    
                      var infowindow = new google.maps.InfoWindow({
                            content: '<a class="clink" href="/spots/'+ loc.id +'/'+ loc.nickname +'" target="_blank">'+ loc.nickname +'</a>'
                            });
    
                    google.maps.event.addListener(marker, 'click', function() {
                         if (arrInfoWindows != null) { 
                            arrInfoWindows.close(); 
                        } 
                        infowindow.open(map,marker);
                        arrInfoWindows = infowindow;
                        });
                      });
                    });
                };  
    

    Special credit to this post for giving me the idea: can't see google marker