0

Im using Google Maps javascript api to show a map full of markers of locations. The markers display but once they are clicked on the console gives the error: "Uncaught TypeError: Cannot read property '0' of undefined" at infowindow.setContent('<div><p>'+locations[i][0]+'</p></div>'); . I found that the problem was the script didn't know what i was. I have tested to this conclusion by substituting i with a number and it works without error. So far I have tried making i a global variable and testing its value as window.i. It still didn't work, but in console it showed its last count. Is there something I'm doing wrong?

function initialize() {
    var locations = [<?php echo $jscript; ?>];

    map = new google.maps.Map(document.getElementById('map-canvas'), {
        zoom: 8,
        center: new google.maps.LatLng(32.639594, -97.117879),
        mapTypeId: google.maps.MapTypeId.ROADMAP
    });

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

    var marker = '';
    var i = 0;
    for (i = 0; i < locations.length; i++) {
        var geocoder_map = new google.maps.Geocoder();
        var addlocat;

        geocoder_map.geocode({'address': locations[i][0]}, function (results, status) {
            if (results) {
                addlocat = results[0].geometry.location;

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

                google.maps.event.addListener(marker, 'click', (function (marker, i) {
                    return function () {
                        infowindow.setContent('<div><p>' + locations[i][0] + '</p></div>');
                        infowindow.open(map, marker);
                    }
                })(marker, i));

            }
        });
    }
}

google.maps.event.addDomListener(window, 'load', initialize);
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
keji
  • 5,947
  • 3
  • 31
  • 47
  • if you fixed that then what is the problem ? if the console displays the latest value of i that is what it is supposed to do unless you zero it out every time you are done with it – CME64 Jun 16 '13 at 07:34
  • You should put the IIFE around the function you pass to `geocoder_map.geocode`, not around the event handler. At this moment it's already too late. Also make `marker` local to the `geocode` callback. – Felix Kling Jun 16 '13 at 07:36
  • OOOOOh you have a major mistake here. you can't use php inside javascript that is server side inside client, it is not allowed, you can use ajax to populate your field from the server – CME64 Jun 16 '13 at 07:36
  • @CME64: I think we can assume that the code is part of a file served thorough PHP. Otherwise the while script would not run (syntax error). – Felix Kling Jun 16 '13 at 07:37
  • 1
    possible duplicate of [Javascript infamous Loop problem?](http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem) and [Javascript closure inside loops - simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example). – Felix Kling Jun 16 '13 at 07:39
  • have you tried making the locations variable global? – klickagent.ch Jun 16 '13 at 07:39
  • @CME64: Its still showing the error despite the log even though the array exists and so does the `i` – keji Jun 16 '13 at 07:39
  • @FelixKling you can't place php code inside the script that's for sure, scripts even don't recognize tags too regardless of the big fact that server-side code cannot reside in client-side .. – CME64 Jun 16 '13 at 07:39
  • @klickagent.ch: Yes I tried that before I posted too. – keji Jun 16 '13 at 07:40
  • @CME64: If the php is echoing javascript then the client side sees no problem – keji Jun 16 '13 at 07:41
  • @CME64: Since the file is served through PHP, the PHP commands are processed first. The result that is sent to the browser could be something like `var locations = [0,2,3];`. There is no problem to "mix" the code as long as you know when and where it is processed. Besides, the OP said *"I have tested to this conclusion by substituting `i` with a number and it works without error."*, so we can assume the problem is not with how `locations` is built. – Felix Kling Jun 16 '13 at 07:41
  • @kdogisthebest try assigning the locations manually and test if that works for you then you only have to use xhtml requests (ajax) read about it here http://www.w3schools.com/ajax/ajax_xmlhttprequest_send.asp or use jquery's ajax for that to get the date from the server into your javascript ( a request from the client-side must be initiated to get the data from the server's) – CME64 Jun 16 '13 at 07:42
  • @FelixKling you mean that the server returns the js code with the values in it ,, that's reasonable .. thanks – CME64 Jun 16 '13 at 07:44
  • @FelixKling If I wanted to rewrite this what would be the best way to structure it? – keji Jun 16 '13 at 07:45
  • 1
    I would create a new function containing everything that is currently inside the loop. Then you simply call the function inside the loop like `geocode(i, locations[i]);`. Then you avoid the loop problem. You might have to pass more arguments (e.g. `infowindow`) or make them global (or better, put them in a shared,higher scope that is not global). But pass `i` and the location directly to the function. You could do the same you did for the event handler as well (as I already mentioned), but splitting up the code into multiple functions would improve readability as well IMO. – Felix Kling Jun 16 '13 at 07:48

1 Answers1

0

Following @FelixKling 's structure I busted out this and it worked first try:

<script>
function initialize() {
      locations = [<?php echo $jscript; ?>];

    map = new google.maps.Map(document.getElementById('map-canvas'), {
      zoom: 8,
      center: new google.maps.LatLng(32.639594, -97.117879),
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    infowindow = new google.maps.InfoWindow();

    var i = 0;
    for (i = 0; i < locations.length; i++) {  
    geocode(i, locations[i])
   }
}

function geocode(i, location){
    var geocoder_map = new google.maps.Geocoder();
    var addlocat;

    geocoder_map.geocode( { 'address': location[0]}, function(results, status) {
            if(results){
            addlocat = results[0].geometry.location; 

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

      google.maps.event.addListener(marker, 'click',
        return function() {
          infowindow.setContent('<div><p>'+location[0]+'</p></div>');
          infowindow.open(map, marker);
        });
      }
    });
}

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

    </script>
keji
  • 5,947
  • 3
  • 31
  • 47
  • Inside `geocode`, make `marker` local (`var marker = ...;`) and then you can remove the `(function(marker, i) {....}) (marker, i)` part around the event handler. – Felix Kling Jun 16 '13 at 09:47
  • Also, you don't actually use `i` in the `geocode()` function, so no need to pass it in as a parameter. – Michael Geary Jun 16 '13 at 10:26