Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to expose callback function for Google Maps when using Browserify?

I'm using Gulp and Browserify to bundle my JavaScripts. I need to expose a callback function that should be executed after the Google Maps API loads.

How can this be done without using something like window.initMap? The problem with this is that I need to fire a large number of other methods inside initMap, so there has to be a better way of doing it besides using window.functionName and polluting the global namespace.

On the other hand, is it alright to just exclude the callback parameter and do something like this instead?

$.getScript('https://maps.googleapis.com/maps/api/js').done(function() {
  initMap();
});

Any help would be greatly appreciated. I have spent more time that I would ever admit in getting this to work.

gulpfile.js:

gulp.task('browserify', ['eslint'], function() {
  return browserify('/src/js/main.js')
    .bundle()
    .pipe(source('main.js'))
    .pipe(buffer())
    .pipe(gulp.dest('/dist/js'))
    .pipe(reload({ stream: true }));
});

main.js:

require('jquery');
require('./map');

map.js:

var map = (function() {
  'use strict';

  var mapElement = $('#map');

  function googleMapsAPI() {
    $.getScript('https://maps.googleapis.com/maps/api/js?callback=initMap');
  }

  function initMap() {
    var theMap = new google.maps.Map(mapElement);
    // functions...
  }

  function init() {
    googleMapsAPI();
  }
});

map.init();
like image 292
Cofey Avatar asked Aug 10 '17 23:08

Cofey


2 Answers

No, it's not okay to not include the callback parameter.

The google maps API library calls a bunch of other scripts to be loaded on the page and then, when they have all been loaded, the callback parameter is called on the window object.

Just declare it on the window object:

var MyApp = {
    init: function() {
         //all your stuff
    }
}

window.initMap = function() {
   window.initMap = null; //set this to null this so that it can't get called anymore....if you want
   MyApp.init();
};

and then just include the script tag on your page:

<script src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
like image 152
Adam Avatar answered Sep 29 '22 01:09

Adam


If you want to load the script and then do something when the script has been loaded, you can set the attributes async and onload when injecting the script. By wrapping all the code into an IIFE we will keep private all objects defined inside the IIFE, avoiding populate the global namespace window. See the following example:

// IIFE (Immediately-Invoked Function Expression)
// Keeps all private
!function() {
/**
 * Injects the script asynchronously.
 *
 * @param {String} url: the URL from where the script will be loaded
 * @param {Function} callback: function executed after the script is loaded
 */
function inject(url, callback) {
  var tag = 'script',
    script = document.createElement(tag),
    first = document.getElementsByTagName(tag)[0];
  script.defer = script.async = 1; // true
  script.type = 'text/javascript';
  script.src = url;
  script.onload = callback;
  first.parentNode.insertBefore(script, first);
}

/**
 * Injects and initializes the google maps api script.
 */
function injectMapsApi() {
  var key = 'your-api-key';
  var query = '?key=' + key;
  var url = 'https://maps.googleapis.com/maps/api/js' + query;
  inject(url, initMapsApi);
}

/**
 * Callback that initializes the google maps api script.
 */
function initMapsApi() {
  var maps = window.google.maps;
  // ... code initializations
  console.log(maps);
}

injectMapsApi();

}(); // end IIFE

You need to register and claim you API key in order to use the google maps API. More information here:

  • https://developers.google.com/maps/documentation/javascript/get-api-key
  • https://developers.google.com/maps/documentation/javascript/tutorial#Loading_the_Maps_API
like image 38
jherax Avatar answered Sep 29 '22 02:09

jherax