Forum Moderators: open

Message Too Old, No Replies

Google Maps help

         

gosman

12:25 pm on Oct 10, 2009 (gmt 0)

10+ Year Member



Hi, I hope I'm posting n the correct forum.

I'm trying to create a map with several points that gets centered and zoomed automatically so all markers are visible. I've successfully managed to accomplish this.

My next problem is being able to open an info window for each marker. I've tried using the code below, but when I click on the marker the info window always opens on one particular marker.

Can anybody tell me where I'm going wrong?

<script type="text/javascript">
var map1;
var latlng1 =
[
new GLatLng(40.70535,-74.01714),
new GLatLng(40.76575,-73.97629),
];

function map1_initialize( )
{
if ( GBrowserIsCompatible( ) )
{
map1 = new GMap2( document.getElementById( 'map1div' ) );
map1.addControl( new GSmallMapControl( ) );
map1.addControl( new GMenuMapTypeControl( ) );
map1.setCenter( new GLatLng( 0, 0 ), 0 );
for ( var i = 0; i < latlng1.length; i++ )
{
var marker = new GMarker( latlng1[ i ] );

GEvent.addListener
(

marker, 'click', function()
{
marker.openInfoWindowHtml('<p>Test</p>');
}
);

map1.addOverlay( marker );
}
var latlngbounds = new GLatLngBounds( );
for ( var i = 0; i < latlng1.length; i++ )
{
latlngbounds.extend( latlng1[ i ] );
}
map1.setCenter( latlngbounds.getCenter( ), map1.getBoundsZoomLevel( latlngbounds ) );
}
}
GEvent.addDomListener( window, 'load', map1_initialize );
</script>

gosman

3:56 pm on Oct 10, 2009 (gmt 0)

10+ Year Member



<bump>anyone?</bump>

rocknbil

6:38 pm on Oct 10, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Bump three hours later? Hey it's Saturday man, most people are doing **fun** stuff! :-)

I've have this exact same problem and while I consider myself "pretty good" with Javascript was never able to solve it, "marker" always stuck on one info window. So I resorted to slightly bloating my code with the following workaround, creating a new var for each instance:


for (i=0;i<2;i++) {
maps[i] = new GMap2(document.getElementById(obj[i]));
maps[i].addControl(new GSmallMapControl());
maps[i].setCenter(new GLatLng(coordX[i],coordY[i]), 15);

if (i==0) {
mk1= new GMarker(maps[i].getCenter(),icon);
GEvent.addListener(mk1, "click", function() {
mk1.openInfoWindowHtml(html[0],{maxWidth:infoWinWidth});
});
maps[i].addOverlay(mk1);
mk1.openInfoWindowHtml(html[0],{maxWidth:infoWinWidth});
}
else {
mk2= new GMarker(maps[i].getCenter(),icon);
GEvent.addListener(mk2, "click", function() {
mk2.openInfoWindowHtml(html[1],{maxWidth:infoWinWidth});
});
maps[i].addOverlay(mk2);
mk2.openInfoWindowHtml(html[1],{maxWidth:infoWinWidth});
}
}

I played around with eval(), tweaked it a couple different ways until I just got tired of pounding the square peg. A definitive solution from others would be great . . . .

astupidname

10:00 pm on Oct 10, 2009 (gmt 0)

10+ Year Member



My next problem is being able to open an info window for each marker. I've tried using the code below, but when I click on the marker the info window always opens on one particular marker.

Can anybody tell me where I'm going wrong?


Yes, I believe so... you are running in to a problem with closures in javascript, it has some quirks this way. The problem is within the first 'for' loop in your map1_initialize function. I may have difficulty explaining it in an easy to understand way, depends how much experience you have had with closure issues in past or not, but here are some notes on the problem in the first for loop:
for (var i = 0; i < latlng1.length; i++) {
var marker = new GMarker(latlng1[i]); /***once this for loop is done running, the reference to marker variable in the anonymous function passed to addListener will always 'point' to the last marker variable created in this loop***/
GEvent.addListener(marker/***right here, marker is evaluated each time by the addListener method, so each creation of marker in the loop here does get an onclick event attached***/, 'click', function() {
marker.openInfoWindowHtml('<p>Test</p>'); /***the reference to 'marker' here in the anonymous function which is passed to addListener will always (later on) refer to the last marker variable created in this for loop, thus the reason only one of the markers 'pops up' regardless of which one is clicked. You can confirm this in your current set-up by changing the string passed to marker.openInfoWindowHtml to: ('<p>Test, i = ' + i + '</p>'), and it will always in this case show i = 2 (2 is i's final value after for loop has finished running)***/
});
map1.addOverlay(marker);
}

There are a couple ways one can go about getting around the problem, simplest fix is below (even with anonymous function calls, each invokation is a seperate event and maintains seperate 'hidden pointers' to variables used within them), replace the first 'for' loop with the following:

for (var i = 0; i < latlng1.length; i++) {
(function () { /***making use of a closure here, each invokation of this function will hold it's own marker to be referenced later***/
var marker = new GMarker(latlng1[i]);
GEvent.addListener(marker, 'click', function() {
marker.openInfoWindowHtml('<p>Test</p>');
});
map1.addOverlay(marker);
})();
}

