// GAsync v2 by Michael Geary
// https://mg.to/2007/06/22/write-the-same-code-for-google-mapplets-and-maps-api
// Free beer and free speech license. Enjoy!
//
// Call one or more xyzAsync() functions from the Google
// Mapplet API, with a single callback that receives the
// values from all of the called functions. The first argument
// to GAsync is the object to be used. The next arguments
// are each of the function names, without the 'Async'
// suffix. The last argument is the callback function.
// To call xyzAsync() functions for more than one object,
// list another object in the argument list and the function
// names after that will use that object.
// To call an xyzAsync() function that takes arguments of
// its own (other than the callback argument), place an
// array of those arguments after the function name in
// GAsync's argument list.
// Example calls, given existing map and marker objects
/*
// Get the size, bounds, and center of the map
GAsync( map, 'getSize', 'getBounds', 'getCenter',
function( size, bounds, center ) {
// ...
});
// Get the zoom level, size, bounds, and center for
// the map, as well as the lat/long of the top left
// corner of the map. Also get the point and icon
// for marker.
GAsync(
map, 'getZoom', 'getSize', 'getBounds', 'getCenter',
'fromContainerPixelToLatLng', [ new GPoint(0,0) ],
marker, 'getPoint', 'getIcon',
function( zoom, size, bounds, center, topleft, point, icon ) {
// ...
});
// Equivalent code using nested xyzAsync calls:
map.getSizeAsync( function( size ) {
map.getBoundsAsync( function( bounds ) {
map.getCenterAsync( function( center ) {
// ...
});
});
});
map.getZoomAsync( function( zoom ) {
map.getSizeAsync( function( size ) {
map.getBoundsAsync( function( bounds ) {
map.getCenterAsync( function( center ) {
map.fromContainerPixelToLatLngAsync( new GPoint(0,0), function( topleft ) {
marker.getPointAsync( function( point ) {
marker.getIconAsync( function( icon ) {
// ...
});
});
});
});
});
});
});
*/
function GAsync( obj ) {
// Call the callback function provided in the GAsync() call
function callback
() {
args[nArgs].apply( null, results );
}
// Queue a single xyzAsync() function call.
// 'iResult' is the index into the final results array.
// 'name' is the name of the Maps API function without
// the Async suffix.
// 'next' is the next argument to GAsync following name;
// If next is an array, it contains the arguments to be
// passed to xyzAsync().
function queue( iResult, name, next ) {
// Callback for the xyzAsync() function that was called
// by this invocation of the queue() function.
// value is the return value from the Maps API.
function ready
( value
) {
// Save the result in the final results array
results[iResult] = value;
// If every async function has completed, call the
// GAsync callback (in the last argument to GAsync)
// with the final results array as its arguments.
if( ! --nCalls
)
callback();
}
// Arguments array for the xyzAsync() call
var a = [];
// If 'next' is an array, it contains arguments to
// be passed to xyzAsync()
if( next.join ) // Arrays have .join, strings do not
a = a.
concat(next
), ++iArg;
// append and skip
// Call xyzAsync() in a mapplet or xyz() in the Maps API
if( mapplet ) {
// The callback for xyzAsync is its last argument
a.push( ready );
// Call xyzAsync() with arguments in 'a'
obj
[ name+
'Async' ].
apply( obj, a
);
}
else {
// Maps API, call xyz() and save its return value
results
[iResult
] = obj
[name].
apply( obj, a
);
}
}
// Is this is a mapplet or the Maps API?
var mapplet = ! window.GBrowserIsCompatible;
// 'args' is a reference to GAsync's arguments array
// that can be used in the nested functions.
// 'nArgs' is is the number of arguments, not counting
// the callback function at the end. (Thus, args[nArgs]
// is a reference to the callback function.)
var args = arguments, nArgs = args.
length -
1;
// 'results' is the final results array for the callback. It
// will be populated from the individual ready() callbacks.
// 'nCalls' is the total number of xyzAsync() calls. It is
// incremented as those calls are queued, and then
// decremented to discover when all the calls are done.
var results = [], nCalls = 0;
// Loop through GAsync()'s arguments, starting at
// the first function name (after 'obj'), and ending
// before the callback function.
for( var iArg =
1; iArg < nArgs; ++iArg
) {
// Get the name of the function to be called
var name = args[iArg];
// If the argument is an object, not a name,
// switch to that object for subsequent calls.
// If it is a name, count and queue the function.
if( typeof name ==
'object' )
obj = name; // change object
else
queue( nCalls++, name, args[iArg+1] );
}
// If using the Maps API, call the callback now
if( ! mapplet )
callback
();
}