MikaFil commited on
Commit
13e3cdc
·
verified ·
1 Parent(s): 7237480

Update style/defaults/style.css

Browse files
Files changed (1) hide show
  1. style/defaults/style.css +464 -349
style/defaults/style.css CHANGED
@@ -1,353 +1,468 @@
1
- /* viewer.css */
2
-
3
- /* Widget container styling */
4
- .ply-widget-container {
5
- position: relative;
6
- width: 100%;
7
- height: 0;
8
- background-color: white;
9
- transition: all 0.3s ease;
10
- box-sizing: border-box;
11
- overflow: hidden;
12
- }
13
- .ply-widget-container.fake-fullscreen {
14
- position: fixed !important;
15
- top: 0 !important;
16
- left: 0 !important;
17
- width: 100vw !important;
18
- height: 100vh !important;
19
- padding-bottom: 0 !important;
20
- z-index: 9999 !important;
21
- background-color: black;
22
- border-radius: 0 !important;
23
- margin: 0 !important;
24
- max-width: 100vw !important;
25
- max-height: 100vh !important;
26
- box-sizing: border-box;
27
- overflow: hidden;
28
- }
29
- .ply-widget-container:fullscreen,
30
- .ply-widget-container:-webkit-full-screen,
31
- .ply-widget-container:-moz-full-screen,
32
- .ply-widget-container:-ms-fullscreen {
33
- width: 100vw !important;
34
- height: 100vh !important;
35
- padding-bottom: 0 !important;
36
- border-radius: 0 !important;
37
- background-color: black;
38
- }
39
- .viewer-container {
40
- display: none;
41
- position: absolute;
42
- top: 0; left: 0; right: 0; bottom: 0;
43
- width: 100%; height: 100%;
44
- background: black;
45
- border: 1px solid #474558;
46
- border-radius: 10px;
47
- overflow: hidden;
48
- box-sizing: border-box;
49
- transition: all 0.3s ease;
50
- min-height: 100%;
51
- object-fit: contain;
52
- }
53
- .fake-fullscreen .viewer-container,
54
- :fullscreen .viewer-container,
55
- :-webkit-full-screen .viewer-container,
56
- :-moz-full-screen .viewer-container,
57
- :-ms-fullscreen .viewer-container {
58
- border-radius: 0;
59
- border: none;
60
- width: 100%;
61
- height: 100%;
62
- }
63
- .ply-canvas {
64
- width: 100%;
65
- height: 100%;
66
- display: block;
67
- background-color: transparent;
68
- z-index: 1;
69
- position: absolute;
70
- top: 0; left: 0; right: 0; bottom: 0;
71
- }
72
- .fake-fullscreen .ply-canvas,
73
- :fullscreen .ply-canvas,
74
- :-webkit-full-screen .ply-canvas,
75
- :-moz-full-screen .ply-canvas,
76
- :-ms-fullscreen .ply-canvas {
77
- width: 100vw;
78
- height: 100vh;
79
- }
80
- .progress-dialog {
81
- position: absolute;
82
- top: 50%; left: 50%;
83
- transform: translate(-50%, -50%);
84
- border: none;
85
- background: rgba(0,0,0,0.7);
86
- padding: 20px;
87
- border-radius: 5px;
88
- z-index: 1000;
89
- display: none;
90
- color: white;
91
- }
92
- progress {
93
- width: 250px;
94
- height: 15px;
95
- appearance: none;
96
- border: none;
97
- border-radius: 10px;
98
- overflow: hidden;
99
- }
100
- progress::-webkit-progress-bar {
101
- background-color: #333;
102
- border-radius: 10px;
103
- }
104
- progress::-webkit-progress-value {
105
- background-color: #4682B4;
106
- border-radius: 10px;
107
- }
108
- progress::-moz-progress-bar {
109
- background-color: #4682B4;
110
- border-radius: 10px;
111
- }
112
- /* Menu (instructions) content styling */
113
- .menu-content {
114
- display: none;
115
- position: absolute;
116
- top: 50%; left: 50%;
117
- transform: translate(-50%, -50%);
118
- background: rgba(242,240,239,0.9);
119
- color: #545454;
120
- border: 1px solid #ddd;
121
- border-radius: 10px;
122
- padding: 18px 24px;
123
- font-size: 15px;
124
- line-height: 1.4;
125
- box-shadow: none;
126
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
127
- z-index: 1010;
128
- }
129
- .help-close {
130
- position: absolute;
131
- top: 8px;
132
- right: 8px;
133
- background-color: #B0B0B0;
134
- color: #333;
135
- border: none;
136
- border-radius: 4px;
137
- width: 24px;
138
- height: 24px;
139
- line-height: 24px;
140
- text-align: center;
141
- cursor: pointer;
142
- font-size: 16px;
143
- display: flex;
144
- align-items: center;
145
- justify-content: center;
146
- padding: 0;
147
- }
148
- .widget-button {
149
- position: absolute;
150
- width: 32px;
151
- height: 32px;
152
- background-color: #F2F0EF;
153
- border: 1px solid #ccc;
154
- border-radius: 8px;
155
- cursor: pointer;
156
- font-size: 16px;
157
- color: #545454;
158
- display: flex !important;
159
- align-items: center;
160
- justify-content: center;
161
- transition: background-color 0.2s ease;
162
- z-index: 1000;
163
- opacity: 1 !important;
164
- visibility: visible !important;
165
- margin-right: 8px;
166
- }
167
- .widget-button:hover { background-color: rgba(242,240,239,0.7); }
168
- .fullscreen-toggle { top: 12px; right: 12px; }
169
- .help-toggle { top: 12px; right: 52px; font-size: 18px; }
170
- .reset-camera-btn { top: 12px; right: 92px; font-size: 18px; line-height: normal; padding: 0; }
171
- .tooltips-toggle { top: 12px; right: 132px; font-size: 18px; }
172
- .fake-fullscreen .widget-button,
173
- :fullscreen .widget-button,
174
- :-webkit-full-screen .widget-button,
175
- :-moz-full-screen .widget-button,
176
- :-ms-fullscreen .widget-button { z-index: 10000; }
177
-
178
- /* --------- TOOLTIP PANEL ----------- */
179
- /* ...rest of your CSS remains unchanged... */
180
-
181
- /* --------- TOOLTIP PANEL ----------- */
182
- .tooltip-panel {
183
- position: absolute;
184
- top: 50%;
185
- right: 5%;
186
- transform: translate(0, -50%);
187
- background: rgba(242,240,239,0.97);
188
- color: #545454;
189
- border: 1px solid #ddd;
190
- border-radius: 6px;
191
- padding: 20px 20px 16px 16px; /* Extra top/right for button */
192
- max-width: 340px;
193
- width: 92vw;
194
- min-width: 180px;
195
- min-height: 60px;
196
- max-height: 90vh;
197
- z-index: 20000;
198
- display: none;
199
- flex-direction: column;
200
- align-items: flex-start;
201
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
202
- overflow: auto;
203
- box-sizing: border-box;
204
- position: absolute;
205
- }
206
-
207
- /* Ensure content does not go under close button */
208
- .tooltip-content {
209
- width: 100%;
210
- min-width: 160px;
211
- max-width: 100%;
212
- box-sizing: border-box;
213
- display: flex;
214
- flex-direction: column;
215
- align-items: flex-start;
216
- overflow: hidden;
217
- margin-top: 0;
218
- }
219
-
220
- /* CLOSE BUTTON AS SQUARE WITH ROUNDED CORNERS */
221
- .tooltip-close {
222
- position: absolute;
223
- top: 12px;
224
- right: 12px;
225
- width: 32px;
226
- height: 32px;
227
- background: #F2F0EF;
228
- color: #333;
229
- border: 1px solid #ccc;
230
- border-radius: 8px;
231
- font-size: 17px;
232
- font-weight: bold;
233
- display: flex;
234
- align-items: center;
235
- justify-content: center;
236
- line-height: 1;
237
- cursor: pointer;
238
- z-index: 2;
239
- transition: background 0.18s;
240
- box-sizing: border-box;
241
- padding: 0;
242
- }
243
- .tooltip-close:hover,
244
- .tooltip-close:focus {
245
- background: #e0e0e0;
246
- outline: none;
247
- }
248
-
249
- /* Tooltip text and image */
250
- .tooltip-text {
251
- margin-bottom: 10px;
252
- font-size: 14px;
253
- line-height: 1.4;
254
- overflow-wrap: break-word;
255
- word-break: break-word;
256
- max-width: 100%;
257
- }
258
- .tooltip-image {
259
- max-width: 100%;
260
- max-height: 35vh;
261
- border-radius: 4px;
262
- margin-top: 5px;
263
- display: block;
264
- object-fit: contain;
265
- box-sizing: border-box;
266
- }
267
-
268
- /* --- MOBILE adjustments --- */
269
- @media (max-width: 600px) {
270
- .tooltip-panel {
271
- top: auto;
272
- bottom: 8px;
273
- right: 3vw;
274
- left: 3vw;
275
- transform: none;
276
- width: auto;
277
- max-width: 94vw;
278
- min-width: 0;
279
- max-height: 55vh;
280
- padding: 16px 10px 12px 10px;
281
- font-size: 13.5px;
282
- }
283
- .tooltip-close {
284
- top: 8px;
285
- right: 8px;
286
- width: 26px;
287
- height: 26px;
288
- font-size: 15px;
289
- }
290
- .tooltip-image {
291
- max-height: 22vh;
292
- }
293
- }
294
-
295
-
296
- /* --- Mobile adjustments --- */
297
- @media (max-width: 600px) {
298
- .tooltip-panel {
299
- top: auto;
300
- bottom: 8px;
301
- right: 3vw;
302
- left: 3vw;
303
- transform: none;
304
- width: auto;
305
- max-width: 94vw;
306
- min-width: 0;
307
- max-height: 55vh;
308
- padding: 28px 14px 12px 12px; /* extra for top, right */
309
- font-size: 13.5px;
310
- }
311
- .tooltip-content {
312
- min-width: 0;
313
- }
314
- .tooltip-close {
315
- top: 6px;
316
- right: 6px;
317
- width: 26px;
318
- height: 26px;
319
- font-size: 15px;
320
  }
321
- .tooltip-image {
322
- max-height: 22vh;
 
 
 
 
 
 
 
 
 
 
323
  }
324
- }
325
-
326
- .ply-widget-container.mobile .widget-button {
327
- width: 24px;
328
- height: 24px;
329
- font-size: 12px;
330
- }
331
- .ply-widget-container.mobile .help-toggle { font-size: 14px; }
332
- .ply-widget-container.mobile .fullscreen-toggle { top: 8px; right: 8px; }
333
- .ply-widget-container.mobile .help-toggle { top: 8px; right: 40px; }
334
- .ply-widget-container.mobile .reset-camera-btn { top: 8px; right: 72px; }
335
- .ply-widget-container.mobile .tooltips-toggle { top: 8px; right: 104px; }
336
-
337
- #application-canvas { width: 100%; height: 100%; display: block; }
338
- html, body { margin: 0; padding: 0; height: 100%; }
339
- .progress-dialog p { margin: 0; padding: 5px; }
340
-
341
- @media (max-width: 600px) {
342
- .menu-content {
343
- width: 85vw;
344
- max-height: 55vh;
345
- overflow-y: auto;
346
- padding: 40px 18px 14px;
347
- font-size: 14px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  }
349
- .menu-content .help-close {
350
- top: 6px;
351
- right: 6px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  }
353
- }
 
