Showing posts with label Google Maps API. Show all posts
Showing posts with label Google Maps API. Show all posts

Thursday, August 23, 2012

Google Maps API 3 inside jQuery Accordion

I am working on a web page that utilizes multiple JS libraries including jQuery and Google Maps. My map is inside a jQuery Accordion pane, and has been presenting a problem with partial rendering as described on a StackOverflow topic. In my case, the code was configured to initialize the map at the time of the first click on the accordion panel that contained the map. It worked fine, unless the user switched to a different pane then tried to return to the map. Then, it would only draw approximately 1/4 of the map canvas, with the remainder being gray.

In my research, calling google.maps.event.trigger(map, "resize"); was a consistent suggestion, but the first few locations I tried calling it did not work. I finally solved the problem by binding the trigger to the click event of the jQuery Accordion pane, based on an example at essentialwebconcepts.com.

My code:
function triggerMapResize()
    {
    google.maps.event.trigger(map, "resize");
    }

jQuery(document).ready(function() {
    jQuery("#the-accordion").bind('accordionchange', function(event, ui) {
        if (ui.newContent.attr('id') == 'the-pane-id')
            {
            triggerMapResize();
            }
        });
    });
The only remaining problem is that the center of the map changes when the user returns to the map pane after looking at a different pane.  I started a topic on SO for this issue.

Update August 24:
Several changes were required to get this to work on all browsers including IE. IE failed upon page load when I was trying to initialize the map. Originally I was using window.onload = function () { initialize_map(); } but that resulted in a vague IE error.

