@panoramax/web-viewer 3.2.3 → 4.0.0-develop-9f9cf858

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 (255) hide show
  1. package/.gitlab-ci.yml +13 -6
  2. package/CHANGELOG.md +56 -1
  3. package/CODE_OF_CONDUCT.md +1 -1
  4. package/README.md +1 -1
  5. package/build/editor.html +10 -1
  6. package/build/index.css +12 -12
  7. package/build/index.css.map +1 -1
  8. package/build/index.html +1 -1
  9. package/build/index.js +2126 -14
  10. package/build/index.js.map +1 -1
  11. package/build/map.html +1 -1
  12. package/build/photo.html +1 -0
  13. package/build/static/media/atkinson-hyperlegible-next-latin-400-normal..woff +0 -0
  14. package/build/static/media/atkinson-hyperlegible-next-latin-400-normal..woff2 +0 -0
  15. package/build/static/media/atkinson-hyperlegible-next-latin-ext-400-normal..woff +0 -0
  16. package/build/static/media/atkinson-hyperlegible-next-latin-ext-400-normal..woff2 +0 -0
  17. package/build/viewer.html +12 -1
  18. package/build/widgets.html +1 -0
  19. package/config/jest/mocks.js +201 -0
  20. package/config/paths.js +2 -0
  21. package/config/webpack.config.js +52 -0
  22. package/docs/03_URL_settings.md +14 -16
  23. package/docs/05_Compatibility.md +59 -76
  24. package/docs/09_Develop.md +46 -11
  25. package/docs/90_Releases.md +2 -2
  26. package/docs/images/class_diagram.drawio +60 -45
  27. package/docs/images/class_diagram.jpg +0 -0
  28. package/docs/images/screenshot.jpg +0 -0
  29. package/docs/index.md +135 -0
  30. package/docs/reference/components/core/Basic.md +196 -0
  31. package/docs/reference/components/core/CoverageMap.md +210 -0
  32. package/docs/reference/components/core/Editor.md +224 -0
  33. package/docs/reference/components/core/PhotoViewer.md +307 -0
  34. package/docs/reference/components/core/Viewer.md +350 -0
  35. package/docs/reference/components/layout/BottomDrawer.md +35 -0
  36. package/docs/reference/components/layout/CorneredGrid.md +29 -0
  37. package/docs/reference/components/layout/Mini.md +45 -0
  38. package/docs/reference/components/layout/Tabs.md +45 -0
  39. package/docs/reference/components/menus/MapBackground.md +32 -0
  40. package/docs/reference/components/menus/MapFilters.md +15 -0
  41. package/docs/reference/components/menus/MapLayers.md +15 -0
  42. package/docs/reference/components/menus/MapLegend.md +15 -0
  43. package/docs/reference/components/menus/PictureLegend.md +16 -0
  44. package/docs/reference/components/menus/PictureMetadata.md +15 -0
  45. package/docs/reference/components/menus/PlayerOptions.md +15 -0
  46. package/docs/reference/components/menus/QualityScoreDoc.md +15 -0
  47. package/docs/reference/components/menus/ReportForm.md +15 -0
  48. package/docs/reference/components/menus/ShareMenu.md +15 -0
  49. package/docs/reference/components/ui/Button.md +40 -0
  50. package/docs/reference/components/ui/ButtonGroup.md +36 -0
  51. package/docs/reference/components/ui/CopyButton.md +38 -0
  52. package/docs/reference/components/ui/Grade.md +32 -0
  53. package/docs/reference/components/ui/LinkButton.md +45 -0
  54. package/docs/reference/components/ui/ListGroup.md +22 -0
  55. package/docs/reference/components/ui/Loader.md +56 -0
  56. package/docs/reference/components/ui/Map.md +239 -0
  57. package/docs/reference/components/ui/MapMore.md +256 -0
  58. package/docs/reference/components/ui/Photo.md +385 -0
  59. package/docs/reference/components/ui/Popup.md +56 -0
  60. package/docs/reference/components/ui/ProgressBar.md +32 -0
  61. package/docs/reference/components/ui/QualityScore.md +45 -0
  62. package/docs/reference/components/ui/SearchBar.md +63 -0
  63. package/docs/reference/components/ui/TogglableGroup.md +39 -0
  64. package/docs/reference/components/ui/widgets/GeoSearch.md +32 -0
  65. package/docs/reference/components/ui/widgets/Legend.md +49 -0
  66. package/docs/reference/components/ui/widgets/MapFiltersButton.md +33 -0
  67. package/docs/reference/components/ui/widgets/MapLayersButton.md +15 -0
  68. package/docs/reference/components/ui/widgets/OSMEditors.md +15 -0
  69. package/docs/reference/components/ui/widgets/PictureLegendActions.md +32 -0
  70. package/docs/reference/components/ui/widgets/Player.md +33 -0
  71. package/docs/reference/components/ui/widgets/Zoom.md +15 -0
  72. package/docs/reference/utils/API.md +334 -0
  73. package/docs/reference/utils/InitParameters.md +68 -0
  74. package/docs/reference/utils/URLHandler.md +107 -0
  75. package/docs/reference.md +79 -0
  76. package/docs/shortcuts.md +11 -0
  77. package/docs/tutorials/aerial_imagery.md +19 -0
  78. package/docs/tutorials/authentication.md +10 -0
  79. package/docs/tutorials/custom_widgets.md +59 -0
  80. package/docs/tutorials/map_style.md +39 -0
  81. package/docs/tutorials/migrate_v4.md +153 -0
  82. package/docs/tutorials/synced_coverage.md +43 -0
  83. package/mkdocs.yml +66 -5
  84. package/package.json +22 -17
  85. package/public/editor.html +21 -29
  86. package/public/index.html +17 -12
  87. package/public/map.html +19 -18
  88. package/public/photo.html +55 -0
  89. package/public/viewer.html +22 -26
  90. package/public/widgets.html +306 -0
  91. package/scripts/doc.js +79 -0
  92. package/src/components/core/Basic.css +48 -0
  93. package/src/components/core/Basic.js +349 -0
  94. package/src/components/core/CoverageMap.css +9 -0
  95. package/src/components/core/CoverageMap.js +139 -0
  96. package/src/components/core/Editor.css +23 -0
  97. package/src/components/core/Editor.js +390 -0
  98. package/src/components/core/PhotoViewer.css +48 -0
  99. package/src/components/core/PhotoViewer.js +499 -0
  100. package/src/components/core/Viewer.css +98 -0
  101. package/src/components/core/Viewer.js +564 -0
  102. package/src/components/core/index.js +12 -0
  103. package/src/components/index.js +13 -0
  104. package/src/components/layout/BottomDrawer.js +257 -0
  105. package/src/components/layout/CorneredGrid.js +112 -0
  106. package/src/components/layout/Mini.js +117 -0
  107. package/src/components/layout/Tabs.js +133 -0
  108. package/src/components/layout/index.js +9 -0
  109. package/src/components/menus/MapBackground.js +106 -0
  110. package/src/components/menus/MapFilters.js +400 -0
  111. package/src/components/menus/MapLayers.js +143 -0
  112. package/src/components/menus/MapLegend.js +34 -0
  113. package/src/components/menus/PictureLegend.js +257 -0
  114. package/src/components/menus/PictureMetadata.js +317 -0
  115. package/src/components/menus/PlayerOptions.js +95 -0
  116. package/src/components/menus/QualityScoreDoc.js +36 -0
  117. package/src/components/menus/ReportForm.js +133 -0
  118. package/src/components/menus/Share.js +100 -0
  119. package/src/components/menus/index.js +15 -0
  120. package/src/components/styles.js +383 -0
  121. package/src/components/ui/Button.js +77 -0
  122. package/src/components/ui/ButtonGroup.css +57 -0
  123. package/src/components/ui/ButtonGroup.js +68 -0
  124. package/src/components/ui/CopyButton.js +106 -0
  125. package/src/components/ui/Grade.js +54 -0
  126. package/src/components/ui/LinkButton.js +67 -0
  127. package/src/components/ui/ListGroup.js +66 -0
  128. package/src/components/ui/Loader.js +203 -0
  129. package/src/components/{Map.css → ui/Map.css} +5 -17
  130. package/src/components/{Map.js → ui/Map.js} +148 -156
  131. package/src/components/ui/MapMore.js +324 -0
  132. package/src/components/{Photo.css → ui/Photo.css} +6 -6
  133. package/src/components/{Photo.js → ui/Photo.js} +313 -101
  134. package/src/components/ui/Popup.js +145 -0
  135. package/src/components/ui/ProgressBar.js +104 -0
  136. package/src/components/ui/QualityScore.js +147 -0
  137. package/src/components/ui/SearchBar.js +367 -0
  138. package/src/components/ui/TogglableGroup.js +157 -0
  139. package/src/components/ui/index.js +22 -0
  140. package/src/components/ui/widgets/GeoSearch.css +21 -0
  141. package/src/components/ui/widgets/GeoSearch.js +139 -0
  142. package/src/components/ui/widgets/Legend.js +113 -0
  143. package/src/components/ui/widgets/MapFiltersButton.js +104 -0
  144. package/src/components/ui/widgets/MapLayersButton.js +79 -0
  145. package/src/components/ui/widgets/OSMEditors.js +155 -0
  146. package/src/components/ui/widgets/PictureLegendActions.js +117 -0
  147. package/src/components/ui/widgets/Player.css +7 -0
  148. package/src/components/ui/widgets/Player.js +151 -0
  149. package/src/components/ui/widgets/Zoom.js +82 -0
  150. package/src/components/ui/widgets/index.js +13 -0
  151. package/src/img/loader_base.jpg +0 -0
  152. package/src/img/panoramax.svg +13 -0
  153. package/src/img/switch_big.svg +20 -10
  154. package/src/index.js +7 -9
  155. package/src/translations/br.json +1 -0
  156. package/src/translations/da.json +38 -15
  157. package/src/translations/de.json +5 -3
  158. package/src/translations/en.json +35 -15
  159. package/src/translations/eo.json +38 -15
  160. package/src/translations/es.json +1 -1
  161. package/src/translations/fr.json +36 -16
  162. package/src/translations/hu.json +1 -1
  163. package/src/translations/it.json +39 -16
  164. package/src/translations/ja.json +182 -1
  165. package/src/translations/nl.json +106 -6
  166. package/src/translations/pl.json +1 -1
  167. package/src/translations/sv.json +182 -0
  168. package/src/translations/zh_Hant.json +35 -14
  169. package/src/utils/API.js +109 -49
  170. package/src/utils/InitParameters.js +388 -0
  171. package/src/utils/PhotoAdapter.js +1 -0
  172. package/src/utils/URLHandler.js +362 -0
  173. package/src/utils/geocoder.js +152 -0
  174. package/src/utils/{I18n.js → i18n.js} +7 -3
  175. package/src/utils/index.js +11 -0
  176. package/src/utils/{Map.js → map.js} +256 -77
  177. package/src/utils/picture.js +442 -0
  178. package/src/utils/utils.js +324 -0
  179. package/src/utils/widgets.js +55 -0
  180. package/tests/components/core/Basic.test.js +121 -0
  181. package/tests/components/core/BasicMock.js +25 -0
  182. package/tests/components/core/CoverageMap.test.js +20 -0
  183. package/tests/components/core/Editor.test.js +20 -0
  184. package/tests/components/core/PhotoViewer.test.js +57 -0
  185. package/tests/components/core/Viewer.test.js +84 -0
  186. package/tests/components/core/__snapshots__/PhotoViewer.test.js.snap +73 -0
  187. package/tests/components/core/__snapshots__/Viewer.test.js.snap +145 -0
  188. package/tests/components/ui/CopyButton.test.js +52 -0
  189. package/tests/components/ui/Loader.test.js +55 -0
  190. package/tests/components/{Map.test.js → ui/Map.test.js} +73 -61
  191. package/tests/components/{Photo.test.js → ui/Photo.test.js} +97 -63
  192. package/tests/components/ui/Popup.test.js +26 -0
  193. package/tests/components/ui/QualityScore.test.js +18 -0
  194. package/tests/components/ui/SearchBar.test.js +110 -0
  195. package/tests/components/ui/__snapshots__/CopyButton.test.js.snap +33 -0
  196. package/tests/components/ui/__snapshots__/Loader.test.js.snap +56 -0
  197. package/tests/components/{__snapshots__ → ui/__snapshots__}/Map.test.js.snap +11 -38
  198. package/tests/components/{__snapshots__ → ui/__snapshots__}/Photo.test.js.snap +70 -6
  199. package/tests/components/ui/__snapshots__/Popup.test.js.snap +29 -0
  200. package/tests/components/ui/__snapshots__/QualityScore.test.js.snap +11 -0
  201. package/tests/components/ui/__snapshots__/SearchBar.test.js.snap +65 -0
  202. package/tests/utils/API.test.js +83 -83
  203. package/tests/utils/InitParameters.test.js +499 -0
  204. package/tests/utils/URLHandler.test.js +401 -0
  205. package/tests/utils/__snapshots__/API.test.js.snap +10 -0
  206. package/tests/utils/__snapshots__/URLHandler.test.js.snap +21 -0
  207. package/tests/utils/__snapshots__/{Map.test.js.snap → geocoder.test.js.snap} +1 -1
  208. package/tests/utils/__snapshots__/map.test.js.snap +11 -0
  209. package/tests/utils/__snapshots__/picture.test.js.snap +327 -0
  210. package/tests/utils/__snapshots__/widgets.test.js.snap +19 -0
  211. package/tests/utils/geocoder.test.js +37 -0
  212. package/tests/utils/{I18n.test.js → i18n.test.js} +8 -8
  213. package/tests/utils/map.test.js +126 -0
  214. package/tests/utils/picture.test.js +745 -0
  215. package/tests/utils/utils.test.js +288 -0
  216. package/tests/utils/widgets.test.js +31 -0
  217. package/docs/01_Start.md +0 -149
  218. package/docs/02_Usage.md +0 -831
  219. package/docs/04_Advanced_examples.md +0 -216
  220. package/src/Editor.css +0 -37
  221. package/src/Editor.js +0 -361
  222. package/src/StandaloneMap.js +0 -114
  223. package/src/Viewer.css +0 -203
  224. package/src/Viewer.js +0 -1246
  225. package/src/components/CoreView.css +0 -70
  226. package/src/components/CoreView.js +0 -175
  227. package/src/components/Loader.css +0 -74
  228. package/src/components/Loader.js +0 -120
  229. package/src/img/loader_hd.jpg +0 -0
  230. package/src/utils/Exif.js +0 -193
  231. package/src/utils/Utils.js +0 -631
  232. package/src/utils/Widgets.js +0 -562
  233. package/src/viewer/URLHash.js +0 -469
  234. package/src/viewer/Widgets.css +0 -880
  235. package/src/viewer/Widgets.js +0 -1470
  236. package/tests/Editor.test.js +0 -126
  237. package/tests/StandaloneMap.test.js +0 -45
  238. package/tests/Viewer.test.js +0 -366
  239. package/tests/__snapshots__/Editor.test.js.snap +0 -298
  240. package/tests/__snapshots__/StandaloneMap.test.js.snap +0 -30
  241. package/tests/__snapshots__/Viewer.test.js.snap +0 -195
  242. package/tests/components/CoreView.test.js +0 -92
  243. package/tests/components/Loader.test.js +0 -38
  244. package/tests/components/__snapshots__/Loader.test.js.snap +0 -15
  245. package/tests/utils/Exif.test.js +0 -124
  246. package/tests/utils/Map.test.js +0 -113
  247. package/tests/utils/Utils.test.js +0 -300
  248. package/tests/utils/Widgets.test.js +0 -107
  249. package/tests/utils/__snapshots__/Exif.test.js.snap +0 -43
  250. package/tests/utils/__snapshots__/Utils.test.js.snap +0 -41
  251. package/tests/utils/__snapshots__/Widgets.test.js.snap +0 -44
  252. package/tests/viewer/URLHash.test.js +0 -559
  253. package/tests/viewer/Widgets.test.js +0 -127
  254. package/tests/viewer/__snapshots__/URLHash.test.js.snap +0 -108
  255. package/tests/viewer/__snapshots__/Widgets.test.js.snap +0 -403
