@panoramax/web-viewer 5.0.0-develop-d26305dd → 5.0.0-develop-be5ba1a7

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.
Files changed (153) hide show
  1. package/build/cjs/index.js +1 -1
  2. package/build/cjs/index_photoviewer.js +1 -1
  3. package/build/esm/components/core/Basic.js +1 -1
  4. package/build/esm/translations/el.json +92 -1
  5. package/package.json +1 -1
  6. package/build/bundle.cjs +0 -3399
  7. package/build/bundle.cjs.map +0 -1
  8. package/build/bundle_photoviewer.cjs +0 -2510
  9. package/build/bundle_photoviewer.cjs.map +0 -1
  10. package/build/components/core/Basic.css +0 -56
  11. package/build/components/core/Basic.js +0 -378
  12. package/build/components/core/CoverageMap.css +0 -10
  13. package/build/components/core/CoverageMap.js +0 -169
  14. package/build/components/core/Editor.css +0 -33
  15. package/build/components/core/Editor.js +0 -398
  16. package/build/components/core/PhotoViewer.css +0 -70
  17. package/build/components/core/PhotoViewer.js +0 -650
  18. package/build/components/core/Viewer.css +0 -130
  19. package/build/components/core/Viewer.js +0 -711
  20. package/build/components/core/index.js +0 -10
  21. package/build/components/index.js +0 -11
  22. package/build/components/index_photoviewer.js +0 -6
  23. package/build/components/layout/BottomDrawer.js +0 -258
  24. package/build/components/layout/CorneredGrid.js +0 -143
  25. package/build/components/layout/Mini.js +0 -121
  26. package/build/components/layout/Tabs.js +0 -140
  27. package/build/components/layout/index.js +0 -9
  28. package/build/components/menus/LocationPrecisionDoc.js +0 -42
  29. package/build/components/menus/MapBackground.js +0 -110
  30. package/build/components/menus/MapFilters.js +0 -567
  31. package/build/components/menus/MapLayers.js +0 -238
  32. package/build/components/menus/MapLegend.js +0 -68
  33. package/build/components/menus/MiniPictureLegend.js +0 -73
  34. package/build/components/menus/PictureLegend.js +0 -379
  35. package/build/components/menus/PictureMetadata.js +0 -380
  36. package/build/components/menus/PlayerOptions.js +0 -93
  37. package/build/components/menus/QualityScoreDoc.js +0 -42
  38. package/build/components/menus/ReportForm.js +0 -132
  39. package/build/components/menus/SemanticsDoc.js +0 -38
  40. package/build/components/menus/SemanticsDownload.js +0 -33
  41. package/build/components/menus/SemanticsFilters.js +0 -153
  42. package/build/components/menus/SemanticsList.js +0 -413
  43. package/build/components/menus/SemanticsMetadata.js +0 -368
  44. package/build/components/menus/Share.js +0 -105
  45. package/build/components/menus/index.js +0 -22
  46. package/build/components/menus/index_photoviewer.js +0 -11
  47. package/build/components/styles.js +0 -557
  48. package/build/components/ui/AnnotationsSwitch.js +0 -159
  49. package/build/components/ui/Button.js +0 -77
  50. package/build/components/ui/ButtonGroup.css +0 -59
  51. package/build/components/ui/ButtonGroup.js +0 -69
  52. package/build/components/ui/CopyButton.js +0 -110
  53. package/build/components/ui/Grade.js +0 -54
  54. package/build/components/ui/GradeFilter.js +0 -122
  55. package/build/components/ui/IconSwitch.js +0 -193
  56. package/build/components/ui/LinkButton.js +0 -67
  57. package/build/components/ui/ListGroup.js +0 -66
  58. package/build/components/ui/ListItem.js +0 -90
  59. package/build/components/ui/Loader.js +0 -203
  60. package/build/components/ui/Map.css +0 -63
  61. package/build/components/ui/Map.js +0 -853
  62. package/build/components/ui/MapMore.js +0 -175
  63. package/build/components/ui/Photo.css +0 -50
  64. package/build/components/ui/Photo.js +0 -1502
  65. package/build/components/ui/Popup.js +0 -145
  66. package/build/components/ui/ProgressBar.js +0 -104
  67. package/build/components/ui/QualityScore.js +0 -147
  68. package/build/components/ui/SearchBar.js +0 -374
  69. package/build/components/ui/SemanticsEditor.js +0 -191
  70. package/build/components/ui/SemanticsTable.js +0 -88
  71. package/build/components/ui/Switch.js +0 -139
  72. package/build/components/ui/TogglableGroup.js +0 -157
  73. package/build/components/ui/index.js +0 -29
  74. package/build/components/ui/index_photoviewer.js +0 -21
  75. package/build/components/ui/widgets/CopyCoordinates.js +0 -75
  76. package/build/components/ui/widgets/GeoSearch.css +0 -21
  77. package/build/components/ui/widgets/GeoSearch.js +0 -150
  78. package/build/components/ui/widgets/Legend.js +0 -190
  79. package/build/components/ui/widgets/LevelSelect.css +0 -51
  80. package/build/components/ui/widgets/LevelSelect.js +0 -143
  81. package/build/components/ui/widgets/MapFiltersButton.js +0 -114
  82. package/build/components/ui/widgets/MapLayersButton.js +0 -79
  83. package/build/components/ui/widgets/OSMEditors.js +0 -155
  84. package/build/components/ui/widgets/PictureLegendActions.js +0 -99
  85. package/build/components/ui/widgets/Player.css +0 -7
  86. package/build/components/ui/widgets/Player.js +0 -154
  87. package/build/components/ui/widgets/SemanticsFiltersButton.js +0 -65
  88. package/build/components/ui/widgets/Zoom.js +0 -84
  89. package/build/components/ui/widgets/index.js +0 -16
  90. package/build/components/ui/widgets/index_photoviewer.js +0 -7
  91. package/build/img/arrow_360.svg +0 -14
  92. package/build/img/arrow_flat.svg +0 -11
  93. package/build/img/arrow_triangle.svg +0 -9
  94. package/build/img/arrow_turn.svg +0 -8
  95. package/build/img/bg_aerial.jpg +0 -0
  96. package/build/img/bg_streets.jpg +0 -0
  97. package/build/img/loader_base.jpg +0 -0
  98. package/build/img/logo_dead.svg +0 -91
  99. package/build/img/marker.svg +0 -17
  100. package/build/img/marker_blue.svg +0 -20
  101. package/build/img/osm.svg +0 -49
  102. package/build/img/panoramax.svg +0 -13
  103. package/build/img/switch_big.svg +0 -54
  104. package/build/img/switch_mini.svg +0 -48
  105. package/build/img/wd.svg +0 -1
  106. package/build/index_photoviewer.js +0 -4
  107. package/build/package.json +0 -148
  108. package/build/servers.js +0 -14
  109. package/build/translations/ar.json +0 -1
  110. package/build/translations/be.json +0 -257
  111. package/build/translations/br.json +0 -81
  112. package/build/translations/cy.json +0 -117
  113. package/build/translations/da.json +0 -300
  114. package/build/translations/de.json +0 -309
  115. package/build/translations/en.json +0 -294
  116. package/build/translations/eo.json +0 -235
  117. package/build/translations/es.json +0 -292
  118. package/build/translations/fi.json +0 -1
  119. package/build/translations/fr.json +0 -294
  120. package/build/translations/hr.json +0 -294
  121. package/build/translations/hu.json +0 -294
  122. package/build/translations/it.json +0 -306
  123. package/build/translations/ja.json +0 -182
  124. package/build/translations/ko.json +0 -1
  125. package/build/translations/nl.json +0 -305
  126. package/build/translations/nn.json +0 -1
  127. package/build/translations/pl.json +0 -169
  128. package/build/translations/pt.json +0 -296
  129. package/build/translations/pt_BR.json +0 -304
  130. package/build/translations/sv.json +0 -182
  131. package/build/translations/ti.json +0 -9
  132. package/build/translations/tr.json +0 -297
  133. package/build/translations/uk.json +0 -268
  134. package/build/translations/zh_Hant.json +0 -309
  135. package/build/utils/API.js +0 -928
  136. package/build/utils/InitParameters.js +0 -521
  137. package/build/utils/MapStyleComposer.js +0 -889
  138. package/build/utils/PanoraMapProtocol.js +0 -49
  139. package/build/utils/PhotoAdapter.js +0 -49
  140. package/build/utils/PresetsManager.js +0 -148
  141. package/build/utils/SemanticsMapProtocol.js +0 -144
  142. package/build/utils/URLHandler.js +0 -426
  143. package/build/utils/geocoder.js +0 -203
  144. package/build/utils/i18n.js +0 -128
  145. package/build/utils/index.js +0 -17
  146. package/build/utils/index_photoviewer.js +0 -14
  147. package/build/utils/indoor.js +0 -200
  148. package/build/utils/map.js +0 -788
  149. package/build/utils/picture.js +0 -507
  150. package/build/utils/semantics.js +0 -321
  151. package/build/utils/services.js +0 -148
  152. package/build/utils/utils.js +0 -433
  153. package/build/utils/widgets.js +0 -110
