google map info window multiple addresses via xml

I’m using the Google map code below to retrieve and plot markers for multiple addresses from an XML file dynamically created with PHP. The code is doing everything I need except for displaying the correct information in the Google map info window for the corresponding marker. I get the information of the last XML item/listing for all the markers.

I’ve been searching and trying different variations to get it to work, but no luck.

sample XML data

<?xml version="1.0" encoding="UTF-8"?>
<listings>
<listing>
    <address>123 Street</address>
    <city>MANOTICK</city>
</listing>
<listing>
    <address>456 Street</address>
    <city>MANOTICK</city>
</listing>
<listing>
    <address>111 Avenue</address>
    <city>MANOTICK</city>
</listing>
<listing>
    <address>777 Avenue</address>
    <city>Ottawa</city>
</listing>
<listing>
    <address>333 Street</address>
    <city>Manotick</city>
</listing>
</listings>

google map code

function initialize ()
{
    var myLatLng = new google.maps.LatLng(45.2340684, -75.6287287);
    var myOptions =
    {
        zoom: 10,
        mapTypeControl: true,
        center: myLatLng,
        zoomControl: true,
        zoomControlOptions:
        {
            style: google.maps.ZoomControlStyle.SMALL
        },
        StreetViewControl: false,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    var map = new google.maps.Map(document.getElementById('google_map'), myOptions);
    var info_window = new google.maps.InfoWindow;
    google.maps.event.addListener
    (map, 'click',
    function ()
    {
        info_window.close();
    });


    downloadUrl
    ('listings.xml',
    function (listings_data)
    {
        var markers = listings_data.documentElement.getElementsByTagName('listing');
        var geocoder = new google.maps.Geocoder();
        for (var i = 0; i < markers.length; i++)
        {
            var address = markers[i].getElementsByTagName('address')[0].firstChild.data;
            var city = markers[i].getElementsByTagName('city')[0].firstChild.data;
            var address_google_map = address + ', ' + city + ', ON';
            var info_text = address + '<br />' + city + ' ON';

            geocoder.geocode
            ({'address': address_google_map},
            function (results)
            {
                    var marker = new google.maps.Marker
                    ({
                        map: map, 
                        position: results[0].geometry.location
                    });
                    google.maps.event.addListener
                    (marker, 'click',
                    function()
                    {
                        info_window.setContent(info_text);
                        info_window.open(map, marker);
                    });
            });
        }
    });
}

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

You have a problem with the asynchronous nature of the geocoder, and if you add many addresses you will have a problem with the geocoder quota/rate limits (particularly since your code doesn’t look at the return status of the geocoder).

All these questions are related:

The simplest solution is to use function closure to associate the call to the geocoder with the returned result:

geocodeAddress(xmldata)
{
        var address = xmldata.getElementsByTagName('address')[0].firstChild.data;
        var city = xmldata.getElementsByTagName('city')[0].firstChild.data;
        var address_google_map = address + ', ' + city + ', ON';
        var info_text = address + '<br />' + city + ' ON';

        geocoder.geocode
        ({'address': address_google_map},
        function (results, status)
        {
          if (status == google.maps.GeocoderStatus.OK) {
            createMarker(results[0].geometry.location, info_text);
          } else { 
            alert("geocode of "+ address +" failed:"+status);
          }
        });
    }

And a createMarker function to associate the infowindow content with the marker:

function createMarker(latlng, html)
{
  var marker = new google.maps.Marker
                ({
                    map: map, 
                    position: latlng
                });
  google.maps.event.addListener(marker, 'click', function() {
                    info_window.setContent(html);
                    info_window.open(map, marker);
                });
}

Makes your for loop:

for (var i = 0; i < markers.length; i++)
{
  geocodeAddress(markers[i]);
}

Working example

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply