Joe, the problem is that your code has a single variable "i". At any point
in time, when you reference that variable you will get the *current* value
of "i".

While the for loop is running, "i" gets each of the values you expect. But
when is your callback function called? Much later, *after* the loop has
finished running. At this point "i" has the last value it was given in the
loop, 150.

(Note that your loop does not run from 1 through 150, but 1 through 149. The
last time through the loop, the value is 149, and then when the value
reaches 150 the loop terminates - so "i" is 150 after that.)

Then why is the marker created at the correct location? Because the
searchAddress geocoding function calls the callback with "point" set
correctly. But "i" is your own variable, and there's only one copy of it for
the entire program.

The easiest way to fix this is usually to use a closure. You could code it
like this:

jQuery(function( $ ) {
    
    var $map2 = $('#map2');
    
    $map2.jmap({
            mapCenter:[30.2687,-97.7452],
            mapZoom: 13
    });
    
    for( i = 1; i < 150; i++ )
        createMarker( i );
    
    function createMarker( i ) {
        $map2.jmap("searchAddress", { address :$('#address'+i).val() },
function(options,point) {
            $map2.jmap("addMarker", {
                pointLatLng: [point.y, point.x],
                pointHTML: "<div style='width:200px;'><p>This office is
located at:</p><p><b>" + $('#address'+i).val() + "</p></div>" ,
                centerMap: false
             });
         });
    }

}); // End of DOM Ready

The only real change to the code here is the addition of the createMarker()
function. This function is called each time through your loop, and each time
it's called it gets its *own* local variable, also named "i". (It isn't
significant that this name "i" is the same name as the "i" outside the
function - they are two different variables and could have different names.)

So, when the searchAddress callback is called, it's using the local "i"
inside that particular instance of the createMarker function, which will be
the value you expect.

I took the liberty of making a couple of unrelated changes to the code, just
to illustrate some recommended coding techniques - in particular, the use of
the $map2 variable instead of calling the jQuery function $('#map2') every
time through the loop. Any time you can move something outside a loop
instead of calling it repeatedly, it will help performance.

One thing I didn't fix is the hard coded value of 150 (or 149). You probably
don't want to just hard code this - what happens when you open another
office? :-)

HOWEVER...

All that said, there is a much worse problem with the code, one that we
can't fix here.

The Google client geocoder is limited to 15,000 queries per day per API key.
At 150 per visit, you are going to hit that limit as soon as your page is
visited (or reloaded) 100 times. Then you will be blocked from further
geocoding requests, typically for 24 hours.

Even before you hit the limit, geocoding 150 locations is going to take a
while.

There's no way to fix this in JavaScript. Instead, you need to geocode all
of your locations ahead of time, save them in a database or a file on your
server, and code those latitude/longitude points into your HTML/JavaScript.
This will eliminate all the need for geocoding on the client. Your map will
load *much* faster, and you won't have to worry about the geocoder API
limit.

-Mike

> From: Joe
> 
> Check the following code:
> 
> $j = jQuery;
> 
> $j().ready(function()
> {
> 
> $j('#map2').jmap({
>                 mapCenter:[30.2687,-97.7452],
>                 mapZoom: 13
>         });
> 
>         for(i=1; i < 150; i++)
>         {
> 
>              $j('#map2').jmap("searchAddress", {address:
> $j('#address'+i).val() }, function(options,point)
>                   {
>                        $j('#map2').jmap("addMarker", {
>                                         pointLatLng:[point.y, 
> point.x],
>                                         pointHTML: "<div style='width:
> 200px;'><p>This office is located at:</p><p><b>" +
> $j('#address'+i).val() + "</p></div>" ,
>                                         centerMap: false
>                                 });
>                 });
> 
>         }
> 
> }); // End of DOM Ready
> 
> In the markup there are 150 like these:
> 
> // "N" represents a number from 1 to 150
> 
> <input type="hidden" id="addressN" value="123 Main Street New 
> York, NY 10101" />
> 
> 
> Now when I throw in some alerts I notice that the 2nd 
> function (the callback function) actually places the proper 
> point, but does NOT produce the proper HTML; for each point 
> that is place the comment bubble has the address of the LAST 
> point that was placed on the map.  Why would it place the 
> point in the proper iteration, but not the associated HTML?

Reply via email to