'use strict';
/**
* @module async-google-maps/map-loader
*/
var URL_PREFIX = '//maps.googleapis.com/maps/api/js',
CALLBACK_IDENTIFIER = 'mapLoaded',
mapLoadedDeferred,
mapLoadedPromise;
global[CALLBACK_IDENTIFIER] = function mapLoaded() {
mapLoadedDeferred.resolve();
};
function buildUrl(options) {
return URL_PREFIX
+ '?v=' + options.version
+ '&key=' + options.key
+ '&callback=' + CALLBACK_IDENTIFIER;
}
function createDeferredToAllowForResolutionAfterGoogleMapsLoaderFinishes(resolve, reject) {
mapLoadedDeferred = {
resolve: resolve,
reject: reject
};
}
function createMapLoadedPromise() {
mapLoadedPromise = new Promise(function (resolve, reject) {
createDeferredToAllowForResolutionAfterGoogleMapsLoaderFinishes(resolve, reject);
});
}
function appendScriptOnDocumentReady(scriptEl) {
document.addEventListener('DOMContentLoaded', function () {
document.head.appendChild(scriptEl);
});
}
function injectGoogleMapsScript(options) {
var scriptEl = document.createElement('script');
scriptEl.src = buildUrl(options);
scriptEl.type = 'text/javascript';
appendScriptOnDocumentReady(scriptEl);
}
function init() {
createMapLoadedPromise();
}
init();
module.exports = {
/**
* Asynchronously loads the google maps javascript library, given the supplied options.
* Returns a promise that will be resolved once the google maps loader has finished.
* Once the promise resolves, it is safe to reference anything under the `google.maps` namespace.
* This method should only be called once for a given application.
*
* @param {Object} options - The configuration used to load the google maps API
* @param {string} options.version - The version of the google maps API to load
* @param {string} options.key - The API key of the consuming application
* @returns {Promise}
* */
load: function loadGoogleMapsAsync(options) {
injectGoogleMapsScript(options);
return mapLoadedPromise;
},
/**
* @property {Promise} loaded - A reference to a promise that is resolved once the google maps API is ready.
*/
loaded: (function () {
return mapLoadedPromise;
}()),
/**
* Creates a map instance given the supplied options. The options will be passed into the `google.maps.Map` constructor,
* therefore, all options from the [google maps api](https://developers.google.com/maps/documentation/javascript/reference#MapOptions) can be used.
* This function returns a promise which will be resolved once the newly created map instance is in the `idle` state,
* which is the point at which overlays, markers, and geometries can be added to the map.
*
* @param mapContainer - The element to attach the map instance to
* @param options - Options passed to the google Map constructor
* @returns {Promise}
* */
create: function createMap(mapContainer, options) {
return new Promise(function mapIdleResolver(resolve) {
mapLoadedPromise.then(function whenMapHasLoaded() {
var googleMaps = require('./google-maps-shim.js'),
mapInstance = new googleMaps.maps.Map(mapContainer, options);
googleMaps.maps.event.addListenerOnce(mapInstance, 'idle', function mapIdleHandler() {
resolve(mapInstance);
});
});
});
}
};