0

I have json data, i want to display LatLng data on map. Now the given LatLng was displayed on map but I am not getting infoWindow when i click, please help. I have attaced my code below : here is my script tag. Please suggess me how to do this, once again thank you

<script>
    var obj  = {
        "location": [
            {
                "street_address": {
                    "city": "Trichy",
                    "state": "TamilNadu",
                    "address_1": "Test address",
                    "country": "India"
                },
                "gps": {
                    "latitude": 32.67,
                    "longitude": -85.44
                }
            },
            {
                "street_address": {
                    "city": "Madurai",
                    "state": "TamilNadu",
                    "address_1": "Test address",
                    "country": "India"
                },
                "gps": {
                    "latitude": 28.65859029,
                    "longitude": 77.22063432
                }
            },
            {
                "street_address": {
                    "city": "Chennai",
                    "state": "TamilNadu",
                    "address_1": "Test address",
                    "country": "India"
                },
                "gps": {
                    "latitude": 67.1,
                    "longitude": -157.85
                }
            },
            {
                "street_address": {
                    "city": "Combiatore",
                    "state": "TamilNadu",
                    "address_1": "Test address",
                    "country": "India"
                },
                "gps": {
                    "latitude": 52.67,
                    "longitude": -95.44
                }
            },
            {
                "street_address": {
                    "city": "Tirunelveli",
                    "state": "TamilNadu",
                    "address_1": "Test address",
                    "country": "India"
                },
                "gps": {
                    "latitude": 25.9,
                    "longitude": -97.43
                }
            }
        ]
    };
    var place = [];
    var locations = [];
    for(var i = 0; i < obj["location"].length;i++){
        //var data = {"latitude" : 0, "longitude" : 0};   
        //data["latitude"] = obj["location"][i]["gps"]
        locations.push(obj["location"][i]["gps"]);
        place.push(obj["location"][i]["street_address"]);
    }

    console.log(place);
    console.log(locations);
    var pointer = new google.maps.LatLng(51.508742,-0.120850);
    function intialize(){
        var mapOption = {
            zoom : 3,
            center : pointer,
            mapTypeControl:true,
            mapTypeControlOptions: {
                style:google.maps.MapTypeControlStyle.DROPDOWN_MENU
            },
            mapTypeId: google.maps.MapTypeId.ROADMAP            
        };
        var map = new google.maps.Map(document.getElementById("map-canvas"),mapOption);         
        for(var i = 0; i < locations.length; i++){
            var marker = new google.maps.Marker({
                position: new google.maps.LatLng(locations[i]["latitude"], locations[i]["longitude"]),              
                icon: 'map-icon.png'
            });
            marker.setMap(map); 
            console.log(locations[i]["latitude"], locations[i]["longitude"]);       
        }
        for(var i = 0;i < place.length; i++){
            var infoWindow = new google.maps.InfoWindow({
                content : new google.maps.InfoWindow(place[i]["address_1"], place[i]["city"],place[i]["country"],place[i]["state"])
            });
            google.maps.event.addListener(marker, 'click', function(){
                infoWindow.open(map, marker);
            });
            console.log(place[i]["address_1"], place[i]["city"],place[i]["country"],place[i]["state"]); 
        }                   
    }
    google.maps.event.addDomListener(window, 'load', intialize);
</script>
hennes
  • 9,147
  • 4
  • 43
  • 63
