@panoramax/web-viewer 3.2.3-develop-d7e5a16d → 3.2.3-develop-f9c0224b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitlab-ci.yml +5 -0
- package/CHANGELOG.md +19 -0
- package/CODE_OF_CONDUCT.md +1 -1
- package/README.md +1 -1
- package/build/editor.html +10 -1
- package/build/index.css +2 -2
- package/build/index.css.map +1 -1
- package/build/index.html +1 -1
- package/build/index.js +1682 -5
- package/build/index.js.map +1 -1
- package/build/map.html +1 -1
- package/build/viewer.html +10 -1
- package/build/widgets.html +1 -0
- package/config/jest/mocks.js +172 -0
- package/config/paths.js +1 -0
- package/config/webpack.config.js +26 -0
- package/docs/03_URL_settings.md +3 -11
- package/docs/05_Compatibility.md +59 -76
- package/docs/09_Develop.md +30 -11
- package/docs/90_Releases.md +2 -2
- package/docs/images/class_diagram.drawio +28 -28
- package/docs/images/class_diagram.jpg +0 -0
- package/docs/index.md +112 -0
- package/docs/reference/components/core/Basic.md +153 -0
- package/docs/reference/components/core/CoverageMap.md +160 -0
- package/docs/reference/components/core/Editor.md +172 -0
- package/docs/reference/components/core/Viewer.md +288 -0
- package/docs/reference/components/layout/CorneredGrid.md +29 -0
- package/docs/reference/components/layout/Mini.md +45 -0
- package/docs/reference/components/menus/MapBackground.md +32 -0
- package/docs/reference/components/menus/MapFilters.md +15 -0
- package/docs/reference/components/menus/MapLayers.md +15 -0
- package/docs/reference/components/menus/MapLegend.md +15 -0
- package/docs/reference/components/menus/PictureLegend.md +15 -0
- package/docs/reference/components/menus/PictureMetadata.md +15 -0
- package/docs/reference/components/menus/PlayerOptions.md +15 -0
- package/docs/reference/components/menus/QualityScoreDoc.md +15 -0
- package/docs/reference/components/menus/ReportForm.md +15 -0
- package/docs/reference/components/menus/ShareMenu.md +15 -0
- package/docs/reference/components/ui/Button.md +39 -0
- package/docs/reference/components/ui/ButtonGroup.md +36 -0
- package/docs/reference/components/ui/CopyButton.md +35 -0
- package/docs/reference/components/ui/Grade.md +32 -0
- package/docs/reference/components/ui/LinkButton.md +44 -0
- package/docs/reference/components/ui/Loader.md +54 -0
- package/docs/reference/components/ui/Map.md +214 -0
- package/docs/reference/components/ui/MapMore.md +233 -0
- package/docs/reference/components/ui/Photo.md +369 -0
- package/docs/reference/components/ui/Popup.md +56 -0
- package/docs/reference/components/ui/QualityScore.md +45 -0
- package/docs/reference/components/ui/SearchBar.md +63 -0
- package/docs/reference/components/ui/TogglableGroup.md +39 -0
- package/docs/reference/components/ui/widgets/GeoSearch.md +32 -0
- package/docs/reference/components/ui/widgets/Legend.md +32 -0
- package/docs/reference/components/ui/widgets/MapFiltersButton.md +33 -0
- package/docs/reference/components/ui/widgets/MapLayersButton.md +15 -0
- package/docs/reference/components/ui/widgets/Player.md +32 -0
- package/docs/reference/components/ui/widgets/Share.md +15 -0
- package/docs/reference/components/ui/widgets/Zoom.md +15 -0
- package/docs/reference/utils/API.md +311 -0
- package/docs/reference/utils/InitParameters.md +67 -0
- package/docs/reference/utils/URLHandler.md +102 -0
- package/docs/reference.md +73 -0
- package/docs/shortcuts.md +11 -0
- package/docs/tutorials/aerial_imagery.md +19 -0
- package/docs/tutorials/authentication.md +10 -0
- package/docs/tutorials/custom_widgets.md +64 -0
- package/docs/tutorials/map_style.md +27 -0
- package/docs/tutorials/migrate_v4.md +122 -0
- package/docs/tutorials/synced_coverage.md +42 -0
- package/mkdocs.yml +60 -5
- package/package.json +10 -7
- package/public/editor.html +21 -29
- package/public/index.html +3 -3
- package/public/map.html +19 -18
- package/public/viewer.html +18 -24
- package/public/widgets.html +265 -0
- package/scripts/doc.js +77 -0
- package/src/components/core/Basic.css +44 -0
- package/src/components/core/Basic.js +258 -0
- package/src/components/core/CoverageMap.css +9 -0
- package/src/components/core/CoverageMap.js +105 -0
- package/src/components/core/Editor.css +23 -0
- package/src/components/core/Editor.js +354 -0
- package/src/components/core/Viewer.css +109 -0
- package/src/components/core/Viewer.js +707 -0
- package/src/components/core/index.js +11 -0
- package/src/components/index.js +13 -0
- package/src/components/layout/CorneredGrid.js +109 -0
- package/src/components/layout/Mini.js +117 -0
- package/src/components/layout/index.js +7 -0
- package/src/components/menus/MapBackground.js +106 -0
- package/src/components/menus/MapFilters.js +386 -0
- package/src/components/menus/MapLayers.js +143 -0
- package/src/components/menus/MapLegend.js +54 -0
- package/src/components/menus/PictureLegend.js +103 -0
- package/src/components/menus/PictureMetadata.js +188 -0
- package/src/components/menus/PlayerOptions.js +96 -0
- package/src/components/menus/QualityScoreDoc.js +36 -0
- package/src/components/menus/ReportForm.js +133 -0
- package/src/components/menus/Share.js +228 -0
- package/src/components/menus/index.js +15 -0
- package/src/components/styles.js +365 -0
- package/src/components/ui/Button.js +75 -0
- package/src/components/ui/ButtonGroup.css +49 -0
- package/src/components/ui/ButtonGroup.js +68 -0
- package/src/components/ui/CopyButton.js +71 -0
- package/src/components/ui/Grade.js +54 -0
- package/src/components/ui/LinkButton.js +68 -0
- package/src/components/ui/Loader.js +188 -0
- package/src/components/{Map.css → ui/Map.css} +5 -17
- package/src/components/{Map.js → ui/Map.js} +114 -138
- package/src/components/ui/MapMore.js +324 -0
- package/src/components/{Photo.css → ui/Photo.css} +6 -6
- package/src/components/{Photo.js → ui/Photo.js} +279 -90
- package/src/components/ui/Popup.js +145 -0
- package/src/components/ui/QualityScore.js +152 -0
- package/src/components/ui/SearchBar.js +363 -0
- package/src/components/ui/TogglableGroup.js +162 -0
- package/src/components/ui/index.js +20 -0
- package/src/components/ui/widgets/GeoSearch.css +21 -0
- package/src/components/ui/widgets/GeoSearch.js +139 -0
- package/src/components/ui/widgets/Legend.js +51 -0
- package/src/components/ui/widgets/MapFiltersButton.js +104 -0
- package/src/components/ui/widgets/MapLayersButton.js +79 -0
- package/src/components/ui/widgets/Player.css +7 -0
- package/src/components/ui/widgets/Player.js +148 -0
- package/src/components/ui/widgets/Share.js +30 -0
- package/src/components/ui/widgets/Zoom.js +82 -0
- package/src/components/ui/widgets/index.js +12 -0
- package/src/img/panoramax.svg +13 -0
- package/src/img/switch_big.svg +20 -10
- package/src/index.js +6 -9
- package/src/translations/da.json +1 -1
- package/src/translations/de.json +1 -1
- package/src/translations/en.json +5 -3
- package/src/translations/eo.json +1 -1
- package/src/translations/es.json +1 -1
- package/src/translations/fr.json +5 -3
- package/src/translations/hu.json +1 -1
- package/src/translations/it.json +1 -1
- package/src/translations/ja.json +1 -1
- package/src/translations/nl.json +1 -1
- package/src/translations/pl.json +1 -1
- package/src/translations/sv.json +1 -1
- package/src/translations/zh_Hant.json +1 -1
- package/src/utils/API.js +74 -42
- package/src/utils/InitParameters.js +354 -0
- package/src/utils/URLHandler.js +364 -0
- package/src/utils/geocoder.js +116 -0
- package/src/utils/{I18n.js → i18n.js} +3 -1
- package/src/utils/index.js +11 -0
- package/src/utils/{Map.js → map.js} +216 -80
- package/src/utils/picture.js +433 -0
- package/src/utils/utils.js +315 -0
- package/src/utils/widgets.js +93 -0
- package/tests/components/ui/CopyButton.test.js +52 -0
- package/tests/components/ui/Loader.test.js +54 -0
- package/tests/components/{Map.test.js → ui/Map.test.js} +19 -61
- package/tests/components/{Photo.test.js → ui/Photo.test.js} +89 -57
- package/tests/components/ui/Popup.test.js +24 -0
- package/tests/components/ui/QualityScore.test.js +17 -0
- package/tests/components/ui/SearchBar.test.js +107 -0
- package/tests/components/ui/__snapshots__/CopyButton.test.js.snap +34 -0
- package/tests/components/ui/__snapshots__/Loader.test.js.snap +56 -0
- package/tests/components/{__snapshots__ → ui/__snapshots__}/Map.test.js.snap +11 -38
- package/tests/components/{__snapshots__ → ui/__snapshots__}/Photo.test.js.snap +57 -4
- package/tests/components/ui/__snapshots__/Popup.test.js.snap +29 -0
- package/tests/components/ui/__snapshots__/QualityScore.test.js.snap +11 -0
- package/tests/components/ui/__snapshots__/SearchBar.test.js.snap +65 -0
- package/tests/utils/API.test.js +1 -14
- package/tests/utils/InitParameters.test.js +485 -0
- package/tests/utils/URLHandler.test.js +350 -0
- package/tests/utils/__snapshots__/URLHandler.test.js.snap +21 -0
- package/tests/utils/__snapshots__/picture.test.js.snap +315 -0
- package/tests/utils/__snapshots__/widgets.test.js.snap +19 -0
- package/tests/utils/geocoder.test.js +37 -0
- package/tests/utils/{I18n.test.js → i18n.test.js} +1 -1
- package/tests/utils/map.test.js +67 -0
- package/tests/utils/picture.test.js +745 -0
- package/tests/utils/utils.test.js +288 -0
- package/tests/utils/widgets.test.js +90 -0
- package/docs/01_Start.md +0 -149
- package/docs/02_Usage.md +0 -831
- package/docs/04_Advanced_examples.md +0 -216
- package/src/Editor.css +0 -37
- package/src/Editor.js +0 -361
- package/src/StandaloneMap.js +0 -114
- package/src/Viewer.css +0 -203
- package/src/Viewer.js +0 -1246
- package/src/components/CoreView.css +0 -70
- package/src/components/CoreView.js +0 -175
- package/src/components/Loader.css +0 -74
- package/src/components/Loader.js +0 -120
- package/src/utils/Exif.js +0 -193
- package/src/utils/Utils.js +0 -631
- package/src/utils/Widgets.js +0 -562
- package/src/viewer/URLHash.js +0 -469
- package/src/viewer/Widgets.css +0 -880
- package/src/viewer/Widgets.js +0 -1470
- package/tests/Editor.test.js +0 -126
- package/tests/StandaloneMap.test.js +0 -45
- package/tests/Viewer.test.js +0 -366
- package/tests/__snapshots__/Editor.test.js.snap +0 -298
- package/tests/__snapshots__/StandaloneMap.test.js.snap +0 -30
- package/tests/__snapshots__/Viewer.test.js.snap +0 -195
- package/tests/components/CoreView.test.js +0 -92
- package/tests/components/Loader.test.js +0 -38
- package/tests/components/__snapshots__/Loader.test.js.snap +0 -15
- package/tests/utils/Exif.test.js +0 -124
- package/tests/utils/Map.test.js +0 -113
- package/tests/utils/Utils.test.js +0 -300
- package/tests/utils/Widgets.test.js +0 -107
- package/tests/utils/__snapshots__/Exif.test.js.snap +0 -43
- package/tests/utils/__snapshots__/Utils.test.js.snap +0 -41
- package/tests/utils/__snapshots__/Widgets.test.js.snap +0 -44
- package/tests/viewer/URLHash.test.js +0 -559
- package/tests/viewer/Widgets.test.js +0 -127
- package/tests/viewer/__snapshots__/URLHash.test.js.snap +0 -108
- package/tests/viewer/__snapshots__/Widgets.test.js.snap +0 -403
- /package/tests/utils/__snapshots__/{Map.test.js.snap → geocoder.test.js.snap} +0 -0
package/src/utils/API.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { TILES_PICTURES_ZOOM } from "./
|
|
2
|
-
import { BASE_PANORAMA_ID } from "./
|
|
1
|
+
import { TILES_PICTURES_ZOOM } from "./map";
|
|
2
|
+
import { BASE_PANORAMA_ID } from "./utils";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* API contains various utility functions to communicate with
|
|
5
|
+
* API contains various utility functions to communicate with Panoramax/STAC API
|
|
6
6
|
*
|
|
7
|
-
* @
|
|
8
|
-
* @
|
|
7
|
+
* @class Panoramax.utils.API
|
|
8
|
+
* @typicalname api
|
|
9
|
+
* @param {string} endpoint The endpoint. It corresponds to the <a href="https://github.com/radiantearth/stac-api-spec/blob/main/overview.md#example-landing-page">STAC landing page</a>, with all links describing the API capabilites.
|
|
10
|
+
* @param {object} [options] Options
|
|
9
11
|
* @param {string|object} [options.style] General map style
|
|
10
12
|
* @param {string} [options.tiles] API route serving pictures & sequences vector tiles
|
|
11
|
-
* @param {boolean} [options.skipReadLanding] True to not call API landing page automatically
|
|
13
|
+
* @param {boolean} [options.skipReadLanding=false] True to not call API landing page automatically
|
|
12
14
|
* @param {object} [options.fetch] Set custom options for fetch calls made against API ([same syntax as fetch options parameter](https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters))
|
|
13
|
-
* @param {string[]} [options.users] List of initial user IDs to load map styles for
|
|
14
|
-
* @private
|
|
15
|
+
* @param {string[]} [options.users] List of initial user IDs to load map styles for
|
|
15
16
|
*/
|
|
16
17
|
export default class API {
|
|
17
18
|
constructor(endpoint, options = {}) {
|
|
@@ -52,9 +53,11 @@ export default class API {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* @returns {Promise}
|
|
56
|
+
* Resolves when the API is ready to be used.
|
|
57
|
+
* @memberOf Panoramax.utils.API#
|
|
58
|
+
* @returns {Promise}
|
|
59
|
+
* @fulfil {string} "API is ready" when initialization is complete.
|
|
60
|
+
* @reject {string} Error message
|
|
58
61
|
*/
|
|
59
62
|
onceReady() {
|
|
60
63
|
if(this._isReady == -1) {
|
|
@@ -69,9 +72,9 @@ export default class API {
|
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* @returns {boolean} True if ready
|
|
75
|
+
* Checks if the API is ready to be used.
|
|
76
|
+
* @memberOf Panoramax.utils.API#
|
|
77
|
+
* @returns {boolean} True if the API is ready, false otherwise.
|
|
75
78
|
*/
|
|
76
79
|
isReady() {
|
|
77
80
|
return this._isReady == 1;
|
|
@@ -79,6 +82,7 @@ export default class API {
|
|
|
79
82
|
|
|
80
83
|
/**
|
|
81
84
|
* List of available features offered by API
|
|
85
|
+
* @memberOf Panoramax.utils.API#
|
|
82
86
|
* @returns {string[]} Keywords of enabled features
|
|
83
87
|
*/
|
|
84
88
|
getAvailableFeatures() {
|
|
@@ -87,6 +91,7 @@ export default class API {
|
|
|
87
91
|
|
|
88
92
|
/**
|
|
89
93
|
* List of unavailable features on API
|
|
94
|
+
* @memberOf Panoramax.utils.API#
|
|
90
95
|
* @returns {string[]} Keywords of disabled features
|
|
91
96
|
*/
|
|
92
97
|
getUnavailableFeatures() {
|
|
@@ -95,7 +100,7 @@ export default class API {
|
|
|
95
100
|
|
|
96
101
|
/**
|
|
97
102
|
* Interprets JSON landing page and store important information
|
|
98
|
-
*
|
|
103
|
+
* @memberOf Panoramax.utils.API#
|
|
99
104
|
* @private
|
|
100
105
|
*/
|
|
101
106
|
_parseLanding(landing, options) {
|
|
@@ -252,9 +257,12 @@ export default class API {
|
|
|
252
257
|
|
|
253
258
|
/**
|
|
254
259
|
* Loads all MapLibre Styles JSON needed at start.
|
|
260
|
+
* @memberOf Panoramax.utils.API#
|
|
255
261
|
* @param {string|object} style General map style
|
|
256
262
|
* @param {string[]} users List of user IDs to handle. Should include special user "geovisio" for general tiles loading.
|
|
257
|
-
* @returns {Promise}
|
|
263
|
+
* @returns {Promise}
|
|
264
|
+
* @fulfil {null} When style is ready.
|
|
265
|
+
* @private
|
|
258
266
|
*/
|
|
259
267
|
_loadMapStyles(style, users) {
|
|
260
268
|
const mapUsers = new Set(users || []);
|
|
@@ -298,7 +306,7 @@ export default class API {
|
|
|
298
306
|
|
|
299
307
|
/**
|
|
300
308
|
* Get the defaults fetch options to pass during API calls
|
|
301
|
-
*
|
|
309
|
+
* @memberOf Panoramax.utils.API#
|
|
302
310
|
* @private
|
|
303
311
|
* @returns {object} The fetch options
|
|
304
312
|
*/
|
|
@@ -310,7 +318,7 @@ export default class API {
|
|
|
310
318
|
|
|
311
319
|
/**
|
|
312
320
|
* Get the RequestTransformFunction for MapLibre to handle fetch options
|
|
313
|
-
*
|
|
321
|
+
* @memberOf Panoramax.utils.API#
|
|
314
322
|
* @private
|
|
315
323
|
* @returns {function} The RequestTransformFunction
|
|
316
324
|
*/
|
|
@@ -335,11 +343,13 @@ export default class API {
|
|
|
335
343
|
|
|
336
344
|
/**
|
|
337
345
|
* Get sequence GeoJSON representation
|
|
338
|
-
*
|
|
346
|
+
* @memberOf Panoramax.utils.API#
|
|
339
347
|
* @param {string} seqId The sequence ID
|
|
340
348
|
* @param {string} [next] The next link URL (only for internals)
|
|
341
349
|
* @param {object} [data] The previous dataset (only for internals)
|
|
342
|
-
* @returns {Promise}
|
|
350
|
+
* @returns {Promise}
|
|
351
|
+
* @fulfil {object} Sequence GeoJSON
|
|
352
|
+
* @reject {Error} If API is not ready or for any network issue
|
|
343
353
|
*/
|
|
344
354
|
async getSequenceItems(seqId, next = null, data = null) {
|
|
345
355
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -368,7 +378,7 @@ export default class API {
|
|
|
368
378
|
|
|
369
379
|
/**
|
|
370
380
|
* Get full URL for listing pictures around a specific location
|
|
371
|
-
*
|
|
381
|
+
* @memberOf Panoramax.utils.API#
|
|
372
382
|
* @param {number} lat Latitude
|
|
373
383
|
* @param {number} lon Longitude
|
|
374
384
|
* @param {number} [factor] The radius to search around (in degrees)
|
|
@@ -391,13 +401,14 @@ export default class API {
|
|
|
391
401
|
|
|
392
402
|
/**
|
|
393
403
|
* Get list of pictures around a specific location
|
|
394
|
-
*
|
|
404
|
+
* @memberOf Panoramax.utils.API#
|
|
395
405
|
* @param {number} lat Latitude
|
|
396
406
|
* @param {number} lon Longitude
|
|
397
407
|
* @param {number} [factor] The radius to search around (in degrees)
|
|
398
408
|
* @param {number} [limit] Max amount of pictures to retrieve
|
|
399
409
|
* @param {string} [seqId] The sequence ID to filter on (by default, no filter)
|
|
400
|
-
* @returns {
|
|
410
|
+
* @returns {Promise}
|
|
411
|
+
* @fulfil {object} The GeoJSON feature collection
|
|
401
412
|
*/
|
|
402
413
|
getPicturesAroundCoordinates(lat, lon, factor, limit, seqId) {
|
|
403
414
|
return fetch(this.getPicturesAroundCoordinatesUrl(lat, lon, factor, limit, seqId), this._getFetchOptions())
|
|
@@ -406,10 +417,11 @@ export default class API {
|
|
|
406
417
|
|
|
407
418
|
/**
|
|
408
419
|
* Get full URL for retrieving a specific picture metadata
|
|
409
|
-
*
|
|
420
|
+
* @memberOf Panoramax.utils.API#
|
|
410
421
|
* @param {string} picId The picture unique identifier
|
|
411
422
|
* @param {string} [seqId] The sequence ID
|
|
412
423
|
* @returns {string} The corresponding URL
|
|
424
|
+
* @throws {Error} If API is not ready
|
|
413
425
|
*/
|
|
414
426
|
getPictureMetadataUrl(picId, seqId) {
|
|
415
427
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -422,8 +434,10 @@ export default class API {
|
|
|
422
434
|
|
|
423
435
|
/**
|
|
424
436
|
* Get JSON style for general vector tiles
|
|
425
|
-
* @
|
|
426
|
-
* @
|
|
437
|
+
* @memberOf Panoramax.utils.API#
|
|
438
|
+
* @return {Promise|object} Promise if first load, MapLibre JSON style otherwise
|
|
439
|
+
* @fulfil {object} The MapLibre JSON style
|
|
440
|
+
* @reject {Error} If API is not ready, or no style defined.
|
|
427
441
|
*/
|
|
428
442
|
getMapStyle() {
|
|
429
443
|
if(this.isReady()) { return this.mapStyle; }
|
|
@@ -471,10 +485,12 @@ export default class API {
|
|
|
471
485
|
|
|
472
486
|
/**
|
|
473
487
|
* Get JSON style for specific-user vector tiles
|
|
488
|
+
* @memberOf Panoramax.utils.API#
|
|
474
489
|
* @param {string} userId The user UUID
|
|
475
490
|
* @param {boolean} [skipReadyCheck=false] Skip check for API readyness
|
|
476
|
-
* @return {Promise}
|
|
477
|
-
* @
|
|
491
|
+
* @return {Promise}
|
|
492
|
+
* @fulfil {object} The MapLibre JSON style
|
|
493
|
+
* @reject {Error} If API is not ready, or no style defined.
|
|
478
494
|
*/
|
|
479
495
|
getUserMapStyle(userId, skipReadyCheck = false) {
|
|
480
496
|
if(!skipReadyCheck && !this.isReady()) { return Promise.reject(new Error("API is not ready to use")); }
|
|
@@ -515,9 +531,10 @@ export default class API {
|
|
|
515
531
|
|
|
516
532
|
/**
|
|
517
533
|
* Find the thumbnail URL for a given picture
|
|
518
|
-
*
|
|
534
|
+
* @memberOf Panoramax.utils.API#
|
|
519
535
|
* @param {object} picture The picture GeoJSON feature
|
|
520
536
|
* @returns {string} The thumbnail URL, or null if not found
|
|
537
|
+
* @throws {Error} If API is not ready
|
|
521
538
|
* @private
|
|
522
539
|
*/
|
|
523
540
|
findThumbnailInPictureFeature(picture) {
|
|
@@ -538,10 +555,12 @@ export default class API {
|
|
|
538
555
|
|
|
539
556
|
/**
|
|
540
557
|
* Get a picture thumbnail URL for a given sequence
|
|
541
|
-
*
|
|
558
|
+
* @memberOf Panoramax.utils.API#
|
|
542
559
|
* @param {string} seqId The sequence ID
|
|
543
560
|
* @param {object} [seq] The sequence metadata (with links) if already loaded
|
|
544
|
-
* @returns {Promise}
|
|
561
|
+
* @returns {Promise}
|
|
562
|
+
* @fulfil {string|null} Promise resolving on the picture thumbnail URL, or null if not found
|
|
563
|
+
* @throws {Error} If API is not ready
|
|
545
564
|
*/
|
|
546
565
|
getPictureThumbnailURLForSequence(seqId, seq) {
|
|
547
566
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -575,10 +594,12 @@ export default class API {
|
|
|
575
594
|
|
|
576
595
|
/**
|
|
577
596
|
* Get thumbnail URL for a specific picture
|
|
578
|
-
*
|
|
597
|
+
* @memberOf Panoramax.utils.API#
|
|
579
598
|
* @param {string} picId The picture unique identifier
|
|
580
599
|
* @param {string} [seqId] The sequence ID
|
|
581
|
-
* @returns {Promise}
|
|
600
|
+
* @returns {Promise}
|
|
601
|
+
* @fulfil {string|null} The corresponding URL on resolve, or null if no thumbnail could be found
|
|
602
|
+
* @throws {Error} If API is not ready
|
|
582
603
|
*/
|
|
583
604
|
getPictureThumbnailURL(picId, seqId) {
|
|
584
605
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -610,9 +631,10 @@ export default class API {
|
|
|
610
631
|
|
|
611
632
|
/**
|
|
612
633
|
* Get the RSS feed URL with map parameters (if map is enabled)
|
|
613
|
-
*
|
|
634
|
+
* @memberOf Panoramax.utils.API#
|
|
614
635
|
* @param {LngLatBounds} [bbox] The map current bounding box, or null if not available
|
|
615
|
-
* @returns {string} The URL, or null if no RSS feed is available
|
|
636
|
+
* @returns {string|null} The URL, or null if no RSS feed is available
|
|
637
|
+
* @throws {Error} If API is not ready
|
|
616
638
|
*/
|
|
617
639
|
getRSSURL(bbox) {
|
|
618
640
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -632,9 +654,10 @@ export default class API {
|
|
|
632
654
|
|
|
633
655
|
/**
|
|
634
656
|
* Get full URL for retrieving a specific sequence metadata
|
|
635
|
-
*
|
|
657
|
+
* @memberOf Panoramax.utils.API#
|
|
636
658
|
* @param {string} seqId The sequence ID
|
|
637
659
|
* @returns {string} The corresponding URL
|
|
660
|
+
* @throws {Error} If API is not ready
|
|
638
661
|
*/
|
|
639
662
|
getSequenceMetadataUrl(seqId) {
|
|
640
663
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -643,8 +666,9 @@ export default class API {
|
|
|
643
666
|
|
|
644
667
|
/**
|
|
645
668
|
* Get available data bounding box
|
|
646
|
-
*
|
|
669
|
+
* @memberOf Panoramax.utils.API#
|
|
647
670
|
* @returns {LngLatBoundsLike} The bounding box or null if not available
|
|
671
|
+
* @throws {Error} If API is not ready
|
|
648
672
|
*/
|
|
649
673
|
getDataBbox() {
|
|
650
674
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -654,8 +678,11 @@ export default class API {
|
|
|
654
678
|
|
|
655
679
|
/**
|
|
656
680
|
* Look for user ID based on user name query
|
|
681
|
+
* @memberOf Panoramax.utils.API#
|
|
657
682
|
* @param {string} query The user name to look for
|
|
658
|
-
* @returns {Promise}
|
|
683
|
+
* @returns {Promise}
|
|
684
|
+
* @fulfil {object|null} List of potential users
|
|
685
|
+
* @throws {Error} If API is not ready or user search not available
|
|
659
686
|
*/
|
|
660
687
|
searchUsers(query) {
|
|
661
688
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -670,8 +697,11 @@ export default class API {
|
|
|
670
697
|
|
|
671
698
|
/**
|
|
672
699
|
* Get user name based on its ID
|
|
700
|
+
* @memberOf Panoramax.utils.API#
|
|
673
701
|
* @param {string} userId The user UUID
|
|
674
|
-
* @returns {Promise}
|
|
702
|
+
* @returns {Promise}
|
|
703
|
+
* @throws {Error} If API is not ready
|
|
704
|
+
* @fulfil {string|null} The user name (or null if not found)
|
|
675
705
|
*/
|
|
676
706
|
getUserName(userId) {
|
|
677
707
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -686,8 +716,10 @@ export default class API {
|
|
|
686
716
|
|
|
687
717
|
/**
|
|
688
718
|
* Send a report to API
|
|
719
|
+
* @memberOf Panoramax.utils.API#
|
|
689
720
|
* @param {object} data The input form data
|
|
690
|
-
* @returns {Promise}
|
|
721
|
+
* @returns {Promise}
|
|
722
|
+
* @fulfil {object} The JSON API response
|
|
691
723
|
*/
|
|
692
724
|
sendReport(data) {
|
|
693
725
|
if(!this.isReady()) { throw new Error("API is not ready to use"); }
|
|
@@ -715,7 +747,7 @@ export default class API {
|
|
|
715
747
|
|
|
716
748
|
/**
|
|
717
749
|
* Checks URL string validity
|
|
718
|
-
*
|
|
750
|
+
* @memberOf Panoramax.utils.API
|
|
719
751
|
* @param {string} str The URL to check
|
|
720
752
|
* @returns {boolean} True if valid
|
|
721
753
|
*/
|
|
@@ -733,7 +765,7 @@ export default class API {
|
|
|
733
765
|
|
|
734
766
|
/**
|
|
735
767
|
* Checks picture or sequence ID validity
|
|
736
|
-
*
|
|
768
|
+
* @memberOf Panoramax.utils.API
|
|
737
769
|
* @param {string} id The ID to check
|
|
738
770
|
* @returns {boolean} True if valid
|
|
739
771
|
* @throws {Error} If not valid
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
export const MAP_FILTERS_JS2URL = {
|
|
2
|
+
"minDate": "date_from",
|
|
3
|
+
"maxDate": "date_to",
|
|
4
|
+
"pic_type": "pic_type",
|
|
5
|
+
"camera": "camera",
|
|
6
|
+
"theme": "theme",
|
|
7
|
+
"qualityscore": "pic_score",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const MAP_FILTERS_URL2JS = Object.fromEntries(Object.entries(MAP_FILTERS_JS2URL).map(v => [v[1], v[0]]));
|
|
11
|
+
const MAP_NONE = ["none", "null", "false", false];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Merges all URL parameters and component attributes into a single set of coherent settings.
|
|
15
|
+
*
|
|
16
|
+
* @class Panoramax.utils.InitParameters
|
|
17
|
+
* @param {object} [componentAttrs] HTML attributes from parent component
|
|
18
|
+
* @param {object} [urlParams] Parameters extracted from URL
|
|
19
|
+
*/
|
|
20
|
+
export default class InitParameters { // eslint-disable-line import/no-unused-modules
|
|
21
|
+
constructor(componentAttrs = {}, urlParams = {}) {
|
|
22
|
+
// Skip URL parameters if disabled by component
|
|
23
|
+
if(componentAttrs["url-parameters"] === "false") { urlParams = {}; }
|
|
24
|
+
|
|
25
|
+
// Sanitize PSV parameters
|
|
26
|
+
let componentPsv = {};
|
|
27
|
+
if(typeof componentAttrs?.psv === "object") { componentPsv = componentAttrs.psv; }
|
|
28
|
+
|
|
29
|
+
// Sanitize Map parameters
|
|
30
|
+
let componentMap = {};
|
|
31
|
+
if(typeof componentAttrs?.map === "object") { componentMap = componentAttrs.map; }
|
|
32
|
+
|
|
33
|
+
// Extract map position from URL
|
|
34
|
+
let urlMap = urlParams.map && urlParams.map !== "none" ? getMapPositionFromString(urlParams.map) : null;
|
|
35
|
+
|
|
36
|
+
// Parse and prioritize all parameters
|
|
37
|
+
// - Overlapping between URL & component
|
|
38
|
+
let map = MAP_NONE.includes(urlParams.map) || MAP_NONE.includes(componentAttrs.map) ? false : true;
|
|
39
|
+
let focus = urlParams.focus || componentAttrs.focus;
|
|
40
|
+
let picture = urlParams.pic || componentAttrs.picture;
|
|
41
|
+
let users = urlParams.users || componentAttrs.users;
|
|
42
|
+
let psv_speed = urlParams.speed || componentPsv?.transitionDuration;
|
|
43
|
+
let psv_nav = urlParams.nav || componentPsv?.picturesNavigation;
|
|
44
|
+
let map_theme = urlParams.theme || componentMap.theme;
|
|
45
|
+
let map_background = urlParams.background || componentMap.background;
|
|
46
|
+
let map_center = urlMap?.center || componentMap.center;
|
|
47
|
+
let map_zoom = urlMap?.zoom || componentMap.zoom;
|
|
48
|
+
let map_pitch = urlMap?.pitch || componentMap.pitch;
|
|
49
|
+
let map_bearing = urlMap?.bearing || componentMap.bearing;
|
|
50
|
+
|
|
51
|
+
// - Component only
|
|
52
|
+
let geocoder = componentAttrs.geocoder;
|
|
53
|
+
let widgets = componentAttrs.widgets;
|
|
54
|
+
let sequence = componentAttrs.sequence;
|
|
55
|
+
let fetchOptions = componentAttrs.fetchOptions;
|
|
56
|
+
let style = componentAttrs.style;
|
|
57
|
+
let lang = componentAttrs.lang;
|
|
58
|
+
let endpoint = componentAttrs.endpoint;
|
|
59
|
+
let map_raster = componentMap.raster;
|
|
60
|
+
|
|
61
|
+
// - URL only
|
|
62
|
+
let psv_xyz = urlParams.xyz;
|
|
63
|
+
let map_date_from = urlParams.date_from;
|
|
64
|
+
let map_date_to = urlParams.date_to;
|
|
65
|
+
let map_pic_type = urlParams.pic_type;
|
|
66
|
+
let map_camera = urlParams.camera;
|
|
67
|
+
let map_pic_score = urlParams.pic_score;
|
|
68
|
+
|
|
69
|
+
// Check coherence
|
|
70
|
+
if(!["map", "meta", "pic"].includes(focus)) {
|
|
71
|
+
console.warn("Invalid value for parameter focus:", focus);
|
|
72
|
+
focus = map && !picture ? "map" : "pic";
|
|
73
|
+
}
|
|
74
|
+
else if(focus === "map" && !map) {
|
|
75
|
+
console.warn("Parameter focus can't be 'map' as map is disabled");
|
|
76
|
+
focus = "pic";
|
|
77
|
+
}
|
|
78
|
+
if(map_background == "aerial" && !map_raster) {
|
|
79
|
+
console.warn("Parameter background can't be 'aerial' as no aerial imagery is available");
|
|
80
|
+
map_background = "streets";
|
|
81
|
+
}
|
|
82
|
+
if(map && !picture) {
|
|
83
|
+
focus = "map";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Put all attributes in appropriate container
|
|
87
|
+
this._parentInit = { map, users, fetchOptions, style, lang, endpoint };
|
|
88
|
+
this._parentPostInit = { focus, picture, sequence, geocoder, widgets, forceFocus: true };
|
|
89
|
+
|
|
90
|
+
this._psvInit = Object.fromEntries(
|
|
91
|
+
Object.entries(componentPsv).filter(
|
|
92
|
+
([k,]) => !["transitionDuration", "picturesNavigation"].includes(k)
|
|
93
|
+
)
|
|
94
|
+
);
|
|
95
|
+
this._psvAny = {
|
|
96
|
+
transitionDuration: psv_speed,
|
|
97
|
+
picturesNavigation: psv_nav,
|
|
98
|
+
};
|
|
99
|
+
this._psvPostInit = { xyz: psv_xyz };
|
|
100
|
+
|
|
101
|
+
this._mapInit = { raster: map_raster };
|
|
102
|
+
this._mapAny = {
|
|
103
|
+
theme: map_theme,
|
|
104
|
+
background: map_background,
|
|
105
|
+
center: map_center,
|
|
106
|
+
zoom: map_zoom,
|
|
107
|
+
pitch: map_pitch,
|
|
108
|
+
bearing: map_bearing,
|
|
109
|
+
users,
|
|
110
|
+
};
|
|
111
|
+
this._mapPostInit = {
|
|
112
|
+
date_from: map_date_from,
|
|
113
|
+
date_to: map_date_to,
|
|
114
|
+
pic_type: map_pic_type,
|
|
115
|
+
camera: map_camera,
|
|
116
|
+
pic_score: map_pic_score,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Cleans out undefined values from object.
|
|
122
|
+
* @param {object} obj The input object
|
|
123
|
+
* @returns {object} Clean object without undefined values
|
|
124
|
+
* @private
|
|
125
|
+
*/
|
|
126
|
+
_sanitize(obj) {
|
|
127
|
+
return Object.fromEntries(Object.entries(obj).filter(([,v]) => v !== undefined));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get core component initialization parameters.
|
|
132
|
+
* They must be passed as soon as possible.
|
|
133
|
+
* @memberof Panoramax.utils.InitParameters#
|
|
134
|
+
*/
|
|
135
|
+
getParentInit() {
|
|
136
|
+
return this._sanitize(this._parentInit);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get core component post-initialization parameters.
|
|
141
|
+
* They must be passed after first rendering or init.
|
|
142
|
+
* @memberof Panoramax.utils.InitParameters#
|
|
143
|
+
*/
|
|
144
|
+
getParentPostInit() {
|
|
145
|
+
return this._sanitize(this._parentPostInit);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get Photo Sphere Viewer initialization parameters.
|
|
150
|
+
* They must be passed as soon as possible.
|
|
151
|
+
* @memberof Panoramax.utils.InitParameters#
|
|
152
|
+
*/
|
|
153
|
+
getPSVInit() {
|
|
154
|
+
return this._sanitize(Object.assign({}, this._psvInit, this._psvAny));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get Photo Sphere Viewer post-initialization parameters.
|
|
159
|
+
* They must be passed after first rendering or init.
|
|
160
|
+
* @memberof Panoramax.utils.InitParameters#
|
|
161
|
+
*/
|
|
162
|
+
getPSVPostInit() {
|
|
163
|
+
return this._sanitize(Object.assign({}, this._psvPostInit, this._psvAny));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get MapLibre GL initialization parameters.
|
|
168
|
+
* They must be passed as soon as possible.
|
|
169
|
+
* @memberof Panoramax.utils.InitParameters#
|
|
170
|
+
*/
|
|
171
|
+
getMapInit() {
|
|
172
|
+
return this._sanitize(Object.assign({}, this._mapInit, this._mapAny));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get MapLibre GL post-initialization parameters.
|
|
177
|
+
* They must be passed after first rendering or init.
|
|
178
|
+
* @memberof Panoramax.utils.InitParameters#
|
|
179
|
+
*/
|
|
180
|
+
getMapPostInit() {
|
|
181
|
+
return this._sanitize(Object.assign({}, this._mapPostInit, this._mapAny));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Reads public properties from LitElement and returns a classic key-value object.
|
|
186
|
+
* @param {class} compClass The component class (with static `properties` definition)
|
|
187
|
+
* @param {LitElement} comp The component itself
|
|
188
|
+
*/
|
|
189
|
+
static GetComponentProperties(compClass, comp) {
|
|
190
|
+
const props = {};
|
|
191
|
+
for(let classK in compClass.properties) {
|
|
192
|
+
let classV = compClass.properties[classK];
|
|
193
|
+
if(!classV.state && comp[classK] != null) {
|
|
194
|
+
props[classK] = comp[classK];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return props;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Extracts map center, zoom & more from formatted string.
|
|
203
|
+
* @param {string} str The map position as hash string
|
|
204
|
+
* @param {Panoramax.components.ui.Map} [map] The current map
|
|
205
|
+
* @returns {object} { center, zoom, pitch, bearing }
|
|
206
|
+
* @private
|
|
207
|
+
*/
|
|
208
|
+
export function getMapPositionFromString(str, map) {
|
|
209
|
+
const loc = (str || "").split("/");
|
|
210
|
+
if (loc.length >= 3 && !loc.some(v => isNaN(v))) {
|
|
211
|
+
const res = {
|
|
212
|
+
center: [+loc[2], +loc[1]],
|
|
213
|
+
zoom: +loc[0],
|
|
214
|
+
pitch: +(loc[4] || 0)
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
if(map) {
|
|
218
|
+
res.bearing = map.dragRotate.isEnabled() && map.touchZoomRotate.isEnabled() ? +(loc[3] || 0) : map.getBearing();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return res;
|
|
222
|
+
}
|
|
223
|
+
else { return null; }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Extracts from string xyz position
|
|
228
|
+
* @param {string} str The xyz position as hash string
|
|
229
|
+
* @returns {object} { x, y, z }
|
|
230
|
+
* @private
|
|
231
|
+
*/
|
|
232
|
+
export function xyzParamToPSVPosition(str) {
|
|
233
|
+
const loc = (str || "").split("/");
|
|
234
|
+
if (loc.length === 3 && !loc.some(v => isNaN(v))) {
|
|
235
|
+
const res = {
|
|
236
|
+
x: +loc[0],
|
|
237
|
+
y: +loc[1],
|
|
238
|
+
z: +loc[2]
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
return res;
|
|
242
|
+
}
|
|
243
|
+
else { return null; }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Extracts from hash parsed keys all map filters values
|
|
248
|
+
* @param {*} vals Hash keys
|
|
249
|
+
* @returns {object} Map filters
|
|
250
|
+
* @private
|
|
251
|
+
*/
|
|
252
|
+
export function paramsToMapFilters(vals) {
|
|
253
|
+
const newMapFilters = {};
|
|
254
|
+
for(let k in MAP_FILTERS_URL2JS) {
|
|
255
|
+
if(vals[k]) {
|
|
256
|
+
newMapFilters[MAP_FILTERS_URL2JS[k]] = vals[k];
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if(newMapFilters.qualityscore) {
|
|
260
|
+
let values = newMapFilters.qualityscore.split("");
|
|
261
|
+
const mapping = {"A": 5, "B": 4, "C": 3, "D": 2, "E": 1};
|
|
262
|
+
newMapFilters.qualityscore = values.map(v => mapping[v]);
|
|
263
|
+
}
|
|
264
|
+
return newMapFilters;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Change PSV current state based on standardized parameters.
|
|
269
|
+
* @param {Photo} psv The Photo Sphere Viewer component to change.
|
|
270
|
+
* @param {object} params The parameters to apply.
|
|
271
|
+
*/
|
|
272
|
+
export function alterPSVState(psv, params) {
|
|
273
|
+
// Change xyz position
|
|
274
|
+
if(params.xyz) {
|
|
275
|
+
psv.addEventListener("picture-loaded", () => {
|
|
276
|
+
const coords = xyzParamToPSVPosition(params.xyz);
|
|
277
|
+
psv.setXYZ(coords.x, coords.y, coords.z);
|
|
278
|
+
}, {once: true});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Change transitionDuration
|
|
282
|
+
if(params.transitionDuration !== undefined) {
|
|
283
|
+
psv.setTransitionDuration(params.transitionDuration);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Change pictures navigation mode
|
|
287
|
+
if(["pic", "any", "seq"].includes(params.picturesNavigation)) {
|
|
288
|
+
psv.setPicturesNavigation(params.picturesNavigation);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Change MapLibre GL current state based on standardized parameters.
|
|
294
|
+
* @param {Map} map The MapLibre component to change.
|
|
295
|
+
* @param {object} params The parameters to apply.
|
|
296
|
+
*/
|
|
297
|
+
export function alterMapState(map, params) {
|
|
298
|
+
// Map position
|
|
299
|
+
const mapOpts = getMapPositionFromString(params.map, map);
|
|
300
|
+
if(mapOpts) {
|
|
301
|
+
map.jumpTo(mapOpts);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Visible users
|
|
305
|
+
let vu = Array.isArray(params.users) ? params.users : (params.users || "").split(",");
|
|
306
|
+
if(vu.length === 0 || (vu.length === 1 && vu[0].trim() === "")) { vu = ["geovisio"]; }
|
|
307
|
+
map.setVisibleUsers(vu);
|
|
308
|
+
|
|
309
|
+
// Change map filters
|
|
310
|
+
map.setFilters(paramsToMapFilters(params));
|
|
311
|
+
|
|
312
|
+
// Change map background
|
|
313
|
+
if(["aerial", "streets"].includes(params.background)) {
|
|
314
|
+
map.setBackground(params.background);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Change Viewer current state based on standardized parameters.
|
|
320
|
+
* @param {Viewer} viewer The Viewer component to change.
|
|
321
|
+
* @param {object} params The parameters to apply.
|
|
322
|
+
*/
|
|
323
|
+
export function alterViewerState(viewer, params) {
|
|
324
|
+
// Restore selected picture
|
|
325
|
+
if(params.picture) {
|
|
326
|
+
const picIds = params.picture.split(";"); // Handle multiple IDs coming from OSM
|
|
327
|
+
if(picIds.length > 1) {
|
|
328
|
+
console.warn("Multiple picture IDs passed in URL, only first one kept");
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Post-load changes
|
|
332
|
+
if(params.focus && params.focus == "meta") {
|
|
333
|
+
viewer.psv.addEventListener("picture-loaded", () => viewer._showPictureMetadata(), { once: true });
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
viewer.select(null, picIds[0]);
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
viewer.select();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Change focus
|
|
343
|
+
if(params.focus === "map" && viewer?.map) {
|
|
344
|
+
viewer.setPopup(false);
|
|
345
|
+
viewer._setFocus("map", null, params.forceFocus);
|
|
346
|
+
}
|
|
347
|
+
else if(params.focus === "pic") {
|
|
348
|
+
viewer.setPopup(false);
|
|
349
|
+
viewer._setFocus("pic", null, params.forceFocus);
|
|
350
|
+
}
|
|
351
|
+
else if(params.focus && params.focus === "meta") {
|
|
352
|
+
viewer._setFocus("pic", null, params.forceFocus);
|
|
353
|
+
}
|
|
354
|
+
}
|