UNPKG

5.33 kBPlain TextView Raw
1import {Inject, Injectable, OpaqueToken} from '@angular/core';
2
3import {DocumentRef, WindowRef} from '../../utils/browser-globals';
4
5import {MapsAPILoader} from './maps-api-loader';
6
7export enum GoogleMapsScriptProtocol {
8 HTTP = 1,
9 HTTPS = 2,
10 AUTO = 3
11}
12
13/**
14 * Token for the config of the LazyMapsAPILoader. Please provide an object of type {@link
15 * LazyMapsAPILoaderConfig}.
16 */
17export const LAZY_MAPS_API_CONFIG = new OpaqueToken('angular2-google-maps LAZY_MAPS_API_CONFIG');
18
19/**
20 * Configuration for the {@link LazyMapsAPILoader}.
21 */
22export interface LazyMapsAPILoaderConfigLiteral {
23 /**
24 * The Google Maps API Key (see:
25 * https://developers.google.com/maps/documentation/javascript/get-api-key)
26 */
27 apiKey?: string;
28
29 /**
30 * The Google Maps client ID (for premium plans).
31 * When you have a Google Maps APIs Premium Plan license, you must authenticate
32 * your application with either an API key or a client ID.
33 * The Google Maps API will fail to load if both a client ID and an API key are included.
34 */
35 clientId?: string;
36
37 /**
38 * The Google Maps channel name (for premium plans).
39 * A channel parameter is an optional parameter that allows you to track usage under your client
40 * ID by assigning a distinct channel to each of your applications.
41 */
42 channel?: string;
43
44 /**
45 * Google Maps API version.
46 */
47 apiVersion?: string;
48
49 /**
50 * Host and Path used for the `<script>` tag.
51 */
52 hostAndPath?: string;
53
54 /**
55 * Protocol used for the `<script>` tag.
56 */
57 protocol?: GoogleMapsScriptProtocol;
58
59 /**
60 * Defines which Google Maps libraries should get loaded.
61 */
62 libraries?: string[];
63
64 /**
65 * The default bias for the map behavior is US.
66 * If you wish to alter your application to serve different map tiles or bias the
67 * application, you can overwrite the default behavior (US) by defining a `region`.
68 * See https://developers.google.com/maps/documentation/javascript/basics#Region
69 */
70 region?: string;
71
72 /**
73 * The Google Maps API uses the browser's preferred language when displaying
74 * textual information. If you wish to overwrite this behavior and force the API
75 * to use a given language, you can use this setting.
76 * See https://developers.google.com/maps/documentation/javascript/basics#Language
77 */
78 language?: string;
79}
80
81@Injectable()
82export class LazyMapsAPILoader extends MapsAPILoader {
83 private _scriptLoadingPromise: Promise<void>;
84 private _config: LazyMapsAPILoaderConfigLiteral;
85 private _windowRef: WindowRef;
86 private _documentRef: DocumentRef;
87
88 constructor(@Inject(LAZY_MAPS_API_CONFIG) config: any, w: WindowRef, d: DocumentRef) {
89 super();
90 this._config = config || {};
91 this._windowRef = w;
92 this._documentRef = d;
93 }
94
95 load(): Promise<void> {
96 if (this._scriptLoadingPromise) {
97 return this._scriptLoadingPromise;
98 }
99
100 const script = this._documentRef.getNativeDocument().createElement('script');
101 script.type = 'text/javascript';
102 script.async = true;
103 script.defer = true;
104 const callbackName: string = `angular2GoogleMapsLazyMapsAPILoader`;
105 script.src = this._getScriptSrc(callbackName);
106
107 this._scriptLoadingPromise = new Promise<void>((resolve: Function, reject: Function) => {
108 (<any>this._windowRef.getNativeWindow())[callbackName] = () => { resolve(); };
109
110 script.onerror = (error: Event) => { reject(error); };
111 });
112
113 this._documentRef.getNativeDocument().body.appendChild(script);
114 return this._scriptLoadingPromise;
115 }
116
117 private _getScriptSrc(callbackName: string): string {
118 let protocolType: GoogleMapsScriptProtocol =
119 (this._config && this._config.protocol) || GoogleMapsScriptProtocol.HTTPS;
120 let protocol: string;
121
122 switch (protocolType) {
123 case GoogleMapsScriptProtocol.AUTO:
124 protocol = '';
125 break;
126 case GoogleMapsScriptProtocol.HTTP:
127 protocol = 'http:';
128 break;
129 case GoogleMapsScriptProtocol.HTTPS:
130 protocol = 'https:';
131 break;
132 }
133
134 const hostAndPath: string = this._config.hostAndPath || 'maps.googleapis.com/maps/api/js';
135 const queryParams: {[key: string]: string | Array<string>} = {
136 v: this._config.apiVersion || '3',
137 callback: callbackName,
138 key: this._config.apiKey,
139 client: this._config.clientId,
140 channel: this._config.channel,
141 libraries: this._config.libraries,
142 region: this._config.region,
143 language: this._config.language
144 };
145 const params: string =
146 Object.keys(queryParams)
147 .filter((k: string) => queryParams[k] != null)
148 .filter((k: string) => {
149 // remove empty arrays
150 return !Array.isArray(queryParams[k]) ||
151 (Array.isArray(queryParams[k]) && queryParams[k].length > 0);
152 })
153 .map((k: string) => {
154 // join arrays as comma seperated strings
155 let i = queryParams[k];
156 if (Array.isArray(i)) {
157 return {key: k, value: i.join(',')};
158 }
159 return {key: k, value: queryParams[k]};
160 })
161 .map((entry: {key: string, value: string}) => { return `${entry.key}=${entry.value}`; })
162 .join('&');
163 return `${protocol}//${hostAndPath}?${params}`;
164 }
165}
166
\No newline at end of file