Vijaykarthik
  • 333
  • 4
  • 10
  • 25
  • can you add more detail to the question, if you are getting any error or unexpected values in any of the variables... – Vishwanath Aug 28 '14 at 11:37
  • Actually my doubt is, i am not getting infowindow when i click the map icon. for test i keep console.log(place[i]["address_1"], place[i]["city"],place[i]["country"],place[i]["state"]); on my code. In browser im getting "InvalidValueError: setContent: not a string; and [object Object]" – Vijaykarthik Aug 28 '14 at 11:41
  • I have json data, I am trying json value to get on the google map. I am getting marker with the given latLng from json data. But i am not getting Infowindow when i click on the map icon. So far i tryed so was to solve this problem, i am not getting the answer. I have attached my code above this page. Please give some idea.....I am new to Javascript. – Vijaykarthik Aug 28 '14 at 12:00
  • possible duplicate of [Google Maps JS API v3 - Simple Multiple Marker Example](http://stackoverflow.com/questions/3059044/google-maps-js-api-v3-simple-multiple-marker-example) – geocodezip Aug 28 '14 at 13:46

2 Answers2

1

There are multiple issues with your code.

The for Loops

In the second for loop where you're iterating over the place array you're accessing the variable marker and expect it to be the place's marker. The marker variable is, however, only updated in the for loop before where you're iterating over the locations array.

for(var i = 0; i < locations.length; i++){
    var marker = new google.maps.Marker(...);
    ...
}
for(var i = 0;i < place.length; i++){
    ...
    google.maps.event.addListener(marker, ...);
    // Here marker will always be the last marker that
    // was created in the preceding loop
}

To correct this, combine the two loops.

for(var i = 0; i < locations.length; i++){
    var marker = new google.maps.Marker(...);
    ...
    google.maps.event.addListener(marker, ...);
    // Here marker will be the current location's marker
}

The InfoWindow Constructor

You're not calling the google.maps.InfoWindow constructor correctly since you're specifying another InfoWindow for the contentparameter.

var infoWindow = new google.maps.InfoWindow({
    content : new google.maps.InfoWindow(...)
});

The API does, however, expect content to be a string (plain text or HTML) containing, guess what, the info window's content.

var infoWindow = new google.maps.InfoWindow({
    content : '<div>Hello, I am an info window</div>'
});

The for Loop's Scope

Finally, the for loop does not create a new scope that means the current values of your local variables (like marker) are not wrapped with the click event-handler. Hence, accessing those variables in the handler function will yield their values after the for loop has finished.

for(var i = 0; i < locations.length; i++){
    var marker = new google.maps.Marker(...);
    ...
    google.maps.event.addListener(marker, 'click', function(){
        infoWindow.open(map, marker);
        // At the time of click the for loop has finished.
        // Thus, marker will be the last marker that was created in the loop.
    });
}

You can work around this by wrapping the handler in a function closure. Oh and, by the way, you'll only need a single instance of InfoWindow.

var infoWindow = new google.maps.InfoWindow();

for(var i = 0; i < locations.length; i++){
    var marker = new google.maps.Marker(...);
    ...
    google.maps.event.addListener(marker, 'click', (function(marker, i){
        return function() {
            infoWindow.close();
            infoWindow.setContent("<div>" + place[i]["city"] + "</div>");
            infoWindow.open(map, marker);
            // You could also use this instead of marker here but you'll
            // still need the closure for i
        }
    })(marker, i)); // Pass in marker and i to make the closure work
}

Wrapping Up

A somewhat simplified version of your corrected initialize function looks like this (JSFiddle).

function intialize(){
    var mapOption = {
        zoom : 3,
        center : pointer,
        mapTypeControl:true,
        mapTypeControlOptions: {
            style:google.maps.MapTypeControlStyle.DROPDOWN_MENU
        },
        mapTypeId: google.maps.MapTypeId.ROADMAP            
    };
    var map = new google.maps.Map(document.getElementById("map-canvas"),mapOption);         

    var infoWindow = new google.maps.InfoWindow();

    for(var i = 0; i < locations.length; i++){
        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(locations[i]["latitude"], locations[i]["longitude"])
        });
        marker.setMap(map); 

        google.maps.event.addListener(marker, 'click', (function(marker, i){
            return function() {
                infoWindow.close();
                infoWindow.setContent("<div>" + place[i]["city"] + "</div>");
                infoWindow.open(map, this);
            }
        })(marker, i));
    }                   
}

google.maps.event.addDomListener(window, 'load', intialize);
hennes
  • 9,147
  • 4
  • 43
  • 63
  • Thanks for the detailed answer.. Will help the op very much... I need to check my closure understanding again.. I thought when the outer function executes the value of i gets closed inside the inner function which gets returned. Maybe that's not the case.... – Vishwanath Aug 28 '14 at 20:17
  • Got it. This question just made my understanding of closure more concrete. Even though is closed inside the inner function it's value is still getting increased in the for loop. This can be overcome by copying them in some other variables by means of arguments. Maybe I knew this all along.. Just got out of the hand in rushing... Should take care of not answering the question when u r in rush... – Vishwanath Aug 28 '14 at 20:21
0

Only copying the relevant code here. I have changed the place of infoWindow marker instance creation. Each infoWindow object will be attached to marker due to closure. Check if this is working for you.

function intialize(){
    var mapOption = {
        zoom : 3,
        center : pointer,
        mapTypeControl:true,
        mapTypeControlOptions: {
            style:google.maps.MapTypeControlStyle.DROPDOWN_MENU
        },
        mapTypeId: google.maps.MapTypeId.ROADMAP            
    };
    var map = new google.maps.Map(document.getElementById("map-canvas"),mapOption);         
    for(var i = 0; i < locations.length; i++){
        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(locations[i]["latitude"], locations[i]["longitude"]),              
            icon : 'map-icon.png'
        });
        marker.setMap(map); 
        google.maps.event.addListener(marker, 'click', (function(){
            return function(){
                var infoWindow = new google.maps.InfoWindow({
                    content : new google.maps.InfoWindow(place[i]["address_1"], place[i]["city"],place[i]["country"],place[i]["state"])
                });
                infoWindow.open(map, marker);
            }
        })());
    }
}
Vishwanath
  • 6,284
  • 4
  • 38
  • 57
  • Thanks for you reply brother. But i am still not get the answer. Now when i click map icon i am getting error like this "place[i] is undefined"...Can u help. – Vijaykarthik Aug 28 '14 at 13:08
  • Give me a min. I just found out that problem and was updating the answer. – Vishwanath Aug 28 '14 at 13:09
  • @Vishwanath You're not calling the `InfoWindow` constructor correctly. In addition, you need to pass in `marker` and `i` as arguments to the click-handler closure. Otherwise, the closure is useless. – hennes Aug 28 '14 at 20:00