1
+ // interface.js
2
+ // ==============================
3
+
4
+ const currentScriptTag = document.currentScript;
5
+
6
+ (function() {
7
+ // 1. Locate the <script> and read data-config
8
+ let scriptTag = currentScriptTag;
9
+ if (!scriptTag) {
10
+ const scripts = document.getElementsByTagName('script');
11
+ for (let i = 0; i < scripts.length; i++) {
12
+ if (scripts[i].src.includes('interface.js') && scripts[i].hasAttribute('data-config')) {
13
+ scriptTag = scripts[i];
14
+ break;
15
+ }
16
+ }
17
+ if (!scriptTag && scripts.length > 0) {
18
+ scriptTag = scripts[scripts.length - 1];
19
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
+
22
+ const configUrl = scriptTag.getAttribute('data-config');
23
+ let config = {};
24
+ if (configUrl) {
25
+ fetch(configUrl)
26
+ .then(response => response.json())
27
+ .then(cfg => {
28
+ config = cfg;
29
+ main();
30
+ });
31
+ } else {
32
+ return;
33
  }
34
+
35
+ // Inject CSS for pointer events and z-index insurance!
36
+ function injectCompatCSS() {
37
+ if (document.getElementById('ply-compat-css')) return;
38
+ const style = document.createElement('style');
39
+ style.id = 'ply-compat-css';
40
+ style.textContent = `
41
+ .ply-widget-container,
42
+ .viewer-container,
43
+ .ply-canvas,
44
+ .tooltip-panel,
45
+ .widget-button,
46
+ .menu-content {
47
+ pointer-events: auto !important;
48
+ z-index: 9999 !important;
49
+ }
50
+ .tooltip-panel {
51
+ max-width: 90vw !important;
52
+ max-height: 80vh !important;
53
+ overflow: auto !important;
54
+ box-sizing: border-box !important;
55
+ }
56
+ .tooltip-content {
57
+ position: relative;
58
+ width: 100%;
59
+ box-sizing: border-box;
60
+ padding-top: 0;
61
+ }
62
+ .tooltip-close {
63
+ position: absolute;
64
+ top: 12px;
65
+ right: 12px;
66
+ width: 32px;
67
+ height: 32px;
68
+ border-radius: 8px;
69
+ background: #F2F0EF;
70
+ color: #545454;
71
+ display: flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ font-size: 18px;
75
+ z-index: 10001;
76
+ border: 1px solid #ccc;
77
+ cursor: pointer;
78
+ box-sizing: border-box;
79
+ }
80
+ .tooltip-panel img {
81
+ max-width: 100%;
82
+ height: auto;
83
+ display: block;
84
+ margin-top: 8px;
85
+ border-radius: 6px;
86
+ }
87
+ @media (max-width: 600px) {
88
+ .tooltip-panel {
89
+ max-width: 96vw !important;
90
+ max-height: 60vh !important;
91
+ }
92
+ .tooltip-close {
93
+ top: 8px;
94
+ right: 8px;
95
+ width: 28px;
96
+ height: 28px;
97
+ font-size: 16px;
98
+ }
99
+ }
100
+ `;
101
+ document.head.appendChild(style);
102
  }
103
+
104
+ function main() {
105
+ injectCompatCSS();
106
+
107
+ // 3. Generate a unique instanceId for this widget
108
+ const instanceId = Math.random().toString(36).substr(2, 8);
109
+
110
+ // 4. Compute the aspect ratio (padding-bottom %)
111
+ let aspectPercent = "100%";
112
+ if (config.aspect) {
113
+ if (config.aspect.includes(":")) {
114
+ const parts = config.aspect.split(":");
115
+ const w = parseFloat(parts[0]);
116
+ const h = parseFloat(parts[1]);
117
+ if (!isNaN(w) && !isNaN(h) && w > 0) {
118
+ aspectPercent = (h / w * 100) + "%";
119
+ }
120
+ } else {
121
+ const aspectValue = parseFloat(config.aspect);
122
+ if (!isNaN(aspectValue) && aspectValue > 0) {
123
+ aspectPercent = (100 / aspectValue) + "%";
124
+ }
125
+ }
126
+ } else {
127
+ const parentContainer = scriptTag.parentNode;
128
+ const containerWidth = parentContainer.offsetWidth;
129
+ const containerHeight = parentContainer.offsetHeight;
130
+ if (containerWidth > 0 && containerHeight > 0) {
131
+ aspectPercent = (containerHeight / containerWidth * 100) + "%";
132
+ }
133
+ }
134
+
135
+ // 5. Create the widget container
136
+ const widgetContainer = document.createElement('div');
137
+ widgetContainer.id = 'ply-widget-container-' + instanceId;
138
+ widgetContainer.classList.add('ply-widget-container');
139
+ widgetContainer.style.height = "0";
140
+ widgetContainer.style.paddingBottom = aspectPercent;
141
+ widgetContainer.setAttribute('data-original-aspect', aspectPercent);
142
+
143
+ // Conditionally include the “tooltips-toggle” button only if config.tooltips_url is defined
144
+ const tooltipsButtonHTML = config.tooltips_url
145
+ ? `<button id="tooltips-toggle-${instanceId}" class="widget-button tooltips-toggle">⦿</button>`
146
+ : '';
147
+
148
+ widgetContainer.innerHTML = `
149
+ <div id="viewer-container-${instanceId}" class="viewer-container">
150
+ <div id="progress-dialog-${instanceId}" class="progress-dialog">
151
+ <progress id="progress-indicator-${instanceId}" max="100" value="0"></progress>
152
+ </div>
153
+ <button id="fullscreen-toggle-${instanceId}" class="widget-button fullscreen-toggle">⇱</button>
154
+ <button id="help-toggle-${instanceId}" class="widget-button help-toggle">?</button>
155
+ <button id="reset-camera-btn-${instanceId}" class="widget-button reset-camera-btn">
156
+ <span class="reset-icon">⟲</span>
157
+ </button>
158
+ ${tooltipsButtonHTML}
159
+ <div id="menu-content-${instanceId}" class="menu-content">
160
+ <span id="help-close-${instanceId}" class="help-close">×</span>
161
+ <div class="help-text"></div>
162
+ </div>
163
+ </div>
164
+ <div id="tooltip-panel" class="tooltip-panel" style="display: none;">
165
+ <div class="tooltip-content">
166
+ <span id="tooltip-close" class="tooltip-close">×</span>
167
+ <div id="tooltip-text" class="tooltip-text"></div>
168
+ <img id="tooltip-image" class="tooltip-image" src="" alt="" style="display: none;" />
169
+ </div>
170
+ </div>
171
+ `;
172
+
173
+ scriptTag.parentNode.appendChild(widgetContainer);
174
+
175
+ // 6. Grab references to new DOM elements
176
+ const viewerContainerElem = document.getElementById('viewer-container-' + instanceId);
177
+ const fullscreenToggle = document.getElementById('fullscreen-toggle-' + instanceId);
178
+ const helpToggle = document.getElementById('help-toggle-' + instanceId);
179
+ const helpCloseBtn = document.getElementById('help-close-' + instanceId);
180
+ const resetCameraBtn = document.getElementById('reset-camera-btn-' + instanceId);
181
+ const tooltipsToggleBtn = document.getElementById('tooltips-toggle-' + instanceId);
182
+ const menuContent = document.getElementById('menu-content-' + instanceId);
183
+ const helpTextDiv = menuContent.querySelector('.help-text');
184
+ const tooltipPanel = document.getElementById('tooltip-panel');
185
+ const tooltipTextDiv = document.getElementById('tooltip-text');
186
+ const tooltipImage = document.getElementById('tooltip-image');
187
+ const tooltipCloseBtn = document.getElementById('tooltip-close');
188
+
189
+ const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
190
+ const isMobile = isIOS || /Android/i.test(navigator.userAgent);
191
+
192
+ const tooltipInstruction = config.tooltips_url
193
+ ? '- Cliquez sur ⦿ pour afficher/masquer les tooltips.<br>'
194
+ : '';
195
+
196
+ if (isMobile) {
197
+ helpTextDiv.innerHTML =
198
+ '- Pour vous déplacer, glissez deux doigts sur l\'écran.<br>' +
199
+ '- Pour orbiter, utilisez un doigt.<br>' +
200
+ '- Pour zoomer, pincez avec deux doigts.<br>' +
201
+ tooltipInstruction +
202
+ '- ⟲ Réinitialise la caméra.<br>' +
203
+ '- ⇱ Passe en plein écran.<br>';
204
+ } else {
205
+ helpTextDiv.innerHTML =
206
+ '- orbitez avec le clic droit<br>' +
207
+ '- zoomez avec la molette<br>' +
208
+ '- déplacez vous avec le clic gauche<br>' +
209
+ tooltipInstruction +
210
+ '- ⟲ Réinitialise la caméra.<br>' +
211
+ '- ⇱ Passe en plein écran.<br>';
212
+ }
213
+
214
+ menuContent.style.display = 'block';
215
+ viewerContainerElem.style.display = 'block';
216
+
217
+ let dragHide = null;
218
+ let tooltipJustOpened = false;
219
+
220
+ function hideTooltipPanel() {
221
+ if (dragHide) {
222
+ viewerContainerElem.removeEventListener('pointermove', dragHide);
223
+ dragHide = null;
224
+ }
225
+ tooltipPanel.style.display = 'none';
226
+ }
227
+ function hideHelpPanel() {
228
+ menuContent.style.display = 'none';
229
+ }
230
+
231
+ // 7. Dynamically load viewer.js
232
+ let viewerModule;
233
+ import('https://mikafil-viewer-gs.static.hf.space/viewer.js')
234
+ .then(mod => {
235
+ viewerModule = mod;
236
+ return viewerModule.initializeViewer(config, instanceId);
237
+ })
238
+ .then(() => {
239
+ const canvasId = 'canvas-' + instanceId;
240
+ const canvasEl = document.getElementById(canvasId);
241
+
242
+ // 8. Conditional display of tooltips-toggle button
243
+ if (tooltipsToggleBtn) {
244
+ if (!config.tooltips_url) {
245
+ tooltipsToggleBtn.style.display = 'none';
246
+ } else {
247
+ fetch(config.tooltips_url)
248
+ .then(resp => { if (!resp.ok) tooltipsToggleBtn.style.display = 'none'; })
249
+ .catch(() => { tooltipsToggleBtn.style.display = 'none'; });
250
+ }
251
+ }
252
+
253
+ // 9. Fullscreen / state-preservation logic
254
+ let isFullscreen = false;
255
+ let savedState = null;
256
+
257
+ function saveCurrentState() {
258
+ if (isFullscreen) return;
259
+ const originalAspect = widgetContainer.getAttribute('data-original-aspect') || aspectPercent;
260
+ savedState = {
261
+ widget: {
262
+ position: widgetContainer.style.position,
263
+ top: widgetContainer.style.top,
264
+ left: widgetContainer.style.left,
265
+ width: widgetContainer.style.width,
266
+ height: widgetContainer.style.height,
267
+ maxWidth: widgetContainer.style.maxWidth,
268
+ maxHeight:widgetContainer.style.maxHeight,
269
+ paddingBottom: widgetContainer.style.paddingBottom || originalAspect,
270
+ margin: widgetContainer.style.margin,
271
+ },
272
+ viewer: {
273
+ borderRadius: viewerContainerElem.style.borderRadius,
274
+ border: viewerContainerElem.style.border,
275
+ }
276
+ };
277
+ }
278
+
279
+ function restoreOriginalStyles() {
280
+ if (!savedState) return;
281
+ const aspectToUse = savedState.widget.paddingBottom;
282
+ widgetContainer.style.position = savedState.widget.position || "";
283
+ widgetContainer.style.top = savedState.widget.top || "";
284
+ widgetContainer.style.left = savedState.widget.left || "";
285
+ widgetContainer.style.width = "100%";
286
+ widgetContainer.style.height = "0";
287
+ widgetContainer.style.maxWidth = savedState.widget.maxWidth || "";
288
+ widgetContainer.style.maxHeight = savedState.widget.maxHeight || "";
289
+ widgetContainer.style.paddingBottom= aspectToUse;
290
+ widgetContainer.style.margin = savedState.widget.margin || "";
291
+ widgetContainer.classList.remove('fake-fullscreen');
292
+
293
+ viewerContainerElem.style.position = "absolute";
294
+ viewerContainerElem.style.top = "0";
295
+ viewerContainerElem.style.left = "0";
296
+ viewerContainerElem.style.right = "0";
297
+ viewerContainerElem.style.bottom = "0";
298
+ viewerContainerElem.style.width = "100%";
299
+ viewerContainerElem.style.height = "100%";
300
+ viewerContainerElem.style.borderRadius = savedState.viewer.borderRadius || "";
301
+ viewerContainerElem.style.border = savedState.viewer.border || "";
302
+
303
+ if (viewerModule.app) {
304
+ viewerModule.app.resizeCanvas(
305
+ viewerContainerElem.clientWidth,
306
+ viewerContainerElem.clientHeight
307
+ );
308
+ }
309
+ if (fullscreenToggle) fullscreenToggle.textContent = '⇱';
310
+
311
+ savedState = null;
312
+ }
313
+
314
+ function applyFullscreenStyles() {
315
+ widgetContainer.style.position = 'fixed';
316
+ widgetContainer.style.top = '0';
317
+ widgetContainer.style.left = '0';
318
+ widgetContainer.style.width = '100vw';
319
+ widgetContainer.style.height = '100vh';
320
+ widgetContainer.style.maxWidth = '100vw';
321
+ widgetContainer.style.maxHeight = '100vh';
322
+ widgetContainer.style.paddingBottom = '0';
323
+ widgetContainer.style.margin = '0';
324
+ widgetContainer.style.border = 'none';
325
+ widgetContainer.style.borderRadius = '0';
326
+
327
+ viewerContainerElem.style.width = '100%';
328
+ viewerContainerElem.style.height = '100%';
329
+ viewerContainerElem.style.borderRadius= '0';
330
+ viewerContainerElem.style.border = 'none';
331
+
332
+ if (viewerModule.app) {
333
+ viewerModule.app.resizeCanvas(window.innerWidth, window.innerHeight);
334
+ }
335
+
336
+ if (fullscreenToggle) fullscreenToggle.textContent = '⇲';
337
+ isFullscreen = true;
338
+ }
339
+
340
+ function enterFullscreen() {
341
+ if (!savedState) saveCurrentState();
342
+ if (isIOS) {
343
+ applyFullscreenStyles();
344
+ widgetContainer.classList.add('fake-fullscreen');
345
+ } else if (widgetContainer.requestFullscreen) {
346
+ widgetContainer.requestFullscreen()
347
+ .then(applyFullscreenStyles)
348
+ .catch(() => {
349
+ applyFullscreenStyles();
350
+ widgetContainer.classList.add('fake-fullscreen');
351
+ });
352
+ } else {
353
+ applyFullscreenStyles();
354
+ widgetContainer.classList.add('fake-fullscreen');
355
+ }
356
+ }
357
+
358
+ function exitFullscreen() {
359
+ if (document.fullscreenElement === widgetContainer && document.exitFullscreen) {
360
+ document.exitFullscreen().catch(() => {});
361
+ }
362
+ widgetContainer.classList.remove('fake-fullscreen');
363
+ restoreOriginalStyles();
364
+ isFullscreen = false;
365
+ if (fullscreenToggle) fullscreenToggle.textContent = '⇱';
366
+ }
367
+
368
+ fullscreenToggle.addEventListener('click', () => {
369
+ hideTooltipPanel();
370
+ isFullscreen ? exitFullscreen() : enterFullscreen();
371
+ });
372
+
373
+ document.addEventListener('fullscreenchange', () => {
374
+ if (!document.fullscreenElement && isFullscreen) {
375
+ isFullscreen = false;
376
+ restoreOriginalStyles();
377
+ if (fullscreenToggle) fullscreenToggle.textContent = '⇱';
378
+ } else if (document.fullscreenElement === widgetContainer) {
379
+ if (fullscreenToggle) fullscreenToggle.textContent = '⇲';
380
+ }
381
+ });
382
+
383
+ helpToggle.addEventListener('click', (e) => {
384
+ hideTooltipPanel();
385
+ e.stopPropagation();
386
+ menuContent.style.display = menuContent.style.display === 'block' ? 'none' : 'block';
387
+ });
388
+ helpCloseBtn.addEventListener('click', hideHelpPanel);
389
+
390
+ resetCameraBtn.addEventListener('click', () => {
391
+ hideTooltipPanel();
392
+ if (viewerModule.resetViewerCamera) {
393
+ viewerModule.resetViewerCamera();
394
+ }
395
+ });
396
+
397
+ if (tooltipsToggleBtn) {
398
+ let tooltipsVisible = !!config.showTooltipsDefault;
399
+ tooltipsToggleBtn.style.opacity = tooltipsVisible ? '1' : '0.5';
400
+ tooltipsToggleBtn.addEventListener('click', () => {
401
+ hideTooltipPanel();
402
+ tooltipsVisible = !tooltipsVisible;
403
+ tooltipsToggleBtn.style.opacity = tooltipsVisible ? '1' : '0.5';
404
+ document.dispatchEvent(new CustomEvent('toggle-tooltips', { detail: { visible: tooltipsVisible } }));
405
+ });
406
+ }
407
+
408
+ tooltipCloseBtn.addEventListener('click', hideTooltipPanel);
409
+
410
+ // TOOLTIP POPUP + RELIABILITY TWEAK: add 0.1s delay before dragHide is active
411
+ document.addEventListener('tooltip-selected', (evt) => {
412
+ const { title, description, imgUrl } = evt.detail;
413
+ tooltipTextDiv.innerHTML = `<strong>${title}</strong><br>${description}`;
414
+ if (imgUrl) {
415
+ tooltipImage.src = imgUrl;
416
+ tooltipImage.style.display = 'block';
417
+ } else {
418
+ tooltipImage.style.display = 'none';
419
+ }
420
+ tooltipPanel.style.display = 'flex';
421
+
422
+ // Focus for accessibility (mobile esp.)
423
+ tooltipCloseBtn.focus();
424
+
425
+ tooltipJustOpened = true;
426
+ if (dragHide) {
427
+ viewerContainerElem.removeEventListener('pointermove', dragHide);
428
+ dragHide = null;
429
+ }
430
+ setTimeout(() => {
431
+ tooltipJustOpened = false;
432
+ }, 120);
433
+
434
+ dragHide = (e) => {
435
+ if (tooltipJustOpened) return; // Don't close immediately after open
436
+ if ((e.pointerType === 'mouse' && e.buttons !== 0) || e.pointerType === 'touch') {
437
+ hideTooltipPanel();
438
+ }
439
+ };
440
+ viewerContainerElem.addEventListener('pointermove', dragHide);
441
+ });
442
+
443
+ if (canvasEl) {
444
+ canvasEl.addEventListener('wheel', hideTooltipPanel, { passive: true });
445
+ }
446
+ document.addEventListener('keydown', (e) => {
447
+ if ((e.key === 'Escape' || e.key === 'Esc') && isFullscreen) exitFullscreen();
448
+ });
449
+ window.addEventListener('resize', () => {
450
+ if (viewerModule.app) {
451
+ if (isFullscreen) {
452
+ viewerModule.app.resizeCanvas(window.innerWidth, window.innerHeight);
453
+ } else {
454
+ viewerModule.app.resizeCanvas(
455
+ viewerContainerElem.clientWidth,
456
+ viewerContainerElem.clientHeight
457
+ );
458
+ }
459
+ }
460
+ });
461
+
462
+ setTimeout(() => {
463
+ saveCurrentState();
464
+ document.dispatchEvent(new CustomEvent('toggle-tooltips', { detail: { visible: !!config.showTooltipsDefault } }));
465
+ }, 200);
466
+ });
467
  }
468
+ })();