packages/core/src/lib/services/maps-api-loader/lazy-maps-api-loader.ts
Configuration for the LazyMapsAPILoader.
Properties |
|
apiKey |
apiKey:
|
Type : string
|
Optional |
The Google Maps API Key (see: https://developers.google.com/maps/documentation/javascript/get-api-key) |
apiVersion |
apiVersion:
|
Type : string
|
Optional |
Google Maps API version. |
channel |
channel:
|
Type : string
|
Optional |
The Google Maps channel name (for premium plans). A channel parameter is an optional parameter that allows you to track usage under your client ID by assigning a distinct channel to each of your applications. |
clientId |
clientId:
|
Type : string
|
Optional |
The Google Maps client ID (for premium plans). When you have a Google Maps APIs Premium Plan license, you must authenticate your application with either an API key or a client ID. The Google Maps API will fail to load if both a client ID and an API key are included. |
hostAndPath |
hostAndPath:
|
Type : string
|
Optional |
Host and Path used for the |
language |
language:
|
Type : string
|
Optional |
The Google Maps API uses the browser's preferred language when displaying textual information. If you wish to overwrite this behavior and force the API to use a given language, you can use this setting. See https://developers.google.com/maps/documentation/javascript/basics#Language |
libraries |
libraries:
|
Type : string[]
|
Optional |
Defines which Google Maps libraries should get loaded. |
protocol |
protocol:
|
Type : GoogleMapsScriptProtocol
|
Optional |
Protocol used for the |
region |
region:
|
Type : string
|
Optional |
The default bias for the map behavior is US.
If you wish to alter your application to serve different map tiles or bias the
application, you can overwrite the default behavior (US) by defining a |
import { Inject, Injectable, InjectionToken, LOCALE_ID, Optional } from '@angular/core';
import { DocumentRef, WindowRef } from '../../utils/browser-globals';
import { MapsAPILoader } from './maps-api-loader';
export enum GoogleMapsScriptProtocol {
HTTP = 1,
HTTPS = 2,
AUTO = 3,
}
/**
* Token for the config of the LazyMapsAPILoader. Please provide an object of type {@link
* LazyMapsAPILoaderConfig}.
*/
export const LAZY_MAPS_API_CONFIG = new InjectionToken<LazyMapsAPILoaderConfigLiteral>('angular-google-maps LAZY_MAPS_API_CONFIG');
/**
* Configuration for the {@link LazyMapsAPILoader}.
*/
export interface LazyMapsAPILoaderConfigLiteral {
/**
* The Google Maps API Key (see:
* https://developers.google.com/maps/documentation/javascript/get-api-key)
*/
apiKey?: string;
/**
* The Google Maps client ID (for premium plans).
* When you have a Google Maps APIs Premium Plan license, you must authenticate
* your application with either an API key or a client ID.
* The Google Maps API will fail to load if both a client ID and an API key are included.
*/
clientId?: string;
/**
* The Google Maps channel name (for premium plans).
* A channel parameter is an optional parameter that allows you to track usage under your client
* ID by assigning a distinct channel to each of your applications.
*/
channel?: string;
/**
* Google Maps API version.
*/
apiVersion?: string;
/**
* Host and Path used for the `<script>` tag.
*/
hostAndPath?: string;
/**
* Protocol used for the `<script>` tag.
*/
protocol?: GoogleMapsScriptProtocol;
/**
* Defines which Google Maps libraries should get loaded.
*/
libraries?: string[];
/**
* The default bias for the map behavior is US.
* If you wish to alter your application to serve different map tiles or bias the
* application, you can overwrite the default behavior (US) by defining a `region`.
* See https://developers.google.com/maps/documentation/javascript/basics#Region
*/
region?: string;
/**
* The Google Maps API uses the browser's preferred language when displaying
* textual information. If you wish to overwrite this behavior and force the API
* to use a given language, you can use this setting.
* See https://developers.google.com/maps/documentation/javascript/basics#Language
*/
language?: string;
}
@Injectable()
export class LazyMapsAPILoader extends MapsAPILoader {
protected _scriptLoadingPromise: Promise<void>;
protected _config: LazyMapsAPILoaderConfigLiteral;
protected _windowRef: WindowRef;
protected _documentRef: DocumentRef;
protected readonly _SCRIPT_ID: string = 'agmGoogleMapsApiScript';
protected readonly callbackName: string = `agmLazyMapsAPILoader`;
constructor(@Optional() @Inject(LAZY_MAPS_API_CONFIG) config: any = null, w: WindowRef, d: DocumentRef,
@Inject(LOCALE_ID) private localeId: string) {
super();
this._config = config || {};
this._windowRef = w;
this._documentRef = d;
}
load(): Promise<void> {
const window = this._windowRef.getNativeWindow() as any;
if (window.google && window.google.maps) {
// Google maps already loaded on the page.
return Promise.resolve();
}
if (this._scriptLoadingPromise) {
return this._scriptLoadingPromise;
}
// this can happen in HMR situations or Stackblitz.io editors.
const scriptOnPage = this._documentRef.getNativeDocument().getElementById(this._SCRIPT_ID);
if (scriptOnPage) {
this._assignScriptLoadingPromise(scriptOnPage);
return this._scriptLoadingPromise;
}
const script = this._documentRef.getNativeDocument().createElement('script');
script.type = 'text/javascript';
script.async = true;
script.defer = true;
script.id = this._SCRIPT_ID;
script.src = this._getScriptSrc(this.callbackName);
this._assignScriptLoadingPromise(script);
this._documentRef.getNativeDocument().body.appendChild(script);
return this._scriptLoadingPromise;
}
private _assignScriptLoadingPromise(scriptElem: HTMLElement) {
this._scriptLoadingPromise = new Promise((resolve, reject) => {
this._windowRef.getNativeWindow()[this.callbackName] = () => {
resolve();
};
scriptElem.onerror = (error: Event) => {
reject(error);
};
});
}
protected _getScriptSrc(callbackName: string): string {
const protocolType: GoogleMapsScriptProtocol =
(this._config && this._config.protocol) || GoogleMapsScriptProtocol.HTTPS;
let protocol: string;
switch (protocolType) {
case GoogleMapsScriptProtocol.AUTO:
protocol = '';
break;
case GoogleMapsScriptProtocol.HTTP:
protocol = 'http:';
break;
case GoogleMapsScriptProtocol.HTTPS:
protocol = 'https:';
break;
}
const hostAndPath: string = this._config.hostAndPath || 'maps.googleapis.com/maps/api/js';
const queryParams: {[key: string]: string | string[]} = {
v: this._config.apiVersion || 'quarterly',
callback: callbackName,
key: this._config.apiKey,
client: this._config.clientId,
channel: this._config.channel,
libraries: this._config.libraries,
region: this._config.region,
language: this._config.language || (this.localeId !== 'en-US' ? this.localeId : null),
};
const params: string = Object.keys(queryParams)
.filter((k: string) => queryParams[k] != null)
.filter((k: string) => {
// remove empty arrays
return !Array.isArray(queryParams[k]) ||
(Array.isArray(queryParams[k]) && queryParams[k].length > 0);
})
.map((k: string) => {
// join arrays as comma seperated strings
const i = queryParams[k];
if (Array.isArray(i)) {
return {key: k, value: i.join(',')};
}
return {key: k, value: queryParams[k]};
})
.map((entry: {key: string, value: string}) => {
return `${entry.key}=${entry.value}`;
})
.join('&');
return `${protocol}//${hostAndPath}?${params}`;
}
}