1 | /* |
2 | Copyright - 2017 2023 - wwwouaiebe - Contact: https://www.ouaie.be/ |
3 | |
4 | This program is free software; |
5 | you can redistribute it and/or modify it under the terms of the |
6 | GNU General Public License as published by the Free Software Foundation; |
7 | either version 3 of the License, or any later version. |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | GNU General Public License for more details. |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software |
14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
15 | */ |
16 | /* |
17 | Changes: |
18 | - v4.0.0: |
19 | - created from v3.6.0 |
20 | Doc reviewed 202208 |
21 | */ |
22 | |
23 | import theHTMLSanitizer from '../core/htmlSanitizer/HTMLSanitizer.js'; |
24 | import MapLayerToolbarButtonData from './MapLayerToolbarButtonData.js'; |
25 | import { ZERO, ONE } from '../main/Constants.js'; |
26 | |
27 | /* ------------------------------------------------------------------------------------------------------------------------- */ |
28 | /** |
29 | This class represent a background map |
30 | */ |
31 | /* ------------------------------------------------------------------------------------------------------------------------- */ |
32 | |
33 | class MapLayer { |
34 | |
35 | /** |
36 | The name of the map |
37 | @type {String} |
38 | */ |
39 | |
40 | #name = null; |
41 | |
42 | /** |
43 | The type of service: wms or wmts |
44 | @type {String} |
45 | */ |
46 | |
47 | #service = null; |
48 | |
49 | /** |
50 | The url to use to get the map |
51 | @type {String} |
52 | */ |
53 | |
54 | #url = null; |
55 | |
56 | /** |
57 | The wmsOptions for this mapLayer |
58 | See the Leaflet TileLayer.WMS documentation |
59 | @type {LeafletObject} |
60 | */ |
61 | |
62 | #wmsOptions = null; |
63 | |
64 | /** |
65 | The lower left and upper right corner of the mapLayer |
66 | @type {Array.<Number>} |
67 | */ |
68 | |
69 | #bounds = null; |
70 | |
71 | /** |
72 | The smallest possible zoom for this mapLayer |
73 | @type {Number} |
74 | */ |
75 | |
76 | #minZoom = null; |
77 | |
78 | /** |
79 | The largest possible zoom for this mapLayer |
80 | @type {Number} |
81 | */ |
82 | |
83 | #maxZoom = null; |
84 | |
85 | /** |
86 | An object with text, color and backgroundColor properties used to create the button in the toolbar |
87 | @type {LayerToolbarButtonData} |
88 | */ |
89 | |
90 | #toolbarButtonData = null; |
91 | |
92 | /** |
93 | The name of the service provider. |
94 | @type {String} |
95 | */ |
96 | |
97 | #providerName = null; |
98 | |
99 | /** |
100 | When true, an access key is required to get the map. |
101 | @type {Boolean} |
102 | */ |
103 | |
104 | #providerKeyNeeded = false; |
105 | |
106 | /** |
107 | The map attributions. |
108 | @type {String} |
109 | */ |
110 | |
111 | #attribution = null; |
112 | |
113 | /** |
114 | A temporary variable to store the layer data |
115 | @type {JsonObject} |
116 | */ |
117 | |
118 | #jsonLayer = null; |
119 | |
120 | /** |
121 | Set the name of the map layer |
122 | */ |
123 | |
124 | #setLayerName ( ) { |
125 | if ( 'string' === typeof ( this.#jsonLayer?.name ) ) { |
126 | this.#name = theHTMLSanitizer.sanitizeToJsString ( this.#jsonLayer.name ); |
127 | } |
128 | else { |
129 | throw new Error ( 'invalid name for layer' ); |
130 | } |
131 | } |
132 | |
133 | /** |
134 | Set the type of service: wms or wmts |
135 | */ |
136 | |
137 | #setService ( ) { |
138 | if ( 'wms' === this.#jsonLayer?.service || 'wmts' === this.#jsonLayer?.service ) { |
139 | this.#service = this.#jsonLayer.service; |
140 | } |
141 | else { |
142 | throw new Error ( 'invalid service for layer ' + this.#name ); |
143 | } |
144 | } |
145 | |
146 | /** |
147 | Set the url to use to get the map |
148 | */ |
149 | |
150 | #setUrl ( ) { |
151 | if ( 'string' === typeof ( this.#jsonLayer?.url ) ) { |
152 | this.#url = this.#jsonLayer.url; |
153 | } |
154 | else { |
155 | throw new Error ( 'invalid url for layer ' + this.#name ); |
156 | } |
157 | } |
158 | |
159 | /** |
160 | Set the wmsOptions for this mapLayer |
161 | */ |
162 | |
163 | #setWmsOptions ( ) { |
164 | if ( 'wms' === this.#service ) { |
165 | if ( |
166 | 'string' === typeof ( this.#jsonLayer?.wmsOptions?.layers ) |
167 | && |
168 | 'string' === typeof ( this.#jsonLayer?.wmsOptions?.format ) |
169 | && |
170 | 'boolean' === typeof ( this.#jsonLayer?.wmsOptions?.transparent ) |
171 | ) { |
172 | this.#wmsOptions = this.#jsonLayer.wmsOptions; |
173 | this.#wmsOptions.layers = theHTMLSanitizer.sanitizeToJsString ( this.#wmsOptions.layers ); |
174 | this.#wmsOptions.format = theHTMLSanitizer.sanitizeToJsString ( this.#wmsOptions.format ); |
175 | } |
176 | else { |
177 | throw new Error ( 'invalid wmsOptions for layer ' + this.#name ); |
178 | } |
179 | } |
180 | } |
181 | |
182 | /** |
183 | Set the lower left and upper right corner of the mapLayer |
184 | */ |
185 | |
186 | #setBounds ( ) { |
187 | try { |
188 | if ( |
189 | this.#jsonLayer.bounds |
190 | && |
191 | 'number' === typeof this.#jsonLayer.bounds [ ZERO ] [ ZERO ] |
192 | && |
193 | 'number' === typeof this.#jsonLayer.bounds [ ZERO ] [ ONE ] |
194 | && |
195 | 'number' === typeof this.#jsonLayer.bounds [ ONE ] [ ZERO ] |
196 | && |
197 | 'number' === typeof this.#jsonLayer.bounds [ ONE ] [ ONE ] |
198 | ) { |
199 | this.#bounds = this.#jsonLayer.bounds; |
200 | } |
201 | } |
202 | catch { |
203 | throw new Error ( 'invalid bounds for layer ' + this.#name ); |
204 | } |
205 | } |
206 | |
207 | /** |
208 | Set the min and max zoom for the map |
209 | */ |
210 | |
211 | #setMinMaxZoom ( ) { |
212 | if ( this.#jsonLayer.minZoom ) { |
213 | if ( 'number' === typeof ( this.#jsonLayer.minZoom ) ) { |
214 | this.#minZoom = this.#jsonLayer.minZoom; |
215 | } |
216 | else { |
217 | throw new Error ( 'invalid minZoom for layer ' + this.#name ); |
218 | } |
219 | } |
220 | if ( this.#jsonLayer.maxZoom ) { |
221 | if ( 'number' === typeof ( this.#jsonLayer.maxZoom ) ) { |
222 | this.#maxZoom = this.#jsonLayer.maxZoom; |
223 | } |
224 | else { |
225 | throw new Error ( 'invalid maxZoom for layer ' + this.#name ); |
226 | } |
227 | } |
228 | } |
229 | |
230 | /** |
231 | Set the toolbar data |
232 | */ |
233 | |
234 | #setToolbarButtonData ( ) { |
235 | this.#toolbarButtonData = new MapLayerToolbarButtonData ( this.#jsonLayer.toolbar ); |
236 | } |
237 | |
238 | /** |
239 | Set the name of the service provider |
240 | */ |
241 | |
242 | #setProviderName ( ) { |
243 | if ( 'string' === typeof ( this.#jsonLayer?.providerName ) ) { |
244 | this.#providerName = theHTMLSanitizer.sanitizeToJsString ( this.#jsonLayer.providerName ); |
245 | } |
246 | else { |
247 | throw new Error ( 'invalid providerName for layer ' + this.#name ); |
248 | } |
249 | } |
250 | |
251 | /** |
252 | Set the providerKeyNeeded value |
253 | */ |
254 | |
255 | #setProviderKeyNeeded ( ) { |
256 | if ( 'boolean' === typeof ( this.#jsonLayer.providerKeyNeeded ) ) { |
257 | this.#providerKeyNeeded = this.#jsonLayer.providerKeyNeeded; |
258 | } |
259 | else { |
260 | throw new Error ( 'invalid providerKeyNeeded for layer ' + this.#name ); |
261 | } |
262 | } |
263 | |
264 | /** |
265 | Set the map attributions. |
266 | */ |
267 | |
268 | #setAttributions ( ) { |
269 | if ( '' === this.#jsonLayer.attribution ) { |
270 | this.#attribution = ''; |
271 | } |
272 | else if ( 'string' === typeof ( this.#jsonLayer?.attribution ) ) { |
273 | this.#attribution = theHTMLSanitizer.sanitizeToHtmlString ( this.#jsonLayer.attribution ).htmlString; |
274 | } |
275 | else { |
276 | throw new Error ( 'invalid attribution for map layer ' + this.#name ); |
277 | } |
278 | } |
279 | |
280 | /** |
281 | The constructor |
282 | @param {JsonObject} jsonLayer A json object from TravelNotesLayers.json |
283 | */ |
284 | |
285 | constructor ( jsonLayer ) { |
286 | Object.freeze ( this ); |
287 | this.#jsonLayer = jsonLayer; |
288 | this.#setLayerName ( ); |
289 | this.#setService ( ); |
290 | this.#setUrl ( ); |
291 | this.#setWmsOptions ( ); |
292 | this.#setBounds ( ); |
293 | this.#setMinMaxZoom ( ); |
294 | this.#setToolbarButtonData ( ); |
295 | this.#setProviderName ( ); |
296 | this.#setProviderKeyNeeded ( ); |
297 | this.#setAttributions ( ); |
298 | this.#jsonLayer = null; |
299 | } |
300 | |
301 | /** |
302 | The name of the map |
303 | @type {String} |
304 | */ |
305 | |
306 | get name ( ) { return this.#name; } |
307 | |
308 | /** |
309 | The type of service: wms or wmts |
310 | @type {String} |
311 | */ |
312 | |
313 | get service ( ) { return this.#service; } |
314 | |
315 | /** |
316 | The url to use to get the map |
317 | @type {String} |
318 | */ |
319 | |
320 | get url ( ) { return this.#url; } |
321 | |
322 | /** |
323 | The wmsOptions for this mapLayer |
324 | See the Leaflet TileLayer.WMS documentation |
325 | @type {LeafletObject} |
326 | */ |
327 | |
328 | get wmsOptions ( ) { return this.#wmsOptions; } |
329 | |
330 | /** |
331 | The lower left and upper right corner of the mapLayer |
332 | @type {Array.<Number>} |
333 | */ |
334 | |
335 | get bounds ( ) { return this.#bounds; } |
336 | |
337 | /** |
338 | The smallest possible zoom for this mapLayer |
339 | @type {Number} |
340 | */ |
341 | |
342 | get minZoom ( ) { return this.#minZoom; } |
343 | |
344 | /** |
345 | The largest possible zoom for this mapLayer |
346 | @type {Number} |
347 | */ |
348 | |
349 | get maxZoom ( ) { return this.#maxZoom; } |
350 | |
351 | /** |
352 | An object with text, color and backgroundColor properties used to create the button in the toolbar |
353 | @type {LayerToolbarButtonData} |
354 | */ |
355 | |
356 | get toolbarButtonData ( ) { return this.#toolbarButtonData; } |
357 | |
358 | /** |
359 | The name of the service provider. This name will be used to find the access key to the service. |
360 | @type {String} |
361 | */ |
362 | |
363 | get providerName ( ) { return this.#providerName; } |
364 | |
365 | /** |
366 | When true, an access key is required to get the map. |
367 | @type {Boolean} |
368 | */ |
369 | |
370 | get providerKeyNeeded ( ) { return this.#providerKeyNeeded; } |
371 | |
372 | /** |
373 | The map attributions. For maps based on OpenStreetMap, it is not necessary to add |
374 | the attributions of OpenStreetMap because they are always present in Travel & Notes. |
375 | @type {String} |
376 | */ |
377 | |
378 | get attribution ( ) { return this.#attribution; } |
379 | |
380 | } |
381 | |
382 | export default MapLayer; |
383 | |
384 | /* --- End of file --------------------------------------------------------------------------------------------------------- */ |
385 |