@@ -1,562 +0,0 @@
1
- // Every single icon imported separately to reduce bundle size
2
- import { icon } from "@fortawesome/fontawesome-svg-core";
3
- import { faXmark } from "@fortawesome/free-solid-svg-icons/faXmark";
4
- import { faCircleExclamation } from "@fortawesome/free-solid-svg-icons/faCircleExclamation";
5
- import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
6
- import { faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlass";
7
- import { faCircleNotch } from "@fortawesome/free-solid-svg-icons/faCircleNotch";
8
- import { faCheck } from "@fortawesome/free-solid-svg-icons/faCheck";
9
- import { faCopy } from "@fortawesome/free-solid-svg-icons/faCopy";
10
- import { faStar } from "@fortawesome/free-solid-svg-icons/faStar";
11
- import { faStar as farStar } from "@fortawesome/free-regular-svg-icons/faStar";
12
- import { QUALITYSCORE_VALUES } from "./Utils";
13
-
14
-
15
- /**
16
- * Creates a new button, already styled
17
- * @param {string} id The component ID
18
- * @param {string|Element} content The text content
19
- * @param {string} [title] A title label on overlay
20
- * @param {string[]} [classes] List of CSS classes to add
21
- * @returns {Element} The created button
22
- * @private
23
- */
24
- export function createButton(id, content = null, title = null, classes = []) {
25
- const btn = document.createElement("button");
26
- if(content) {
27
- if(content instanceof HTMLElement || content instanceof Node) {
28
- btn.appendChild(content);
29
- }
30
- else {
31
- btn.innerHTML = content;
32
- }
33
- }
34
- btn.id = id;
35
- if(Array.isArray(classes)) {
36
- classes = classes.filter(c => c != null && c.length > 0);
37
- }
38
- btn.classList.add("gvs-btn", "gvs-widget-bg", ...classes);
39
- if(title) { btn.title = title; }
40
- return btn;
41
- }
42
-
43
- /**
44
- * Creates a new "expandable" button, already styled
45
- * @param {string} id The component ID
46
- * @param {object} icon The FontAwesome icon definition
47
- * @param {string} label The label text
48
- * @param {Widgets} container The widgets container
49
- * @param {string[]} [classes] List of CSS classes to add
50
- * @returns {Element} The created button
51
- * @private
52
- */
53
- export function createExpandableButton(id, icon, label, container, classes = []) {
54
- const btn = document.createElement("button");
55
- btn.id = id;
56
- btn.appendChild(fa(icon));
57
- if(!container._viewer.isWidthSmall()) {
58
- btn.appendChild(document.createTextNode(label));
59
- if(classes.includes("gvs-filter-unset-btn")) {
60
- const resetIcon = fa(faXmark, { classes: ["gvs-filter-unset-btn"]});
61
- resetIcon.style.display = "none";
62
- btn.appendChild(resetIcon);
63
- classes = classes.filter(v => v !== "gvs-filter-unset-btn");
64
- }
65
- btn.appendChild(fa(faChevronDown));
66
- }
67
- else {
68
- btn.title = label;
69
- }
70
- btn.classList.add("gvs-btn", "gvs-widget-bg", "gvs-btn-expandable", ...classes);
71
- btn.setActive = val => {
72
- let span = btn.querySelector(".gvs-filters-active");
73
- const resetIcon = btn.querySelector(".gvs-filter-unset-btn");
74
- const downIcon = btn.querySelector(".fa-chevron-down");
75
- if(val && !span) {
76
- span = document.createElement("span");
77
- span.classList.add("gvs-filters-active");
78
- const svg = btn.querySelector("svg");
79
- if(svg.nextSibling) { btn.insertBefore(span, svg.nextSibling); }
80
- else { btn.appendChild(span); }
81
- if(resetIcon) {
82
- resetIcon.style.display = null;
83
- downIcon.style.display = "none";
84
- }
85
- }
86
- else if(!val && span) {
87
- span.remove();
88
- if(resetIcon) {
89
- resetIcon.style.display = "none";
90
- downIcon.style.display = null;
91
- }
92
- }
93
- };
94
- return btn;
95
- }
96
-
97
- /**
98
- * Creates a new search bar
99
- * @param {string} id The bar ID
100
- * @param {string} placeholder The default label to display when search field is empty
101
- * @param {function} onInput Event handler for search text input (should return a Promise)
102
- * @param {function} onResultClick Event handler for result entry click
103
- * @param {Widgets} container The widgets container
104
- * @param {boolean} [nonClosingPanel] Should the search result closes other panels
105
- * @param {boolean} [reduced] Should the search bar be reduced by default ?
106
- * @param {Element} [preContent] DOM element to insert before search input
107
- * @returns {Element} The search bar
108
- * @private
109
- */
110
- export function createSearchBar(
111
- id, placeholder, onInput, onResultClick,
112
- container, nonClosingPanel = false, reduced = false,
113
- preContent = null,
114
- ) {
115
- // Container
116
- const bar = document.createElement("div");
117
- bar.classList.add("gvs-widget-bg", "gvs-search-bar");
118
- bar.id = id;
119
- if(reduced) { bar.classList.add("gvs-search-bar-reducable"); }
120
-
121
- // Pre-content
122
- if(preContent) {
123
- bar.appendChild(preContent);
124
- }
125
-
126
- // Input field
127
- const input = document.createElement("input");
128
- input.type = "text";
129
- input.placeholder = placeholder;
130
- input.id = `${id}-input`;
131
- input.setAttribute("autocomplete", "off");
132
- bar.appendChild(input);
133
- const extendInput = () => {
134
- bar.classList.remove("gvs-search-bar-reduced");
135
- };
136
- const reduceInput = () => {
137
- bar.classList.add("gvs-search-bar-reduced");
138
- };
139
- if(reduced) { reduceInput(); }
140
-
141
- // Status icon
142
- const icon = document.createElement("span");
143
- icon.classList.add("gvs-search-bar-icon");
144
- const iconSearch = fa(faMagnifyingGlass);
145
- const iconLoading = fa(faCircleNotch, { classes: ["fa-spin"] });
146
- const iconEmpty = fa(faXmark);
147
- const iconWarn = fa(faCircleExclamation);
148
- icon.appendChild(iconSearch);
149
- bar.appendChild(icon);
150
-
151
- // List of results
152
- const list = createPanel(container, bar, [], ["gvs-search-bar-results"], nonClosingPanel);
153
- bar.appendChild(list);
154
-
155
- // Change status icon
156
- const switchIcon = newStatusIcon => {
157
- icon.innerHTML = "";
158
- icon.appendChild(newStatusIcon);
159
- };
160
-
161
- // Reset search bar
162
- const resetSearch = () => {
163
- if(bar._throttler) { clearTimeout(bar._throttler); }
164
- input.value = "";
165
- list.innerHTML = "";
166
- list._toggle(false);
167
- delete bar._lastSearch;
168
- switchIcon(iconSearch);
169
- onResultClick(null);
170
- if(reduced) { reduceInput(); }
171
- };
172
- bar.resetSearch = resetSearch;
173
-
174
- // Handle result item click
175
- input.goItem = (entry) => {
176
- if(reduced) {
177
- onResultClick(entry);
178
- resetSearch();
179
- }
180
- else {
181
- if(bar._throttler) { clearTimeout(bar._throttler); }
182
- input.value = entry.title;
183
- list.innerHTML = "";
184
- list._toggle(false);
185
- switchIcon(iconEmpty);
186
- onResultClick(entry);
187
- }
188
- };
189
-
190
- // Force item selection
191
- input.setItem = (text) => {
192
- if(bar._throttler) { clearTimeout(bar._throttler); }
193
- input.value = text;
194
- list.innerHTML = "";
195
- list._toggle(false);
196
- switchIcon(iconEmpty);
197
- if(reduced) { extendInput(); }
198
- };
199
-
200
- // Handle search
201
- const goSearch = () => {
202
- if(bar._throttler) { clearTimeout(bar._throttler); }
203
-
204
- if(input.value.length === 0) {
205
- list.innerHTML = "";
206
- list._toggle(false);
207
- return;
208
- }
209
-
210
- bar._throttler = setTimeout(() => {
211
- list.innerHTML = "";
212
- list._toggle(false);
213
- switchIcon(iconLoading);
214
-
215
- onInput(input.value).then(data => {
216
- switchIcon(iconEmpty);
217
- list._toggle(true);
218
-
219
- if(!data || data.length == 0) {
220
- list.innerHTML = `<div class="gvs-search-empty">${container._t.gvs.search_empty}</li>`;
221
- return;
222
- }
223
- else if(data === true) {
224
- list._toggle(false);
225
- return;
226
- }
227
-
228
- data.forEach(entry => {
229
- const listEntry = document.createElement("div");
230
- listEntry.classList.add("gvs-search-bar-result");
231
- listEntry.innerHTML = `${entry.title}<br /><small>${entry?.subtitle || ""}</small>`;
232
- list.appendChild(listEntry);
233
- listEntry.addEventListener("click", () => input.goItem(entry));
234
- });
235
- }).catch(e => {
236
- console.error(e);
237
- switchIcon(iconWarn);
238
- });
239
- }, 250);
240
- };
241
-
242
- input.addEventListener("change", goSearch);
243
- input.addEventListener("keypress", goSearch);
244
- input.addEventListener("paste", goSearch);
245
- input.addEventListener("input", goSearch);
246
- icon.addEventListener("click", () => {
247
- if(icon.firstChild == iconEmpty || icon.firstChild == iconWarn) {
248
- resetSearch();
249
- }
250
- if(reduced && icon.firstChild == iconSearch) {
251
- if(!bar.classList.contains("gvs-search-bar-reduced")) { reduceInput(); }
252
- else { extendInput(); }
253
- }
254
- });
255
-
256
- return bar;
257
- }
258
-
259
- /**
260
- * Creates a panel associated to a button
261
- * @param {Widgets} container The widgets container
262
- * @param {Element} btn The component to associate to
263
- * @param {Element[]} [elements] DOM elements to append into
264
- * @param {str[]} [classes] CSS classes to add
265
- * @param {boolean} [nonClosingPanel] Should this panel closes other when opened
266
- * @returns {Element} The created panel
267
- * @private
268
- */
269
- export function createPanel(container, btn, elements = [], classes = [], nonClosingPanel = false) {
270
- const panel = document.createElement("div");
271
- panel.id = btn.id + "-panel";
272
- if(Array.isArray(classes)) {
273
- classes = classes.filter(c => c != null && c.length > 0);
274
- }
275
- panel.classList.add("gvs-panel", "gvs-widget-bg", "gvs-hidden", ...classes);
276
- for(let e of elements) {
277
- panel.appendChild(e);
278
- }
279
-
280
- const togglePanel = (e, visible) => {
281
- if(e) { e.stopPropagation(); }
282
- if(visible === true) { panel.classList.remove("gvs-hidden"); }
283
- else if(visible === false) { panel.classList.add("gvs-hidden"); }
284
- else {
285
- panel.classList.toggle("gvs-hidden");
286
- visible = !panel.classList.contains("gvs-hidden");
287
- }
288
-
289
- // Hide all other panels
290
- if(visible && !nonClosingPanel) {
291
- closeOtherPanels(panel, container._viewer.container);
292
- }
293
- };
294
- panel._toggle = v => togglePanel(null, v);
295
-
296
- if(btn.tagName == "BUTTON") {
297
- btn.addEventListener("click", togglePanel);
298
- btn.addEventListener("hover", togglePanel);
299
- }
300
-
301
- return panel;
302
- }
303
-
304
- /**
305
- * Makes all previously opened panels closed if clicked outside of one.
306
- * @param {Element} target The DOM element which has been clicked
307
- * @param {Element} container The viewer container
308
- * @private
309
- */
310
- export function closeOtherPanels(target, container) {
311
- const isPanel = p => (
312
- p.classList.contains("gvs-panel")
313
- || p.classList.contains("gvs-search-bar-result")
314
- || p.classList.contains("gvs-search-empty")
315
- || p.classList.contains("gvs-search-bar-reducable")
316
- );
317
-
318
- // Find nearest panel
319
- if(!isPanel(target) && target?.parentNode) {
320
- target = target.parentNode;
321
- while(target instanceof Element) {
322
- if(isPanel(target)) { break; }
323
- else { target = target.parentNode; }
324
- }
325
- }
326
-
327
- // Click outside of open panel = closing
328
- for(const p of container.getElementsByClassName("gvs-panel")) {
329
- if(p != target && !p.contains(target) && !p.classList.contains("gvs-hidden")) {
330
- p.classList.add("gvs-hidden");
331
- }
332
- }
333
- for(const p of container.getElementsByClassName("gvs-search-bar-reducable")) {
334
- if(p != target && !p.contains(target) && !p.classList.contains("gvs-search-bar-reduced")) {
335
- p.resetSearch();
336
- }
337
- }
338
- }
339
-
340
- /**
341
- * Creates a new group of elements, already styled
342
- * @param {str} id
343
- * @param {str} position (format: component-corner, with component = main/mini, and corner = top-left, top-right, top, bottom-left, bottom, bottom-right)
344
- * @param {Element[]} [elements] The children elements to add
345
- * @param {str[]} [classes] The CSS classes to add
346
- * @returns {Element} The created group
347
- * @private
348
- */
349
- export function createGroup(id, position, container, elements = [], classes = []) {
350
- const group = document.createElement("div");
351
- group.id = id;
352
- if(Array.isArray(classes)) {
353
- classes = classes.filter(c => c != null && c.length > 0);
354
- }
355
- group.classList.add("gvs-group", ...classes);
356
- for(let e of elements) {
357
- group.appendChild(e);
358
- }
359
- container._corners[position].appendChild(group);
360
- return group;
361
- }
362
-
363
- /**
364
- * Make all buttons with data-copy=* or data-input=* attributes able to copy to clipboard.
365
- *
366
- * @param {Element} container The parent container
367
- * @param {object} t The translation container
368
- * @private
369
- */
370
- export function enableCopyButton(container, t) {
371
- for(let btn of container.getElementsByTagName("button")) {
372
- const field = btn.getAttribute("data-input");
373
- const copy = btn.getAttribute("data-copy");
374
- if(field || copy) {
375
- btn.addEventListener("click", () => {
376
- let text;
377
- if(field) {
378
- const inputField = document.getElementById(field);
379
- text = inputField.innerText || inputField.value;
380
- }
381
- else if(copy) {
382
- text = btn.getAttribute("data-copy");
383
- }
384
- navigator.clipboard.writeText(text);
385
- const btnOrigContent = btn.innerHTML;
386
- btn.innerHTML = `${t.gvs.copied} ${fat(faCheck)}`;
387
- btn.classList.add("gvs-btn-active");
388
- setTimeout(() => {
389
- btn.innerHTML = btnOrigContent;
390
- btn.classList.remove("gvs-btn-active");
391
- }, 2000);
392
- });
393
- }
394
- }
395
- }
396
-
397
- /**
398
- * Make a button usable
399
- * @param {Element} btn
400
- * @private
401
- */
402
- export function enableButton(btn) {
403
- btn.removeAttribute("disabled");
404
- }
405
-
406
- /**
407
- * Make a button unusable
408
- * @param {Element} btn
409
- * @private
410
- */
411
- export function disableButton(btn) {
412
- btn.setAttribute("disabled", "");
413
- }
414
-
415
- /**
416
- * Transform Font Awesome icon definition into HTML element
417
- * @param {IconDefinition} i The icon to use
418
- * @param {object} [o] [FontAwesome icon parameters](https://origin.fontawesome.com/docs/apis/javascript/methods#icon-icondefinition-params)
419
- * @returns {Element} HTML element
420
- * @private
421
- */
422
- export function fa(i, o) {
423
- return icon(i, o).node[0];
424
- }
425
-
426
- /**
427
- * Transform Font Awesome icon definition into HTML text
428
- * @param {IconDefinition} i The icon to use
429
- * @param {object} [o] [FontAwesome icon parameters](https://origin.fontawesome.com/docs/apis/javascript/methods#icon-icondefinition-params)
430
- * @returns {string} HTML element as text
431
- * @private
432
- */
433
- export function fat(i, o) {
434
- return icon(i, o).html[0];
435
- }
436
-
437
- /**
438
- * Table cell with a copy link
439
- * @private
440
- */
441
- export function createLinkCell(id, url, title, buttonTitle) {
442
- const link = document.createElement("a");
443
- link.href = url;
444
- link.target = "_blank";
445
- link.title = title;
446
- link.textContent = id;
447
-
448
- const buttonContainer = createButtonSpan(`${fat(faCopy)} ${buttonTitle}`, id);
449
- return [link, buttonContainer];
450
- }
451
-
452
- /**
453
- * Create a light table
454
- * @private
455
- */
456
- export function createTable(className, rows) {
457
- const table = document.createElement("table");
458
- table.className = className;
459
-
460
- rows.forEach(({ section, value, values, classes }) => {
461
- const tr = document.createElement("tr");
462
- const th = document.createElement("th");
463
- th.scope = "row";
464
- th.textContent = section;
465
- tr.appendChild(th);
466
-
467
- const td = document.createElement("td");
468
- if(classes) { td.classList.add(...classes); }
469
- if(values) { values.forEach(v => td.appendChild(v)); }
470
- else if(value instanceof HTMLElement) { td.appendChild(value); }
471
- else { td.innerHTML = value; }
472
- tr.appendChild(td);
473
-
474
- table.appendChild(tr);
475
- });
476
-
477
- return table;
478
- }
479
-
480
- /**
481
- * Create block header
482
- * @private
483
- */
484
- export function createHeader(tag, innerHTML) {
485
- const header = document.createElement(tag);
486
- header.innerHTML = innerHTML;
487
- return header;
488
- }
489
-
490
- /**
491
- * Create copy to clipboard button
492
- * @private
493
- */
494
- export function createButtonSpan(innerHTML, dataCopy = null) {
495
- const button = document.createElement("button");
496
- button.innerHTML = innerHTML;
497
- if (dataCopy) button.setAttribute("data-copy", dataCopy);
498
-
499
- const span = document.createElement("span");
500
- span.className = "gvs-input-btn";
501
- span.appendChild(button);
502
-
503
- return span;
504
- }
505
-
506
- /**
507
- * Create an input label
508
- * @private
509
- */
510
- export function createLabel(forAttr, text, faIcon = null) {
511
- const label = document.createElement("label");
512
- label.htmlFor = forAttr;
513
- if(faIcon) { label.appendChild(fa(faIcon)); }
514
- label.appendChild(document.createTextNode(text));
515
- return label;
516
- }
517
-
518
- /**
519
- * Show a grade in a nice, user-friendly way
520
- * @param {number} grade The obtained grade
521
- * @returns {string} Nice to display grade display
522
- * @private
523
- */
524
- export function showGrade(grade, t) {
525
- let label = "<span class=\"gvs-grade\">";
526
-
527
- for(let i=1; i <= grade; i++) {
528
- label += fat(faStar);
529
- }
530
- for(let i=grade+1; i <= 5; i++) {
531
- label += fat(farStar);
532
- }
533
-
534
- label += "</span> (";
535
- if(grade === null) { label += t.gvs.metadata_quality_missing+")"; }
536
- else { label += grade + "/5)"; }
537
- return label;
538
- }
539
-
540
- /**
541
- * Displays a nice QualityScore
542
- * @param {number} grade The 1 to 5 grade
543
- * @returns {Element} The HTML code for showing the grade
544
- * @private
545
- */
546
- export function showQualityScore(grade) {
547
- const span = document.createElement("span");
548
-
549
- for(let i=1; i <= QUALITYSCORE_VALUES.length; i++) {
550
- const pv = QUALITYSCORE_VALUES[i-1];
551
- const sub = document.createElement("span");
552
- sub.appendChild(document.createTextNode(pv.label));
553
- sub.classList.add("gvs-qualityscore");
554
- sub.style.backgroundColor = pv.color;
555
- if(i === (6-grade)) {
556
- sub.classList.add("gvs-qualityscore-selected");
557
- }
558
- span.appendChild(sub);
559
- }
560
-
561
- return span;
562
- }