1
- import { Injectable , Optional } from '@angular/core' ;
1
+ import { Injectable , Optional , Provider , provide } from '@angular/core' ;
2
+
2
3
import { MapsAPILoader } from './maps-api-loader' ;
3
4
4
5
export enum GoogleMapsScriptProtocol {
@@ -7,62 +8,81 @@ export enum GoogleMapsScriptProtocol {
7
8
AUTO
8
9
}
9
10
10
- export class LazyMapsAPILoaderConfig {
11
+ /**
12
+ * Config literal used to create an instance of LazyMapsAPILoaderConfig.
13
+ */
14
+ export interface LazyMapsAPILoaderConfigLiteral {
11
15
/**
12
16
* The Google Maps API Key (see:
13
17
* https://developers.google.com/maps/documentation/javascript/get-api-key)
14
18
*/
15
- apiKey : string = null ;
19
+ apiKey ? : string ;
16
20
17
21
/**
18
22
* The Google Maps client ID (for premium plans).
19
23
* When you have a Google Maps APIs Premium Plan license, you must authenticate
20
24
* your application with either an API key or a client ID.
21
25
* The Google Maps API will fail to load if both a client ID and an API key are included.
22
26
*/
23
- clientId : string = null ;
27
+ clientId ? : string ;
24
28
25
29
/**
26
30
* The Google Maps channel name (for premium plans).
27
31
* A channel parameter is an optional parameter that allows you to track usage under your client
28
32
* ID by assigning a distinct channel to each of your applications.
29
33
*/
30
- channel : string = null ;
34
+ channel ? : string ;
31
35
32
36
/**
33
37
* Google Maps API version.
34
38
*/
35
- apiVersion : string = '3' ;
39
+ apiVersion ? : string ;
36
40
37
41
/**
38
42
* Host and Path used for the `<script>` tag.
39
43
*/
40
- hostAndPath : string = 'maps.googleapis.com/maps/api/js' ;
44
+ hostAndPath ? : string ;
41
45
42
46
/**
43
47
* Protocol used for the `<script>` tag.
44
48
*/
45
- protocol : GoogleMapsScriptProtocol = GoogleMapsScriptProtocol . HTTPS ;
49
+ protocol ? : GoogleMapsScriptProtocol ;
46
50
47
51
/**
48
52
* Defines which Google Maps libraries should get loaded.
49
53
*/
50
- libraries : string [ ] = [ ] ;
54
+ libraries ? : string [ ] ;
51
55
52
56
/**
53
57
* The default bias for the map behavior is US.
54
58
* If you wish to alter your application to serve different map tiles or bias the
55
59
* application, you can overwrite the default behavior (US) by defining a `region`.
56
60
* See https://developers.google.com/maps/documentation/javascript/basics#Region
57
61
*/
58
- region : string = null ;
62
+ region ? : string ;
59
63
60
64
/**
61
65
* The Google Maps API uses the browser's preferred language when displaying
62
66
* textual information. If you wish to overwrite this behavior and force the API
63
67
* to use a given language, you can use this setting.
64
68
* See https://developers.google.com/maps/documentation/javascript/basics#Language
65
69
*/
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 ;
66
86
language : string = null ;
67
87
}
68
88
@@ -71,33 +91,36 @@ const DEFAULT_CONFIGURATION = new LazyMapsAPILoaderConfig();
71
91
@Injectable ( )
72
92
export class LazyMapsAPILoader extends MapsAPILoader {
73
93
private _scriptLoadingPromise : Promise < void > ;
94
+ private _config : LazyMapsAPILoaderConfig ;
95
+ private _window : Window ;
96
+ private _document : Document ;
74
97
75
- constructor ( @Optional ( ) private _config : LazyMapsAPILoaderConfig ) {
98
+ constructor ( @Optional ( ) config : LazyMapsAPILoaderConfig , w : Window , d : Document ) {
76
99
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 ;
80
103
}
81
104
82
105
load ( ) : Promise < void > {
83
106
if ( this . _scriptLoadingPromise ) {
84
107
return this . _scriptLoadingPromise ;
85
108
}
86
109
87
- const script = document . createElement ( 'script' ) ;
110
+ const script = this . _document . createElement ( 'script' ) ;
88
111
script . type = 'text/javascript' ;
89
112
script . async = true ;
90
113
script . defer = true ;
91
- const callbackName : string = `angular2googlemaps ${ new Date ( ) . getMilliseconds ( ) } ` ;
114
+ const callbackName : string = `angular2GoogleMapsLazyMapsAPILoader ` ;
92
115
script . src = this . _getScriptSrc ( callbackName ) ;
93
116
94
117
this . _scriptLoadingPromise = new Promise < void > ( ( resolve : Function , reject : Function ) => {
95
- ( < any > window ) [ callbackName ] = ( ) => { resolve ( ) ; } ;
118
+ ( < any > this . _window ) [ callbackName ] = ( ) => { resolve ( ) ; } ;
96
119
97
120
script . onerror = ( error : Event ) => { reject ( error ) ; } ;
98
121
} ) ;
99
122
100
- document . body . appendChild ( script ) ;
123
+ this . _document . body . appendChild ( script ) ;
101
124
return this . _scriptLoadingPromise ;
102
125
}
103
126
@@ -119,40 +142,57 @@ export class LazyMapsAPILoader extends MapsAPILoader {
119
142
}
120
143
121
144
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 > } = {
129
146
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
131
154
} ;
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 } ` ;
157
174
}
158
175
}
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