I've had issues with this approach Google has taken also. I don't like it very much myself.
My way to deal with this as of late has been creating the global function, with a twist of firing an event to trigger my actual application javascript. This way I have my application JS clean of dealing the maps API handling, and it's one small global function call outside of my main object.
function initMap(){
$(document).ready(function(){
$(window).on('GoogleMapsLoaded', myObj.init());
$(window).trigger('GoogleMapsLoaded');
});
};
With that I just include the callback=initMap
in the script url.
UPDATE: Another option is to just include your callback as a function inside your object. Ex: your object could be something like
var app = app || {};
(function($){
$(function(){
$.extend(app, {
initMap:function(yourMainWrapDiv){
//Do whatever you need to do after the map has loaded
},
mapLoadFunction(){
//Map API has loaded, run the init for my whole object
this.initMap($('#mainWrapper'))
},
mainInit: function(){
///do all your JS that can or needs
// to be done before the map API loads
this.maybeSetSomeBindings();
},
maybeSetSomeBindings: function(){
//do things
}
});
//On document ready trigger your mainInit
//To do other things while maps API loads
app.mainInit()
});
})(jQuery);
Then you can just use the callback to jump inside your one global object and run what you need to run just for the map handling. Your API url could be with callback=app.initMap
That could keep it cleaner also
UPDATE 2:
Yet another option (I minimally tested) would be to NOT use the callback
parameter in the Google API url, and link it with whatever else, library wise, you needed. (places, search, etc).
https://maps.googleapis.com/maps/api/js?key=YOUR-KEY-HERE&libraries=places
for example.
Then in your object init function just set a timer with to see if the google
object is available! Maybe something like this:
var app = app || {};
(function($){
$(function(){
$.extend(app, {
init:function(){
var self = this;
var timer = setInterval(function(){
if ($('.ex').length){ //but really check for google object
console.log('things exist google, elements, etc..');
self.next();
clearInterval(timer);
}
});
},
next:function(){
console.log('google object exists')
}
});
app.init()
});
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='ex'>as an example for something to trigger a flag (true/false) to clear the interval</div>
in any case where you try to access the global object, in this case app
, as a callback in the URL you would set callback=app.yourFunctionToCall
NOT callback=app.funtionToCall()
you script
tag should also have the async
and defer
attributes attributed to it to promote further html parsing (your app's js should be directly after the maps script)