1- import { Injectable , Optional } from '@angular/core' ;
1+ import { Injectable , Optional , Provider , provide } from '@angular/core' ;
2+
23import { MapsAPILoader } from './maps-api-loader' ;
34
45export enum GoogleMapsScriptProtocol {
@@ -7,62 +8,81 @@ export enum GoogleMapsScriptProtocol {
78 AUTO
89}
910
10- export class LazyMapsAPILoaderConfig {
11+ /**
12+ * Config literal used to create an instance of LazyMapsAPILoaderConfig.
13+ */
14+ export interface LazyMapsAPILoaderConfigLiteral {
1115 /**
1216 * The Google Maps API Key (see:
1317 * https://developers.google.com/maps/documentation/javascript/get-api-key)
1418 */
15- apiKey : string = null ;
19+ apiKey ? : string ;
1620
1721 /**
1822 * The Google Maps client ID (for premium plans).
1923 * When you have a Google Maps APIs Premium Plan license, you must authenticate
2024 * your application with either an API key or a client ID.
2125 * The Google Maps API will fail to load if both a client ID and an API key are included.
2226 */
23- clientId : string = null ;
27+ clientId ? : string ;
2428
2529 /**
2630 * The Google Maps channel name (for premium plans).
2731 * A channel parameter is an optional parameter that allows you to track usage under your client
2832 * ID by assigning a distinct channel to each of your applications.
2933 */
30- channel : string = null ;
34+ channel ? : string ;
3135
3236 /**
3337 * Google Maps API version.
3438 */
35- apiVersion : string = '3' ;
39+ apiVersion ? : string ;
3640
3741 /**
3842 * Host and Path used for the `<script>` tag.
3943 */
40- hostAndPath : string = 'maps.googleapis.com/maps/api/js' ;
44+ hostAndPath ? : string ;
4145
4246 /**
4347 * Protocol used for the `<script>` tag.
4448 */
45- protocol : GoogleMapsScriptProtocol = GoogleMapsScriptProtocol . HTTPS ;
49+ protocol ? : GoogleMapsScriptProtocol ;
4650
4751 /**
4852 * Defines which Google Maps libraries should get loaded.
4953 */
50- libraries : string [ ] = [ ] ;
54+ libraries ? : string [ ] ;
5155
5256 /**
5357 * The default bias for the map behavior is US.
5458 * If you wish to alter your application to serve different map tiles or bias the
5559 * application, you can overwrite the default behavior (US) by defining a `region`.
5660 * See https://developers.google.com/maps/documentation/javascript/basics#Region
5761 */
58- region : string = null ;
62+ region ? : string ;
5963
6064 /**
6165 * The Google Maps API uses the browser's preferred language when displaying
6266 * textual information. If you wish to overwrite this behavior and force the API
6367 * to use a given language, you can use this setting.
6468 * See https://developers.google.com/maps/documentation/javascript/basics#Language
6569 */
70+ language ?: string ;
71+ }
72+
73+ /**
74+ * Configuration for {@link LazyMapsAPILoader}.
75+ * See {@link LazyMapsAPILoaderConfig} for instance attribute descriptions.
76+ */
77+ export class LazyMapsAPILoaderConfig implements LazyMapsAPILoaderConfigLiteral {
78+ apiKey : string = null ;
79+ clientId : string = null ;
80+ channel : string = null ;
81+ apiVersion : string = '3' ;
82+ hostAndPath : string = 'maps.googleapis.com/maps/api/js' ;
83+ protocol : GoogleMapsScriptProtocol = GoogleMapsScriptProtocol . HTTPS ;
84+ libraries : string [ ] = [ ] ;
85+ region : string = null ;
6686 language : string = null ;
6787}
6888
@@ -71,33 +91,36 @@ const DEFAULT_CONFIGURATION = new LazyMapsAPILoaderConfig();
7191@Injectable ( )
7292export class LazyMapsAPILoader extends MapsAPILoader {
7393 private _scriptLoadingPromise : Promise < void > ;
94+ private _config : LazyMapsAPILoaderConfig ;
95+ private _window : Window ;
96+ private _document : Document ;
7497
75- constructor ( @Optional ( ) private _config : LazyMapsAPILoaderConfig ) {
98+ constructor ( @Optional ( ) config : LazyMapsAPILoaderConfig , w : Window , d : Document ) {
7699 super ( ) ;
77- if ( this . _config === null || this . _config === undefined ) {
78- this . _config = DEFAULT_CONFIGURATION ;
79- }
100+ this . _config = config || DEFAULT_CONFIGURATION ;
101+ this . _window = w ;
102+ this . _document = d ;
80103 }
81104
82105 load ( ) : Promise < void > {
83106 if ( this . _scriptLoadingPromise ) {
84107 return this . _scriptLoadingPromise ;
85108 }
86109
87- const script = document . createElement ( 'script' ) ;
110+ const script = this . _document . createElement ( 'script' ) ;
88111 script . type = 'text/javascript' ;
89112 script . async = true ;
90113 script . defer = true ;
91- const callbackName : string = `angular2googlemaps ${ new Date ( ) . getMilliseconds ( ) } ` ;
114+ const callbackName : string = `angular2GoogleMapsLazyMapsAPILoader ` ;
92115 script . src = this . _getScriptSrc ( callbackName ) ;
93116
94117 this . _scriptLoadingPromise = new Promise < void > ( ( resolve : Function , reject : Function ) => {
95- ( < any > window ) [ callbackName ] = ( ) => { resolve ( ) ; } ;
118+ ( < any > this . _window ) [ callbackName ] = ( ) => { resolve ( ) ; } ;
96119
97120 script . onerror = ( error : Event ) => { reject ( error ) ; } ;
98121 } ) ;
99122
100- document . body . appendChild ( script ) ;
123+ this . _document . body . appendChild ( script ) ;
101124 return this . _scriptLoadingPromise ;
102125 }
103126
@@ -119,40 +142,57 @@ export class LazyMapsAPILoader extends MapsAPILoader {
119142 }
120143
121144 const hostAndPath : string = this . _config . hostAndPath || DEFAULT_CONFIGURATION . hostAndPath ;
122- const apiKey : string = this . _config . apiKey || DEFAULT_CONFIGURATION . apiKey ;
123- const clientId : string = this . _config . clientId || DEFAULT_CONFIGURATION . clientId ;
124- const channel : string = this . _config . channel || DEFAULT_CONFIGURATION . channel ;
125- const libraries : string [ ] = this . _config . libraries || DEFAULT_CONFIGURATION . libraries ;
126- const region : string = this . _config . region || DEFAULT_CONFIGURATION . region ;
127- const language : string = this . _config . language || DEFAULT_CONFIGURATION . language ;
128- const queryParams : { [ key : string ] : string } = {
145+ const queryParams : { [ key : string ] : string | Array < string > } = {
129146 v : this . _config . apiVersion || DEFAULT_CONFIGURATION . apiVersion ,
130- callback : callbackName
147+ callback : callbackName ,
148+ key : this . _config . apiKey ,
149+ client : this . _config . clientId ,
150+ channel : this . _config . channel ,
151+ libraries : this . _config . libraries ,
152+ region : this . _config . region ,
153+ language : this . _config . language
131154 } ;
132- if ( apiKey ) {
133- queryParams [ 'key' ] = apiKey ;
134- }
135- if ( clientId ) {
136- queryParams [ 'client' ] = clientId ;
137- }
138- if ( channel ) {
139- queryParams [ 'channel' ] = channel ;
140- }
141- if ( libraries != null && libraries . length > 0 ) {
142- queryParams [ 'libraries' ] = libraries . join ( ',' ) ;
143- }
144- if ( region != null && region . length > 0 ) {
145- queryParams [ 'region' ] = region ;
146- }
147- if ( language != null && language . length > 0 ) {
148- queryParams [ 'language' ] = language ;
149- }
150- const params : string = Object . keys ( queryParams )
151- . map ( ( k : string , i : number ) => {
152- let param = ( i === 0 ) ? '?' : '&' ;
153- return param += `${ k } =${ queryParams [ k ] } ` ;
154- } )
155- . join ( '' ) ;
156- return `${ protocol } //${ hostAndPath } ${ params } ` ;
155+ const params : string =
156+ Object . keys ( queryParams )
157+ . filter ( ( k : string ) => queryParams [ k ] != null )
158+ . filter ( ( k : string ) => {
159+ // remove empty arrays
160+ return ! Array . isArray ( queryParams [ k ] ) ||
161+ ( Array . isArray ( queryParams [ k ] ) && queryParams [ k ] . length > 0 ) ;
162+ } )
163+ . map ( ( k : string ) => {
164+ // join arrays as comma seperated strings
165+ let i = queryParams [ k ] ;
166+ if ( Array . isArray ( i ) ) {
167+ return { key : k , value : i . join ( ',' ) } ;
168+ }
169+ return { key : k , value : queryParams [ k ] } ;
170+ } )
171+ . map ( ( entry : { key : string , value : string } ) => { return `${ entry . key } =${ entry . value } ` ; } )
172+ . join ( '&' ) ;
173+ return `${ protocol } //${ hostAndPath } ?${ params } ` ;
157174 }
158175}
176+
177+ /**
178+ * Creates a provider for a {@link LazyMapsAPILoaderConfig})
179+ */
180+ export function provideLazyMapsAPILoaderConfig ( confLiteral : LazyMapsAPILoaderConfigLiteral ) :
181+ Provider {
182+ return provide ( LazyMapsAPILoaderConfig , {
183+ useFactory : ( ) => {
184+ const config = new LazyMapsAPILoaderConfig ( ) ;
185+ // todo(sebastian): deprecate LazyMapsAPILoader class
186+ config . apiKey = confLiteral . apiKey || DEFAULT_CONFIGURATION . apiKey ;
187+ config . apiVersion = confLiteral . apiVersion || DEFAULT_CONFIGURATION . apiVersion ;
188+ config . channel = confLiteral . channel || DEFAULT_CONFIGURATION . channel ;
189+ config . clientId = confLiteral . clientId || DEFAULT_CONFIGURATION . clientId ;
190+ config . hostAndPath = confLiteral . hostAndPath || DEFAULT_CONFIGURATION . hostAndPath ;
191+ config . language = confLiteral . language || DEFAULT_CONFIGURATION . language ;
192+ config . libraries = confLiteral . libraries || DEFAULT_CONFIGURATION . libraries ;
193+ config . protocol = config . protocol || DEFAULT_CONFIGURATION . protocol ;
194+ config . region = config . region || DEFAULT_CONFIGURATION . region ;
195+ return config ;
196+ }
197+ } ) ;
198+ }
0 commit comments