My kayaking/hiking/biking trips log page uses Google Maps to show a log of “all” trips I’ve taken on foot, biking, or kayaking. I started the log just for kayaking so it is missing all of my bike rides from the first decade that I lived at Lake Tahoe.

I occasionally work on the code for the page and I was recently trying to get the info box to pop up at the right time after clicking on a route. The “right” time is the moment after the map has scrolled and zoomed the route into the center of the screen with the zoom making the route entirely visible.

The problem with the Google Maps API is that it doesn’t always provide functions for what you need. I need to call the FitBounds() function and then have the Google code tell me when any panning and zooming has finished. I can certainly set up a function of mine that will get called when the map code becomes “idle”. But if the map doesn’t change then the map never becomes idle because it already was idle. I searched for and tested many ways to accomplish this. I even asked ChatGPT what to do. Alas, not even the venerable ChatGPT provided a good solution. But all of the tries did lead me to piece together something that seems to work quite well.

	bounds = new google.maps.LatLngBounds();
	var poly = trips[whichtrip].VisiblePolyline.getPath();
	var len = poly.getLength();
	for( var Index=0; Index < len; Index++ ) {
		bounds.extend( poly.getAt( Index ) );
	}
	
	infowindow.close();
	
	// Change the center slightly to get an idle event if the bounds are not changing.
	var currentCenter = map.getCenter();
	var newCenter = { lat: currentCenter.lat() + 0.00001, lng: currentCenter.lng() };
	map.setCenter( newCenter );
	
	// Wait a millisecond and then set the new bounds.
	setTimeout( function() {
		map.addListener('idle', function() {
			google.maps.event.clearListeners(map, 'idle');
			infowindow.open( { shouldFocus: false, map } );
		});
		map.fitBounds( bounds, 55 );
	}, 1 );

The code above is what I ended up using. This is part of a larger piece of code that does some other work so it is not shown as a complete function.

This code steps through a set of GPS coordinates and calculates map bounds from them. It then ensures that a previously visible info window is hidden before altering the center of the map. Then a delay is created using the setTimeout() function so the map can change before the new map bounds are used. Inside the callback function from the delay is where a bit of code is set up to be called when the “idle” event happens. Finally, the bounds are changed to the new bounds. Once any panning and zooming are complete, the map becomes idle and the callback function is called; it then shows the info window.

The problem I encountered before was when the map was already showing a specific route. Picking the same bounds again would cause nothing to happen and since the map was idle to start with, the idle callback function was never called; That function is only called when the map changes from not-idle to idle. By moving the center of the map a tiny bit, the Google map code seems to always do some amount of pan to get the map centered in the correct location. Interestingly, the new bounds after the map becomes idle are not identical, from what I could tell, from the requested bounds. The Google code is deciding itself what bounds are close to those that are desired and yet meet some other criteria. Perhaps the map can only be centered on even latitudes; That’s a bit absurd but there must be something like that happening or this new code would not always work. It does seem to always work!

Another recent change was to add multiple overlapping polylines (a polyline being a chained set of line segments forming a route) so that there is a white border on all of them. There is also a mostly invisible polyline that is very wide so it’s not necessary to click exactly on the line to select it. Clicking on the wider “invisible” line works too.

Finally, I did a little bit of cheating and found out what classes Google uses for parts of the info window. I hide the little pointy bit that would hang down from the info window because I center the info window on the route – it’s not really pointing at the start, finish, or any part of the route line along the path. I do think it’s weird that Google doesn’t make this stuff more customizable. A few options here and there would be nice instead of having to hack together something that could break in the future.

The trip log page is here: https://www.rectorsquid.com/kayaking.php