@@ -1,426 +0,0 @@
1
- import {
2
- MAP_FILTERS_JS2URL, alterMapState, alterPSVState, alterPhotoViewerState, alterViewerState
3
- } from "./InitParameters.js";
4
- import { BASEMAPS_DEFAULT_IDS } from "./MapStyleComposer.js";
5
-
6
- // List of supported parameters
7
- const MANAGED_PARAMETERS = [
8
- "speed", "nav", "focus", "pic", "xyz", "map",
9
- "background", "users", "s", "xywh",
10
- "annot", "seq", "overlay", "level",
11
- ].concat(Object.values(MAP_FILTERS_JS2URL));
12
-
13
- // Events to listen on parent and PSV
14
- const UPDATE_PARENT_EVENTS = ["focus-changed", "pictures-navigation-changed"];
15
- const UPDATE_PSV_EVENTS = ["position-updated", "zoom-updated", "view-rotated", "picture-loaded", "transition-duration-changed", "annotation-focused", "annotations-unfocused"];
16
- const UPDATE_MAP_EVENTS = ["moveend", "zoomend", "boxzoomend", "styledata"];
17
- const UPDATE_MSC_EVENTS = ["filters-changed", "theme-changed", "panoramax-changed", "basemap-changed"];
18
-
19
-
20
- /**
21
- * Updates the URL query part with various parent component information.
22
- *
23
- * Note that you may call `listenToChanges()` for this class to be effective once parent is ready-enough.
24
- *
25
- * @class Panoramax.utils.URLHandler
26
- * @typicalname urlHandler
27
- * @param {Panoramax.components.core.Basic} parent The parent component
28
- * @fires Panoramax.utils.URLHandler#url-changed
29
- */
30
- export default class URLHandler extends EventTarget {
31
- constructor(parent) {
32
- super();
33
- this._parent = parent;
34
- this._delay = null;
35
- }
36
-
37
- /**
38
- * Start listening to URL & parent changes through events.
39
- * This leads to parent & URL updates.
40
- * @memberof Panoramax.utils.URLHandler#
41
- */
42
- listenToChanges() {
43
- window.addEventListener("popstate", this._onURLChange.bind(this), false);
44
- UPDATE_PARENT_EVENTS.forEach(e => this._parent.addEventListener(e, this._onParentChange.bind(this)));
45
- UPDATE_PSV_EVENTS.forEach(e => this._parent.psv.addEventListener(e, this._onParentChange.bind(this)));
46
- if(this._parent.map) {
47
- UPDATE_MAP_EVENTS.forEach(e => this._parent.map.on(e, this._onParentChange.bind(this)));
48
- UPDATE_MSC_EVENTS.forEach(e => this._parent.mapStyleComposer.addEventListener(e, this._onParentChange.bind(this)));
49
- this._parent.map.indoorEqual?.on("levelchange", this._onParentChange.bind(this));
50
- }
51
- }
52
-
53
- /**
54
- * Call this function to stop listening to global events.
55
- * @memberof Panoramax.utils.URLHandler#
56
- */
57
- destroy() {
58
- window.removeEventListener("popstate", this._onURLChange);
59
- }
60
-
61
- /**
62
- * Compute next values to insert in URL
63
- * @returns {object} Query parameters
64
- * @memberof Panoramax.utils.URLHandler#
65
- */
66
- nextURLParams() {
67
- let hashParts = {};
68
-
69
- if(typeof this._parent.psv.getTransitionDuration() === "number") {
70
- hashParts.speed = this._parent.psv.getTransitionDuration();
71
- }
72
-
73
- if(![null, "any"].includes(this._parent.psv.getPicturesNavigation())) {
74
- hashParts.nav = this._parent.psv.getPicturesNavigation();
75
- }
76
-
77
- if(this._parent.psv.getPictureId()) {
78
- hashParts.pic = this._parent.psv.getPictureId();
79
- }
80
- const picMeta = this._parent.psv.getPictureMetadata();
81
- if (picMeta) {
82
- hashParts.xyz = this.currentPSVString();
83
- if(picMeta.sequence?.id) { hashParts.seq = picMeta.sequence.id; }
84
- }
85
-
86
- const annots = this._parent.psv.getSelectedAnnotations();
87
- if(annots?.length > 0) {
88
- hashParts.annot = annots[0];
89
- }
90
-
91
- if(this._parent.map?.loaded) { // Use this test to avoid empty object checking in
92
- hashParts.map = this.currentMapString();
93
- hashParts.focus = "pic";
94
- if(this._parent.isMapWide()) { hashParts.focus = "map"; }
95
- if(this._parent.mapStyleComposer?.hasManyBasemaps?.() && this._parent.mapStyleComposer?.basemap) {
96
- hashParts.background = this._parent.mapStyleComposer.basemap;
97
- }
98
-
99
- if(this._parent.mapStyleComposer?.panoramax) {
100
- hashParts.users = this._parent.mapStyleComposer.panoramax;
101
- }
102
-
103
- if(this._parent.mapStyleComposer.panoramaxFilters) {
104
- for(let k in MAP_FILTERS_JS2URL) {
105
- if(this._parent.mapStyleComposer.panoramaxFilters[k]) {
106
- hashParts[MAP_FILTERS_JS2URL[k]] = this._parent.mapStyleComposer.panoramaxFilters[k];
107
- }
108
- }
109
- if(hashParts.pic_score) {
110
- if(!Array.isArray(hashParts.pic_score)) { hashParts.pic_score = hashParts.pic_score.split(","); }
111
- if(hashParts.pic_score.length === 5) {
112
- delete hashParts.pic_score;
113
- }
114
- else {
115
- const mapping = [null, "E", "D", "C", "B", "A"];
116
- hashParts.pic_score = hashParts.pic_score.map(v => mapping[v]).join("");
117
- }
118
- }
119
- if(Array.isArray(hashParts.gps) && hashParts.gps.length === 5) {
120
- delete hashParts.gps;
121
- }
122
- }
123
-
124
- if(this._parent.map?.getSemanticOverlays) {
125
- const visibleSem = this._parent.map.getSemanticOverlays()
126
- .filter(l => this._parent.mapStyleComposer.dataOverlays.has(l.source))
127
- .map(l => l.id);
128
- if(visibleSem.length > 0) {
129
- hashParts.overlay = visibleSem.join(",");
130
- }
131
- }
132
-
133
- if(this._parent.map?.indoorEqual) {
134
- hashParts.level = this._parent.map.indoorEqual.level;
135
- }
136
- }
137
- return hashParts;
138
- }
139
-
140
- /**
141
- * Compute next URL query string (based on `nextURLParams()`)
142
- * @memberof Panoramax.utils.URLHandler#
143
- * @return {string} The query string
144
- */
145
- nextURLString() {
146
- let hash = "";
147
-
148
- Object.entries(this.nextURLParams())
149
- .sort((a,b) => a[0].localeCompare(b[0]))
150
- .forEach(entry => {
151
- let [ hashName, value ] = entry;
152
- let found = false;
153
- const parts = hash.split("&").map(part => {
154
- const key = part.split("=")[0];
155
- if (key === hashName) {
156
- found = true;
157
- return `${key}=${value}`;
158
- }
159
- return part;
160
- }).filter(a => a);
161
- if (!found) {
162
- parts.push(`${hashName}=${value}`);
163
- }
164
- hash = `${parts.join("&")}`;
165
- });
166
-
167
- return `?${hash}`.replace(/^\?+/, "?");
168
- }
169
-
170
- /**
171
- * Transforms current URL query string into key->value object
172
- * @param {boolean} [readFromHash=false] Switch to reading from hash URL part (for retro-compatibility)
173
- * @return {object} Key-value read from current URL query
174
- * @memberof Panoramax.utils.URLHandler#
175
- */
176
- currentURLParams(readFromHash = false) {
177
- // Get the current hash from location, stripped from its number sign
178
- const hash = (readFromHash ? window.location.hash : window.location.search)
179
- .replace(/^[?#]/, "")
180
- .replace(/&/g, "&");
181
-
182
- // Split the parameter-styled hash into parts and find the value we need
183
- let keyvals = {};
184
- hash.split("&").map(
185
- part => part.split("=")
186
- )
187
- .filter(part => part[0] !== undefined && part[0].length > 0 && MANAGED_PARAMETERS.includes(part[0]))
188
- .forEach(part => {
189
- keyvals[part[0]] = part[1];
190
- });
191
-
192
- // If hash is compressed
193
- if(keyvals.s) {
194
- const shortVals = Object.fromEntries(
195
- decodeURIComponent(keyvals.s)
196
- .split(";")
197
- .map(kv => [kv[0], kv.substring(1)])
198
- );
199
-
200
- keyvals = {};
201
-
202
- // Used letters: a b c d e f g k m n o p q l s t u v
203
- // NOTE: seq=* isn't used in shortlinks
204
- // Focus
205
- if(shortVals.f === "m") { keyvals.focus = "map"; }
206
- else if(shortVals.f === "p") { keyvals.focus = "pic"; }
207
- else if(shortVals.f === "t") { keyvals.focus = "meta"; }
208
-
209
- // Speed
210
- if(shortVals.s !== "") { keyvals.speed = parseFloat(shortVals.s) * 100; }
211
-
212
- // Nav
213
- if(shortVals.n === "a") { keyvals.nav = "any"; }
214
- else if(shortVals.n === "s") { keyvals.nav = "seq"; }
215
- if(["n", "p"].includes(shortVals.n)) { keyvals.nav = "pic"; }
216
-
217
- // Pic
218
- if(shortVals.p !== "") { keyvals.pic = shortVals.p; }
219
-
220
- // Annotation
221
- if(shortVals.a !== "") { keyvals.annot = shortVals.a; }
222
-
223
- // XYZ
224
- if(shortVals.c !== "") { keyvals.xyz = shortVals.c; }
225
-
226
- // Map
227
- if(shortVals.m !== "") { keyvals.map = shortVals.m; }
228
-
229
- // Date
230
- if(shortVals.d !== "") { keyvals.date_from = shortVals.d; }
231
- if(shortVals.e !== "") { keyvals.date_to = shortVals.e; }
232
-
233
- // Pic type
234
- if(shortVals.t === "f") { keyvals.pic_type = "flat"; }
235
- else if(shortVals.t === "e") { keyvals.pic_type = "equirectangular"; }
236
-
237
- // Camera
238
- if(shortVals.k !== "") { keyvals.camera = shortVals.k; }
239
-
240
- // Theme
241
- if(shortVals.v === "d") { keyvals.theme = "default"; }
242
- else if(shortVals.v === "a") { keyvals.theme = "age"; }
243
- else if(shortVals.v === "t") { keyvals.theme = "type"; }
244
- else if(shortVals.v === "s") { keyvals.theme = "score"; }
245
- else if(shortVals.v === "g") { keyvals.theme = "gps"; }
246
-
247
- // Background
248
- if(shortVals.b === "s") { keyvals.background = "streets"; }
249
- else if(shortVals.b === "a") { keyvals.background = "aerial"; }
250
-
251
- // Users
252
- if(shortVals.u !== "") { keyvals.users = shortVals.u; }
253
-
254
- // Photoscore
255
- if(shortVals.q !== "") { keyvals.pic_score = shortVals.q; }
256
-
257
- // GPS precision
258
- if(shortVals.g !== "") { keyvals.gps = shortVals.g; }
259
-
260
- // Overlays
261
- if(shortVals.o !== "") { keyvals.overlay = shortVals.o; }
262
-
263
- // Level
264
- if(shortVals.l !== "") { keyvals.level = shortVals.l; }
265
- }
266
-
267
- return keyvals;
268
- }
269
-
270
- /**
271
- * Get string representation of map position
272
- * @returns {string} zoom/lat/lon or zoom/lat/lon/bearing/pitch
273
- * @memberof Panoramax.utils.URLHandler#
274
- */
275
- currentMapString() {
276
- if(!this._parent.map?.loaded) { return ""; }
277
-
278
- const center = this._parent.map.getCenter(),
279
- zoom = Math.round(this._parent.map.getZoom() * 100) / 100,
280
- // Derived from equation: 512px * 2^z / 360 / 10^d < 0.5px
281
- precision = Math.ceil((zoom * Math.LN2 + Math.log(512 / 360 / 0.5)) / Math.LN10),
282
- m = Math.pow(10, precision),
283
- lng = Math.round(center.lng * m) / m,
284
- lat = Math.round(center.lat * m) / m,
285
- bearing = this._parent.map.getBearing(),
286
- pitch = this._parent.map.getPitch();
287
- let hash = `${zoom}/${lat}/${lng}`;
288
-
289
- if (bearing || pitch) {hash += (`/${Math.round(bearing * 10) / 10}`);}
290
- if (pitch) {hash += (`/${Math.round(pitch)}`);}
291
-
292
- return hash;
293
- }
294
-
295
- /**
296
- * Get PSV view position as string
297
- * @returns {string} x/y/z
298
- * @memberof Panoramax.utils.URLHandler#
299
- */
300
- currentPSVString() {
301
- const xyz = this._parent.psv.getXYZ();
302
- const x = xyz.x.toFixed(2),
303
- y = xyz.y.toFixed(2),
304
- z = Math.round(xyz.z || 0);
305
- return `${x}/${y}/${z}`;
306
- }
307
-
308
- /**
309
- * Updates map and PSV according to current hash values
310
- * @private
311
- * @memberof Panoramax.utils.URLHandler#
312
- */
313
- _onURLChange() {
314
- let vals = this.currentURLParams();
315
-
316
- if(this._parent.getClassName() === "Viewer") { alterViewerState(this._parent, vals); }
317
- else { alterPhotoViewerState(this._parent, vals); }
318
-
319
- alterPSVState(this._parent.psv, vals);
320
- if(this._parent.map) { alterMapState(this._parent.map, vals); }
321
- }
322
-
323
- /**
324
- * Get short link URL (query replaced by Base64)
325
- * @returns {str} The short link URL
326
- * @memberof Panoramax.utils.URLHandler#
327
- */
328
- nextShortLink(baseUrl) {
329
- const url = new URL(baseUrl);
330
- const hashParts = this.nextURLParams();
331
- const shortVals = {
332
- f: (hashParts.focus || "").substring(0, 1),
333
- s: !isNaN(parseInt(hashParts.speed)) ? Math.floor(parseInt(hashParts.speed)/100) : undefined,
334
- n: (hashParts.nav || "").substring(0, 1),
335
- p: hashParts.pic,
336
- c: hashParts.xyz,
337
- m: hashParts.map,
338
- d: hashParts.date_from,
339
- e: hashParts.date_to,
340
- t: (hashParts.pic_type || "").substring(0, 1),
341
- k: hashParts.camera,
342
- v: (hashParts.theme || "").substring(0, 1),
343
- b: BASEMAPS_DEFAULT_IDS.includes(hashParts.background) ? (hashParts.background || "").substring(0, 1) : (hashParts.background || ""),
344
- u: hashParts.users,
345
- q: hashParts.pic_score,
346
- a: hashParts.annot,
347
- g: hashParts.gps,
348
- o: hashParts.overlay,
349
- l: hashParts.level,
350
- };
351
- const short = Object.entries(shortVals)
352
- // eslint-disable-next-line eqeqeq
353
- .filter(([,v]) => v != undefined && v != "")
354
- .map(([k,v]) => `${k}${v}`)
355
- .join(";");
356
- url.search = `s=${short}`;
357
- return url;
358
- }
359
-
360
- /**
361
- * Returns a string containing only parameters out of URLHandler scope
362
- * @param {URL} prevUrl The previously set URL
363
- * @memberof Panoramax.utils.URLHandler#
364
- */
365
- getUnmanagedParameters(prevUrl) {
366
- return new URLSearchParams(
367
- Array.from(prevUrl.searchParams)
368
- .filter(([k]) => !MANAGED_PARAMETERS.includes(k))
369
- ).toString();
370
- }
371
-
372
- /**
373
- * Changes the URL hash using current viewer parameters
374
- * @private
375
- * @memberof Panoramax.utils.URLHandler#
376
- */
377
- _onParentChange() {
378
- if(this._delay) {
379
- clearTimeout(this._delay);
380
- this._delay = null;
381
- }
382
-
383
- this._delay = setTimeout(() => {
384
- const prevUrl = new URL(window.location.href);
385
- const nextUrl = new URL(window.location.href);
386
- const unmanaged = this.getUnmanagedParameters(prevUrl);
387
- nextUrl.search = this._parent ? this.nextURLString() + (unmanaged.length > 0 ? "&"+unmanaged : ""): "";
388
-
389
- // Clear out hash if older parameters appear
390
- if(Object.keys(this.currentURLParams(true)).length > 0) { nextUrl.hash = ""; }
391
-
392
- // Skip hash update if no changes
393
- if(prevUrl.search === nextUrl.search) { return; }
394
-
395
- const prevPic = this.currentURLParams().pic || "";
396
- const nextPic = this._parent?.psv?.getPictureId?.() || "";
397
-
398
- try {
399
- // If different pic, add entry in browser history
400
- // eslint-disable-next-line eqeqeq
401
- if(prevPic != nextPic) {
402
- window.history.pushState(window.history.state, null, nextUrl.href);
403
- }
404
- // If same pic, just update viewer params
405
- else {
406
- window.history.replaceState(window.history.state, null, nextUrl.href);
407
- }
408
-
409
- if(this._parent) {
410
- /**
411
- * URL changed event
412
- * @event Panoramax.utils.URLHandler#url-changed
413
- * @type {CustomEvent}
414
- * @property {string} detail.url The new used URL
415
- */
416
- const event = new CustomEvent("url-changed", { detail: {url: nextUrl.href}});
417
- this.dispatchEvent(event);
418
- }
419
- } catch (SecurityError) {
420
- // IE11 does not allow this if the page is within an iframe created
421
- // With iframe.contentWindow.document.write(...).
422
- // https://github.com/mapbox/mapbox-gl-js/issues/7410
423
- }
424
- }, 500);
425
- }
426
- }
@@ -1,203 +0,0 @@
1
- import { AdresseDataGouvBaseURL, NominatimBaseUrl } from "./services.js";
2
-
3
- const PLACETYPE_ZOOM = {
4
- "house": 20,
5
- "housenumber": 20,
6
- "street": 18,
7
- "locality": 15,
8
- "district": 13,
9
- "municipality": 12,
10
- "city": 12,
11
- "county": 8,
12
- "region": 7,
13
- "state": 7,
14
- "country": 5
15
- };
16
-
17
- /**
18
- * Transforms a set of parameters into an URL-ready string
19
- * It also removes null/undefined values
20
- *
21
- * @param {object} params The parameters object
22
- * @return {string} The URL query part
23
- * @private
24
- */
25
- function geocoderParamsToURLString(params) {
26
- let p = {};
27
- Object.entries(params)
28
- .filter(e => e[1] !== undefined && e[1] !== null)
29
- .forEach(e => p[e[0]] = e[1]);
30
-
31
- return new URLSearchParams(p).toString();
32
- }
33
-
34
- /**
35
- * Nominatim (OSM) geocoder, ready to use for our Map
36
- * @private
37
- */
38
- export function forwardGeocodingNominatim(config) {
39
- // Transform parameters into Nominatim format
40
- const params = {
41
- q: config.query,
42
- countrycodes: config.countries,
43
- limit: config.limit,
44
- viewbox: config.bbox,
45
- };
46
-
47
- return fetch(`${NominatimBaseUrl()}/search?${geocoderParamsToURLString(params)}&format=geocodejson&addressdetails=1`)
48
- .then(res => res.json())
49
- .then(res => {
50
- const finalRes = { features: [] };
51
- const listedNames = [];
52
- (res.features || []).forEach(f => {
53
- const plname = geocodeJsonToPlaceName(f.properties?.geocoding) || f.properties?.geocoding?.label;
54
- if(!listedNames.includes(plname)) {
55
- finalRes.features.push({
56
- place_type: ["place"],
57
- place_name: plname,
58
- center: f.geometry.coordinates,
59
- zoom: PLACETYPE_ZOOM[f.properties?.geocoding?.type],
60
- });
61
- listedNames.push(plname);
62
- }
63
- });
64
- return finalRes;
65
- });
66
- }
67
-
68
- export function reverseGeocodingNominatim(lat, lon) {
69
- return fetch(`${NominatimBaseUrl()}/reverse?lat=${lat}&lon=${lon}&zoom=18&format=geocodejson`)
70
- .then(res => res.json())
71
- .then(res => geocodeJsonToPlaceName(res?.features?.shift()?.properties?.geocoding));
72
- }
73
-
74
- /**
75
- * Base adresse nationale (FR) geocoder, ready to use for our Map
76
- * @param {object} config Configuration sent by MapLibre GL Geocoder, following the geocoderApi format ( https://maplibre.org/maplibre-gl-geocoder/types/MaplibreGeocoderApiConfig.html )
77
- * @returns {object} GeoJSON Feature collection in Carmen GeoJSON format ( https://maplibre.org/maplibre-gl-geocoder/types/CarmenGeojsonFeature.html )
78
- * @private
79
- */
80
- export function forwardGeocodingBAN(config) {
81
- return forwardGeocodingStandard(config, AdresseDataGouvBaseURL());
82
- }
83
-
84
- /**
85
- * Transforms GeocodeJSON search result into a nice-to-display address.
86
- * @param {object} props The GecodeJSON API feature properties
87
- * @returns {string} The clean-up string for display
88
- * @private
89
- */
90
- function geocodeJsonToPlaceName(props) {
91
- // API format @ https://github.com/geocoders/geocodejson-spec/blob/master/draft/README.md
92
- if(!props || typeof props !== "object") { return ""; }
93
-
94
- // P1 = main name, P2=locality-like, P3=country+high-level admin
95
- let p1 = props.name;
96
- let p2 = [], p3 = [];
97
-
98
- switch(props.type) {
99
- case "hamlet":
100
- case "croft":
101
- case "isolated_dwelling":
102
- case "neighbourhood":
103
- case "allotments":
104
- case "quarter":
105
- case "farm":
106
- case "farmyard":
107
- case "industrial":
108
- case "commercial":
109
- case "retail":
110
- case "city_block":
111
- case "residential":
112
- case "locality":
113
- case "district":
114
- p3.push(props.city);
115
- p3.push(props.county);
116
- p3.push(props.state);
117
- p3.push(props.country);
118
- break;
119
- case "city":
120
- p3.push(props.county);
121
- p3.push(props.state);
122
- p3.push(props.country);
123
- break;
124
- case "region":
125
- p3.push(props.county);
126
- p3.push(props.state);
127
- p3.push(props.country);
128
- break;
129
- case "country":
130
- break;
131
- case "house":
132
- case "housenumber":
133
- p2.push(props.housenumber);
134
- p2.push(props.street);
135
- p2.push(props.locality);
136
- p2.push(props.district);
137
- p3.push(props.city);
138
- p3.push(props.county);
139
- p3.push(props.state);
140
- p3.push(props.country);
141
- break;
142
- case "street":
143
- case "road":
144
- default:
145
- p2.push(props.street);
146
- p2.push(props.locality);
147
- p2.push(props.district);
148
- p3.push(props.city);
149
- p3.push(props.county);
150
- p3.push(props.state);
151
- p3.push(props.country);
152
- break;
153
- }
154
-
155
- p2 = p2.filter(v => v);
156
- p2 = p2.filter((v,i) => v !== p1 && (i === 0 || p2[i-1] !== v));
157
- p2 = p2.length > 0 ? (props.housenumber ? p2.slice(0,2).join(" ") : p2.shift()) : null;
158
- if(p2 === p1) { p2 = null; }
159
-
160
- p3 = p3.filter(v => v);
161
- p3 = p3.filter((v,i) => v !== p1 && (!p2 || !p2.includes(v)) && (i === 0 || p3[i-1] !== v));
162
-
163
- let res = [p1, p2, p3.shift()].filter(v => v);
164
-
165
- return res.join(", ");
166
- }
167
-
168
- /**
169
- * Standard forward geocoder
170
- * @param {object} config Configuration sent by MapLibre GL Geocoder, following the geocoderApi format ( https://maplibre.org/maplibre-gl-geocoder/types/MaplibreGeocoderApiConfig.html )
171
- * @param {string} endpoint The URL endpoint (everything before the /?q=...)
172
- * @returns {object} GeoJSON Feature collection in Carmen GeoJSON format ( https://maplibre.org/maplibre-gl-geocoder/types/CarmenGeojsonFeature.html )
173
- * @private
174
- */
175
- export function forwardGeocodingStandard(config, endpoint) {
176
- // Transform parameters into BAN format
177
- const params = { q: config.query, limit: config.limit };
178
- if(typeof config.proximity === "string") {
179
- const [lat, lon] = config.proximity.split(",").map(v => parseFloat(v.trim()));
180
- params.lat = lat;
181
- params.lon = lon;
182
- }
183
-
184
- return fetch(`${endpoint}/?${geocoderParamsToURLString(params)}`)
185
- .then(res => res.json())
186
- .then(res => {
187
- const finalRes = { features: [] };
188
- const listedNames = [];
189
- (res.features || []).forEach(f => {
190
- const plname = geocodeJsonToPlaceName(f.properties);
191
- if(!listedNames.includes(plname) && f.properties.type !== "other") {
192
- finalRes.features.push({
193
- place_type: ["place"],
194
- place_name: plname,
195
- center: f.geometry.coordinates,
196
- zoom: PLACETYPE_ZOOM[f.properties.type],
197
- });
198
- listedNames.push(plname);
199
- }
200
- });
201
- return finalRes;
202
- });
203
- }