I added code to capture the map's center LatLng when the user moves the mouse outside the map canvas, and more code to move the center to that point upon returning to the map.

          var map=null;
    var currMapCenter = null;

    jQuery(document).ready(function() {
    jQuery("#accordion").bind('accordionchange', function(event, ui) {
    if (ui.newContent.attr('id') == 'region-list')
    {
    if(map==null) {
    //first load; call map initialization
    initialize_map();
    }
    triggerMapResize();
    }
    });

    function initialize_map() {
   
    //do initialization here...
   
    google.maps.event.addListener(map, 'mouseout', function() {
    currMapCenter=map.getCenter();
    });
    }

    function triggerMapResize() {
    google.maps.event.trigger(map, "resize");
    map.setCenter(currMapCenter);
    }

A side note about another problem I ran across in IE8 that has limited documentation online: When creating LatLng arrays, double-check syntax to be sure there is no comma after the final element. While the map looked perfect in standards-compliant browsers, in IE8 each polygon had a segment extending up to near the North Pole.

var polygonPoints= [
        new google.maps.LatLng(24.3250983277945,-79.4028109345145),
        new google.maps.LatLng(48.9377507851552,-142.984008088915),
        new google.maps.LatLng(37.9247004907078,-131.891417410329),
        new google.maps.LatLng(29.8055038628199,-122.143142289543),
        new google.maps.LatLng(21.6909424687438,-114.135809333967),
        new google.maps.LatLng(24.3250983277945,-79.4028109345145),
        ];

This mistake cost me an hour of confusion. Finally I found a discussion mentioning trailing commas with Google Maps in Internet Explorer and discovered the improper extra comma at the end of each array.   It was caused by creating the LatLng object using concatenation in Excel without manually trimming the last value.

Wednesday, July 25, 2012

Google Maps API multiple markers and infowindows

I was having trouble with binding InfoWindows to markers. No matter which marker was clicked, the InfoWindow for the last marker to be created was displayed.  I found the answer to the problem here:
http://stackoverflow.com/questions/2357323/trying-to-bind-multiple-infowindows-to-multiple-markers-on-a-lgoogle-map-and-fail

Simply creating a separate function to add the event listener solved the problem.

Monday, February 27, 2012

Working notes February 27

8:30 a.m.
I am working on the Google Maps API 3 again today. One of my goals is to allow users to use their preference of geographic coordinates to locate a spot on the map.

References I have found:

Friday, February 24, 2012

Working notes February 24, 2012: Google Maps API

Today's focus is on creating a user interface for the Google Maps API.  Using basic HTML5, Javascript and the Google Maps API 3, I set out to create a reference of three methods for creating markers on a map, each with different properties.

Here is the source code of the result:
<!DOCTYPE HTML>

<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var geocoder = new google.maps.Geocoder();
var theMap;

function geocodePosition(pos) {
  geocoder.geocode({
    latLng: pos
  }, function(responses) {
    if (responses && responses.length > 0) {
      updateMarkerAddress(responses[0].formatted_address);
    } else {
      updateMarkerAddress('Cannot determine address at this location.');
    }
  });
}

function updateMarkerStatus(str) {
  document.getElementById('markerStatus').innerHTML = str;
}

function updateMarkerPosition(latLng) {
  document.getElementById('info').innerHTML = [
    latLng.lat(),
    latLng.lng()
  ].join(', ');
}

function updateMarkerAddress(str) {
  document.getElementById('address').innerHTML = str;
}

function initialize() {
      //initialize map with pin at Capitol & Front in Boise.
      var latLng = new google.maps.LatLng(43.61351466, -116.203798);
      theMap = new google.maps.Map(document.getElementById('mapCanvas'), {
        zoom: 13,
        center: latLng,
        mapTypeId: google.maps.MapTypeId.HYBRID
      });
     
      var marker = new google.maps.Marker({
        position: latLng,
        title: 'Initialization marker',
        map: theMap,
        draggable: true
      });
     
      // Update current position info.
      updateMarkerPosition(latLng);
      geocodePosition(latLng);
     
      // Add dragging event listeners.
      google.maps.event.addListener(marker, 'dragstart', function() {
      updateMarkerAddress('Dragging...');
      });
     
      google.maps.event.addListener(marker, 'drag', function() {
      updateMarkerStatus('Dragging...');
      updateMarkerPosition(marker.getPosition());
      });
     
      google.maps.event.addListener(marker, 'dragend', function() {
      updateMarkerStatus('Drag ended');
      geocodePosition(marker.getPosition());
      });
     
      //add click listener for new marker http://stackoverflow.com/questions/7083264/google-maps-api-v3-set-marker-and-get-point
      google.maps.event.addListener(theMap, 'click', function(e) {
      placeMarkerByMapClick(e.latLng, theMap);
      });
}

function addMarkerByExternalButton()
    {
        //alert("addMarker");
        var latLng = new google.maps.LatLng(43.60283295462482, -116.19584164278416);
        //var theMap = google.maps.Map(document.getElementById('mapCanvas'));
        var blueMapMarker = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
               
        // Set up our GMarkerOptions object
        markerOptions = {  };
        
        http://stackoverflow.com/questions/4236522/google-maps-api-v3-info-window-displaying-same-information-for-all-the-markers
        var contentString_1 =  "<b>BSU Broncos Stadium</b><br /> Boise, Idaho, USA<br><b><a href='http://broncosports.com'>BSU Athletics site</a></b><br /><img src='http://image.cdnllnwnl.xosnetwork.com/fls/9900/images/facilities/new_turf.jpg' />";
        var infowindow_1 = new google.maps.InfoWindow({content: contentString_1});
        
        
        var newMarkerFromExtButton = new google.maps.Marker({
            position: latLng,
            title: 'Marker added by external button',
            map: theMap,
            icon: blueMapMarker,
            animation: google.maps.Animation.DROP,
            draggable: false
            });

        newMarkerFromExtButton.setMap(theMap);
        
        // Update current position info.
        updateMarkerPosition(latLng);
        geocodePosition(latLng);
          
        // Add dragging event listeners.
        google.maps.event.addListener(newMarkerFromExtButton, 'dragstart', function() {
        updateMarkerAddress('Dragging...');
        });
          
        google.maps.event.addListener(newMarkerFromExtButton, 'drag', function() {
        updateMarkerStatus('Dragging...');
        updateMarkerPosition(newMarkerFromExtButton.getPosition());
        });
          
        google.maps.event.addListener(newMarkerFromExtButton, 'dragend', function() {
        updateMarkerStatus('Drag ended');
        geocodePosition(newMarkerFromExtButton.getPosition());
        });
        
        //add other listeners
        google.maps.event.addListener(newMarkerFromExtButton, 'click', function() {
        infowindow_1.open(theMap,newMarkerFromExtButton);
        });
        
    }


//reference http://stackoverflow.com/questions/7083264/google-maps-api-v3-set-marker-and-get-point
function placeMarkerByMapClick(position, map) {
    //alert("placeMarker");
    var yellowMapMarker = "http://www.google.com/intl/en_us/mapfiles/ms/micons/yellow-dot.png";
     
    var newMarkerFromMapClick = new google.maps.Marker({
        position: position,
        map: map,
        title: "marker added by map click",
        icon: yellowMapMarker,
        animation: google.maps.Animation.DROP,
        draggable: true
        });
   
    // Update current position info.
    updateMarkerPosition(position);
    geocodePosition(position);
   
     
    // Add dragging event listeners.
    google.maps.event.addListener(newMarkerFromMapClick, 'dragstart', function() {
    updateMarkerAddress('Dragging...');
    });
     
    google.maps.event.addListener(newMarkerFromMapClick, 'drag', function() {
    updateMarkerStatus('Dragging...');
    updateMarkerPosition(newMarkerFromMapClick.getPosition());
    });
     
    google.maps.event.addListener(newMarkerFromMapClick, 'dragend', function() {
    updateMarkerStatus('Drag ended');
    geocodePosition(newMarkerFromMapClick.getPosition());
    });
     
    //next line centers the map on the newly created marker. Disabled since the movement is a bit annoying.
    //map.panTo(position);
    }
     

function addMarkerByTypedCoords()
{
    //alert("addMarker");
    var lat=document.getElementById("lat").value;
    var lon=document.getElementById("lon").value;
   
    var latLng = new google.maps.LatLng(lat, lon);
    //var theMap = google.maps.Map(document.getElementById('mapCanvas'));
    var greenMapMarker = "http://www.google.com/intl/en_us/mapfiles/ms/micons/green-dot.png";
    // Set up our GMarkerOptions object
    markerOptions = { };

    var markerContent =  document.getElementById("markertitle").value;
    var infowindow_1 = new google.maps.InfoWindow({content: markerContent});

    var newMarkerFromTypedCoords = new google.maps.Marker({
        position: latLng,
        title: 'Marker added by typed coordinates',
        map: theMap,
        icon: greenMapMarker,
        animation: google.maps.Animation.DROP,
        draggable: true
        });
   
    newMarkerFromTypedCoords.setMap(theMap);
   
    // Update current position info.
    updateMarkerPosition(latLng);
    geocodePosition(latLng);
   
    // Add dragging event listeners.
    google.maps.event.addListener(newMarkerFromTypedCoords, 'dragstart', function() {
    updateMarkerAddress('Dragging...');
    });
   
    google.maps.event.addListener(newMarkerFromTypedCoords, 'drag', function() {
    updateMarkerStatus('Dragging...');
    updateMarkerPosition(newMarkerFromTypedCoords.getPosition());
    });
   
    google.maps.event.addListener(newMarkerFromTypedCoords, 'dragend', function() {
    updateMarkerStatus('Drag ended');
    geocodePosition(newMarkerFromTypedCoords.getPosition());
    });
   
    //add other listeners
    google.maps.event.addListener(newMarkerFromTypedCoords, 'click', function() {
    infowindow_1.open(theMap,newMarkerFromTypedCoords);
    });
   
    theMap.panTo(latLng);
    }

    
// Onload handler to fire off the app.
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
  <style>
  #mapCanvas {
    width: 800px;
    height: 800px;
    float: left;
  }
  #infoPanel {
    float: left;
    margin-left: 10px;
  }
  #infoPanel div {
    margin-bottom: 5px;
  }
  </style>
 
  <div id="mapCanvas"></div>
 
  <div id="infoPanel">
      <p>NOTE: Marker generated at map initialization is red.</p>
      <hr />
      <h3>Current marker information</h3>
      <b>Marker status:</b>
      <div id="markerStatus"><i>Click and drag the marker.</i></div>
      <b>Current position:</b>
      <div id="info"></div>
      <b>Closest matching address:</b>
      <div id="address"></div>
      <hr />
     
      <h3>Method 1: Add a predefined location marker</h3>
      <p>Marker will be blue. Click the blue marker to get an info window with photo.</p>
      <button onclick="addMarkerByExternalButton()"> Add marker at BSU Stadium</button>
     
      <hr />
      <h3>Method 2: Add new marker from manually entered coordinates</h3>
      <p>Marker will be green</p>
      <form id="typedcoords">
          <fieldset>
          <legend>Type coordinates to add a new marker</legend>
          <label for="lat">Title your new marker:</label>
          <input type="text" name="markertitle" id="markertitle" /><br />
          <label for="lat">Latitude (decimal degrees)</label>
          <input type="text" name="lat" id="lat" /><br />
          <label for="lon">Longitude (decimal degrees)</label>
          <input type="text" name="lon" id="lon" />
          <br />
          <button id="addMarker" title="Add Marker" type="button" onclick="addMarkerByTypedCoords()">Add Marker</button>
          </fieldset>
      </form>
      <hr />
     
      <h3>Method 3: Click map to create new marker</h3>
      <p>Marker will be yellow</p>
      <p>Just click anywhere on the map to create a simple new marker</p>
 
  </div>
</body>
</html>
This example has been tested successfully in Firefox 10 and Safari 5.1 on Mac, and IE and Firefox on Windows XP

References utilized to create this example:

http://code.google.com/apis/maps/documentation/javascript/reference.html

http://code.google.com/apis/maps/documentation/javascript/overlays.html#Markers

http://stackoverflow.com/questions/4236522/google-maps-api-v3-info-window-displaying-same-information-for-all-the-markers

http://code.google.com/apis/maps/documentation/javascript/overlays.html#SimpleIcons

http://groups.google.com/group/google-maps-js-api-v3/browse_thread/thread/5865e223d316b238/e221a5a33c7775d3?pli=1

I'll be working with the GM API for several days, and will likely add more examples as I progress through this project.