gosman

2:14 pm on Oct 11, 2009 (gmt 0)

10+ Year Member



Thanks guys.

astupidname you solution worked brilliant, thank you very much for your help.

gosman

3:15 pm on Oct 11, 2009 (gmt 0)

10+ Year Member



Spoke to soon.

I also need to pass a variable to the openInfoWindowHtml

This is what I've tried (among other things) but it doesn't seem to work, just getting a blank info window.

<script type="text/javascript">
var map1;

var latlng1 =
[
new GLatLng(40.70535,-74.01714),
new GLatLng(40.76575,-73.97629),
];

var html1 =
[
'window1 informatiom',
'window2 informatiom',
];
function map1_initialize( )
{
if ( GBrowserIsCompatible( ) )
{
var icon = new GIcon();
icon.image = "/images/hotel.png";
icon.shadow = "/images/hotelshadow.png";
icon.iconSize = new GSize(20, 34);
icon.shadowSize = new GSize(37, 34);
icon.iconAnchor = new GPoint(9, 34);
icon.infoWindowAnchor = new GPoint(9, 2);

map1 = new GMap2( document.getElementById( 'HotelMap' ) );
map1.addControl( new GSmallMapControl( ) );
map1.addControl( new GMenuMapTypeControl( ) );
map1.setCenter( new GLatLng( 0, 0 ), 0 );

for (var i = 0; i < latlng1.length; i++) {
(function () { /***making use of a closure here, each invokation of this function will hold it's own marker to be referenced later***/
var marker = new GMarker(latlng1[i],icon);
GEvent.addListener(marker, 'click', function() {
marker.openInfoWindowHtml(html1[i]);
});
map1.addOverlay(marker);
})();
}
var latlngbounds = new GLatLngBounds( );
for ( var i = 0; i < latlng1.length; i++ )
{
latlngbounds.extend( latlng1[ i ] );
}
map1.setCenter( latlngbounds.getCenter( ), map1.getBoundsZoomLevel( latlngbounds ) );
}
}
GEvent.addDomListener( window, 'load', map1_initialize );
</script>

astupidname

4:33 pm on Oct 11, 2009 (gmt 0)

10+ Year Member



Hi again, gosman, and you are welcome. You are still having trouble with the html aspect of the infoWindow's contents because the html to be used must be assigned, before passing the function to GEvent.addListener, either to a variable or to an object. A re-work with a few other small changes (no need for the extra global variables hanging out there, and what's happening in the second for loop can be accomplished within the first for loop):
<script type="text/javascript">
var map1;

function map1_initialize() {
if (GBrowserIsCompatible()) {
//don't really need two different arrays, just one multi-dimensional array is a bit more organized
var latlng1 = [
[new GLatLng(40.70535,-74.01714), 'window1 information'],
[new GLatLng(40.76575,-73.97629), 'window2 information'] //<--> note never a comma after last item in an array or object!
];
var latlngbounds = new GLatLngBounds();
var icon = new GIcon();
icon.image = "/images/hotel.png";
icon.shadow = "/images/hotelshadow.png";
icon.iconSize = new GSize(20, 34);
icon.shadowSize = new GSize(37, 34);
icon.iconAnchor = new GPoint(9, 34);
icon.infoWindowAnchor = new GPoint(9, 2);
map1 = new GMap2(document.getElementById('HotelMap'));
map1.addControl(new GSmallMapControl());
map1.addControl(new GMenuMapTypeControl());
map1.setCenter(new GLatLng(0,0), 0);
for (var i = 0; i < latlng1.length; i++) {
(function () {
var marker = new GMarker(latlng1[i][0],icon);
var html = latlng1[i][1];
GEvent.addListener(marker, 'click', function() {
marker.openInfoWindowHtml(html);
});
map1.addOverlay(marker);
latlngbounds.extend(latlng1[i][0]);
})();
}
map1.setCenter(latlngbounds.getCenter(), map1.getBoundsZoomLevel(latlngbounds));
}
}

GEvent.addDomListener(window, 'load', map1_initialize);

</script>

And actually, I've come to realize the function wrapper which I showed you before within the for loop isn't really needed in this case either, could also do the for loop like the following, attach the html to the marker object, and within the function passed to GEvent.addListener the 'this' keyword will refer to the currently active marker:

for (var i = 0; i < latlng1.length; i++) {
var marker = new GMarker(latlng1[i][0],icon);
marker.html = latlng1[i][1]; //attach the marker's html to it
GEvent.addListener(marker, 'click', function() {
this.openInfoWindowHtml(this.html); //'this' here will refer to the currently activated marker object
});
map1.addOverlay(marker);
latlngbounds.extend(latlng1[i][0]);
}

gosman

4:43 pm on Oct 11, 2009 (gmt 0)

10+ Year Member



astupidname you're a gentleman. Works a treat.

Just got my head around PHP, now I need to start brushing up on javascript. Does it ever end?

whoisgregg

10:54 pm on Oct 11, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Just got my head around PHP, now I need to start brushing up on javascript. Does it ever end?

Speaking as a WebmasterWorld member who went down the same path, no. As your knowledge increases, the complexity of new projects will typically be just past what you already know.

But it keeps things fun. ;)