MikaFil commited on
Commit
e812f40
Β·
verified Β·
1 Parent(s): 8ddb00d

Update interface.js

Browse files
Files changed (1) hide show
  1. interface.js +365 -31
interface.js CHANGED
@@ -80,8 +80,8 @@ const currentScriptTag = document.currentScript;
80
  widgetContainer.style.paddingBottom = aspectPercent;
81
  widgetContainer.setAttribute('data-original-aspect', aspectPercent);
82
 
83
- // Add the 3D-viewer HTML + πŸ“ toggle + tooltip markup
84
- widgetContainer.innerHTML = `
85
  <div id="viewer-container-${instanceId}" class="viewer-container">
86
  <div id="progress-dialog-${instanceId}" class="progress-dialog">
87
  <progress id="progress-indicator-${instanceId}" max="100" value="0"></progress>
@@ -91,21 +91,22 @@ const currentScriptTag = document.currentScript;
91
  <button id="reset-camera-btn-${instanceId}" class="widget-button reset-camera-btn">
92
  <span class="reset-icon">⟲</span>
93
  </button>
94
- <button id="points-toggle-${instanceId}" class="widget-button points-toggle">β¦Ώ</button>
95
  <div id="menu-content-${instanceId}" class="menu-content">
96
  <span id="help-close-${instanceId}" class="help-close">Γ—</span>
97
  <div class="help-text"></div>
98
  </div>
99
  </div>
100
- <div id="point-tooltip" class="point-tooltip" style="display: none;">
101
- <div class="point-tooltip-content">
102
- <span id="point-tooltip-close" class="point-tooltip-close">Γ—</span>
103
- <div id="point-tooltip-text" class="point-tooltip-text"></div>
104
- <img id="point-tooltip-image" class="point-tooltip-image" src="" alt="" style="display: none;" />
105
  </div>
106
  </div>
107
- `;
108
 
 
109
  scriptTag.parentNode.appendChild(widgetContainer);
110
 
111
  // ─── 6. Grab references to new DOM elements ──────────────────────────────────
@@ -114,51 +115,63 @@ const currentScriptTag = document.currentScript;
114
  const helpToggle = document.getElementById('help-toggle-' + instanceId);
115
  const helpCloseBtn = document.getElementById('help-close-' + instanceId);
116
  const resetCameraBtn = document.getElementById('reset-camera-btn-' + instanceId);
117
- const pointsToggleBtn = document.getElementById('points-toggle-' + instanceId);
118
  const menuContent = document.getElementById('menu-content-' + instanceId);
119
  const helpTextDiv = menuContent.querySelector('.help-text');
120
 
121
- // Tooltip elements
122
- const tooltipDiv = document.getElementById('point-tooltip');
123
- const tooltipTextDiv = document.getElementById('point-tooltip-text');
124
- const tooltipImage = document.getElementById('point-tooltip-image');
125
- const tooltipCloseBtn = document.getElementById('point-tooltip-close');
126
 
127
- // Device detection for help text
128
  const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
129
  const isMobile = isIOS || /Android/i.test(navigator.userAgent);
130
 
131
- // Conditionally include tooltip instruction only if points_url exists
132
- const tooltipInstruction = config.points_url
133
- ? '- Cliquez sur β¦Ώ pour afficher/masquer les points d’information.<br>'
134
  : '';
135
 
136
- // Fill help text with instructions, plus two new French lines
137
  if (isMobile) {
138
- helpTextDiv.innerHTML = `
139
  - Pour vous dΓ©placer, glissez deux doigts sur l'Γ©cran.<br>
140
  - Pour orbiter, utilisez un doigt.<br>
141
  - Pour zoomer, pincez avec deux doigts.<br>
142
  ${tooltipInstruction}
143
- - ⟲ Réinitialise la caméra.<br>
144
- - ⇱ Passe en plein Γ©cran.<br>
145
- `;
146
  } else {
147
- helpTextDiv.innerHTML = `
148
  - orbitez avec le clic droit<br>
149
  - zoomez avec la molette<br>
150
  - dΓ©placez vous avec le clic gauche<br>
151
  ${tooltipInstruction}
152
- - ⟲ Réinitialise la caméra.<br>
153
- - ⇱ Passe en plein Γ©cran.<br>
154
- `;
155
  }
156
 
157
  // Ensure instructions panel is visible by default
158
  menuContent.style.display = 'block';
 
159
  viewerContainerElem.style.display = 'block';
160
 
161
- // …rest of the original working tooltip, drag-hide, fullscreen, resize, dynamic-import logic remains unchanged…
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
  // ─── 7. Dynamically load viewer.js ─────────────────────────────────────────
164
  let viewerModule;
@@ -170,6 +183,327 @@ const currentScriptTag = document.currentScript;
170
  return;
171
  }
172
 
173
- // …etc.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
- })();
 
80
  widgetContainer.style.paddingBottom = aspectPercent;
81
  widgetContainer.setAttribute('data-original-aspect', aspectPercent);
82
 
83
+ // Add the 3D-viewer HTML + β¦Ώ toggle + tooltip + help HTML
84
+ widgetContainer.innerHTML =
85
  <div id="viewer-container-${instanceId}" class="viewer-container">
86
  <div id="progress-dialog-${instanceId}" class="progress-dialog">
87
  <progress id="progress-indicator-${instanceId}" max="100" value="0"></progress>
 
91
  <button id="reset-camera-btn-${instanceId}" class="widget-button reset-camera-btn">
92
  <span class="reset-icon">⟲</span>
93
  </button>
94
+ <button id="tooltips-toggle-${instanceId}" class="widget-button tooltips-toggle">β¦Ώ</button>
95
  <div id="menu-content-${instanceId}" class="menu-content">
96
  <span id="help-close-${instanceId}" class="help-close">Γ—</span>
97
  <div class="help-text"></div>
98
  </div>
99
  </div>
100
+ <div id="tooltip-panel" class="tooltip-panel" style="display: none;">
101
+ <div class="tooltip-content">
102
+ <span id="tooltip-close" class="tooltip-close">Γ—</span>
103
+ <div id="tooltip-text" class="tooltip-text"></div>
104
+ <img id="tooltip-image" class="tooltip-image" src="" alt="" style="display: none;" />
105
  </div>
106
  </div>
107
+ ;
108
 
109
+ // Append the widget container immediately after the <script> tag
110
  scriptTag.parentNode.appendChild(widgetContainer);
111
 
112
  // ─── 6. Grab references to new DOM elements ──────────────────────────────────
 
115
  const helpToggle = document.getElementById('help-toggle-' + instanceId);
116
  const helpCloseBtn = document.getElementById('help-close-' + instanceId);
117
  const resetCameraBtn = document.getElementById('reset-camera-btn-' + instanceId);
118
+ const tooltipsToggleBtn = document.getElementById('tooltips-toggle-' + instanceId);
119
  const menuContent = document.getElementById('menu-content-' + instanceId);
120
  const helpTextDiv = menuContent.querySelector('.help-text');
121
 
122
+ // Tooltip panel elements
123
+ const tooltipPanel = document.getElementById('tooltip-panel');
124
+ const tooltipTextDiv = document.getElementById('tooltip-text');
125
+ const tooltipImage = document.getElementById('tooltip-image');
126
+ const tooltipCloseBtn = document.getElementById('tooltip-close');
127
 
128
+ // ─── 6a. Detect mobile vs. desktop ────────────────────────────────────────────
129
  const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
130
  const isMobile = isIOS || /Android/i.test(navigator.userAgent);
131
 
132
+ // Conditionally include the French tooltip instruction line if tooltips_url exists
133
+ const tooltipInstruction = config.tooltips_url
134
+ ? '- Cliquez sur β¦Ώ pour afficher/masquer les tooltips.<br>'
135
  : '';
136
 
137
+ // Fill help text with appropriate instructions
138
  if (isMobile) {
139
+ helpTextDiv.innerHTML =
140
  - Pour vous dΓ©placer, glissez deux doigts sur l'Γ©cran.<br>
141
  - Pour orbiter, utilisez un doigt.<br>
142
  - Pour zoomer, pincez avec deux doigts.<br>
143
  ${tooltipInstruction}
144
+ ;
 
 
145
  } else {
146
+ helpTextDiv.innerHTML =
147
  - orbitez avec le clic droit<br>
148
  - zoomez avec la molette<br>
149
  - dΓ©placez vous avec le clic gauche<br>
150
  ${tooltipInstruction}
151
+ ;
 
 
152
  }
153
 
154
  // Ensure instructions panel is visible by default
155
  menuContent.style.display = 'block';
156
+
157
  viewerContainerElem.style.display = 'block';
158
 
159
+ // Variable to hold the drag-hide listener reference
160
+ let dragHide = null;
161
+
162
+ // Utility: hide tooltip and remove drag-hide listener
163
+ function hideTooltipPanel() {
164
+ if (dragHide) {
165
+ viewerContainerElem.removeEventListener('pointermove', dragHide);
166
+ dragHide = null;
167
+ }
168
+ tooltipPanel.style.display = 'none';
169
+ }
170
+
171
+ // Utility: hide instructions panel
172
+ function hideHelpPanel() {
173
+ menuContent.style.display = 'none';
174
+ }
175
 
176
  // ─── 7. Dynamically load viewer.js ─────────────────────────────────────────
177
  let viewerModule;
 
183
  return;
184
  }
185
 
186
+ // After viewer is ready, grab the canvas element
187
+ const canvasId = 'canvas-' + instanceId;
188
+ const canvasEl = document.getElementById(canvasId);
189
+
190
+ // ─── 8. Conditional display of tooltips-toggle button ─────────────────────────
191
+ if (!config.tooltips_url) {
192
+ tooltipsToggleBtn.style.display = 'none';
193
+ } else {
194
+ fetch(config.tooltips_url)
195
+ .then(resp => {
196
+ if (!resp.ok) {
197
+ tooltipsToggleBtn.style.display = 'none';
198
+ }
199
+ })
200
+ .catch(() => {
201
+ tooltipsToggleBtn.style.display = 'none';
202
+ });
203
+ }
204
+
205
+ // ─── 9. Fullscreen / state-preservation logic ───────────────────────────────
206
+ let isFullscreen = false;
207
+ let savedState = null;
208
+
209
+ function saveCurrentState() {
210
+ if (isFullscreen) return;
211
+ const computedWidget = window.getComputedStyle(widgetContainer);
212
+ const computedViewer = window.getComputedStyle(viewerContainerElem);
213
+ const originalAspect = widgetContainer.getAttribute('data-original-aspect') || aspectPercent;
214
+ const containerWidth = widgetContainer.offsetWidth;
215
+ const containerHeight = widgetContainer.clientHeight || viewerContainerElem.offsetHeight;
216
+ const calculatedRatio = (containerHeight / containerWidth * 100) + '%';
217
+
218
+ savedState = {
219
+ widget: {
220
+ position: widgetContainer.style.position,
221
+ top: widgetContainer.style.top,
222
+ left: widgetContainer.style.left,
223
+ width: widgetContainer.style.width,
224
+ height: widgetContainer.style.height,
225
+ maxWidth: widgetContainer.style.maxWidth,
226
+ maxHeight: widgetContainer.style.maxHeight,
227
+ paddingBottom: widgetContainer.style.paddingBottom || originalAspect,
228
+ margin: widgetContainer.style.margin,
229
+ aspectPercent: originalAspect,
230
+ calculatedAspect: calculatedRatio,
231
+ computedWidth: computedWidget.width,
232
+ computedHeight: computedWidget.height,
233
+ offsetWidth: containerWidth,
234
+ offsetHeight: containerHeight
235
+ },
236
+ viewer: {
237
+ borderRadius: viewerContainerElem.style.borderRadius,
238
+ border: viewerContainerElem.style.border,
239
+ computedWidth: computedViewer.width,
240
+ computedHeight: computedViewer.height
241
+ }
242
+ };
243
+ }
244
+
245
+ function restoreOriginalStyles() {
246
+ if (!savedState) return;
247
+ let aspectToUse = aspectPercent;
248
+ if (savedState.widget.offsetWidth && savedState.widget.offsetHeight) {
249
+ const actualRatio = (savedState.widget.offsetHeight / savedState.widget.offsetWidth * 100) + '%';
250
+ aspectToUse = actualRatio;
251
+ } else if (savedState.widget.calculatedAspect) {
252
+ aspectToUse = savedState.widget.calculatedAspect;
253
+ } else if (savedState.widget.aspectPercent) {
254
+ aspectToUse = savedState.widget.aspectPercent;
255
+ } else if (savedState.widget.paddingBottom) {
256
+ aspectToUse = savedState.widget.paddingBottom;
257
+ }
258
+
259
+ widgetContainer.style.position = savedState.widget.position || "";
260
+ widgetContainer.style.top = savedState.widget.top || "";
261
+ widgetContainer.style.left = savedState.widget.left || "";
262
+ widgetContainer.style.width = "100%";
263
+ widgetContainer.style.height = "0";
264
+ widgetContainer.style.maxWidth = savedState.widget.maxWidth || "";
265
+ widgetContainer.style.maxHeight = savedState.widget.maxHeight || "";
266
+ widgetContainer.style.paddingBottom= aspectToUse;
267
+ widgetContainer.style.margin = savedState.widget.margin || "";
268
+ widgetContainer.style.border = savedState.widget.border || "";
269
+ widgetContainer.style.borderRadius = savedState.widget.borderRadius|| "";
270
+ widgetContainer.style.overflow = savedState.widget.overflow || "";
271
+ widgetContainer.classList.remove('fake-fullscreen');
272
+
273
+ viewerContainerElem.style.position = "absolute";
274
+ viewerContainerElem.style.top = "0";
275
+ viewerContainerElem.style.left = "0";
276
+ viewerContainerElem.style.right = "0";
277
+ viewerContainerElem.style.bottom = "0";
278
+ viewerContainerElem.style.width = "100%";
279
+ viewerContainerElem.style.height = "100%";
280
+ viewerContainerElem.style.borderRadius= savedState.viewer.borderRadius || "";
281
+ viewerContainerElem.style.border = savedState.viewer.border || "";
282
+
283
+ if (viewerModule.app) {
284
+ const cw = viewerContainerElem.clientWidth;
285
+ const ch = viewerContainerElem.clientHeight;
286
+ viewerModule.app.resizeCanvas(cw, ch);
287
+ }
288
+
289
+ savedState = null;
290
+ }
291
+
292
+ function applyFullscreenStyles() {
293
+ widgetContainer.style.position = 'fixed';
294
+ widgetContainer.style.top = '0';
295
+ widgetContainer.style.left = '0';
296
+ widgetContainer.style.width = '100vw';
297
+ widgetContainer.style.height = '100vh';
298
+ widgetContainer.style.maxWidth = '100vw';
299
+ widgetContainer.style.maxHeight = '100vh';
300
+ widgetContainer.style.paddingBottom= '0';
301
+ widgetContainer.style.margin = '0';
302
+ widgetContainer.style.border = 'none';
303
+ widgetContainer.style.borderRadius = '0';
304
+
305
+ viewerContainerElem.style.width = '100%';
306
+ viewerContainerElem.style.height = '100%';
307
+ viewerContainerElem.style.borderRadius= '0';
308
+ viewerContainerElem.style.border = 'none';
309
+
310
+ if (viewerModule.app) {
311
+ viewerModule.app.resizeCanvas(window.innerWidth, window.innerHeight);
312
+ }
313
+
314
+ fullscreenToggle.textContent = '⇲';
315
+ isFullscreen = true;
316
+ }
317
+
318
+ function enterFullscreen() {
319
+ if (!savedState) {
320
+ saveCurrentState();
321
+ }
322
+ if (isIOS) {
323
+ applyFullscreenStyles();
324
+ widgetContainer.classList.add('fake-fullscreen');
325
+ } else {
326
+ if (widgetContainer.requestFullscreen) {
327
+ widgetContainer.requestFullscreen()
328
+ .then(() => {
329
+ applyFullscreenStyles();
330
+ })
331
+ .catch(err => {
332
+ console.error("Fullscreen request failed:", err);
333
+ applyFullscreenStyles();
334
+ widgetContainer.classList.add('fake-fullscreen');
335
+ });
336
+ } else if (widgetContainer.webkitRequestFullscreen) {
337
+ widgetContainer.webkitRequestFullscreen();
338
+ applyFullscreenStyles();
339
+ } else if (widgetContainer.mozRequestFullScreen) {
340
+ widgetContainer.mozRequestFullScreen();
341
+ applyFullscreenStyles();
342
+ } else if (widgetContainer.msRequestFullscreen) {
343
+ widgetContainer.msRequestFullscreen();
344
+ applyFullscreenStyles();
345
+ } else {
346
+ applyFullscreenStyles();
347
+ widgetContainer.classList.add('fake-fullscreen');
348
+ }
349
+ }
350
+ }
351
+
352
+ function exitFullscreen() {
353
+ if (document.fullscreenElement === widgetContainer) {
354
+ if (document.exitFullscreen) {
355
+ document.exitFullscreen().catch(err => {
356
+ console.error("Error exiting fullscreen:", err);
357
+ });
358
+ } else if (document.webkitExitFullscreen) {
359
+ document.webkitExitFullscreen();
360
+ } else if (document.mozCancelFullScreen) {
361
+ document.mozCancelFullScreen();
362
+ } else if (document.msExitFullscreen) {
363
+ document.msExitFullscreen();
364
+ }
365
+ }
366
+
367
+ widgetContainer.classList.remove('fake-fullscreen');
368
+ restoreOriginalStyles();
369
+ isFullscreen = false;
370
+ }
371
+
372
+ // ─── 10. Hook up event listeners ───────────────────────────────────────────
373
+
374
+ fullscreenToggle.addEventListener('click', () => {
375
+ hideTooltipPanel();
376
+ if (!isFullscreen) {
377
+ enterFullscreen();
378
+ } else {
379
+ exitFullscreen();
380
+ }
381
+ });
382
+
383
+ document.addEventListener('fullscreenchange', () => {
384
+ if (document.fullscreenElement === widgetContainer) {
385
+ isFullscreen = true;
386
+ applyFullscreenStyles();
387
+ } else if (isFullscreen) {
388
+ isFullscreen = false;
389
+ restoreOriginalStyles();
390
+ }
391
+ });
392
+ document.addEventListener('webkitfullscreenchange', () => {
393
+ if (document.webkitFullscreenElement === widgetContainer) {
394
+ isFullscreen = true;
395
+ applyFullscreenStyles();
396
+ } else if (isFullscreen) {
397
+ isFullscreen = false;
398
+ restoreOriginalStyles();
399
+ }
400
+ });
401
+ document.addEventListener('mozfullscreenchange', () => {
402
+ if (document.mozFullScreenElement === widgetContainer) {
403
+ isFullscreen = true;
404
+ applyFullscreenStyles();
405
+ } else if (isFullscreen) {
406
+ isFullscreen = false;
407
+ restoreOriginalStyles();
408
+ }
409
+ });
410
+ document.addEventListener('MSFullscreenChange', () => {
411
+ if (document.msFullscreenElement === widgetContainer) {
412
+ isFullscreen = true;
413
+ applyFullscreenStyles();
414
+ } else if (isFullscreen) {
415
+ isFullscreen = false;
416
+ restoreOriginalStyles();
417
+ }
418
+ });
419
+
420
+ helpToggle.addEventListener('click', (e) => {
421
+ hideTooltipPanel();
422
+ e.stopPropagation();
423
+ menuContent.style.display = (menuContent.style.display === 'block') ? 'none' : 'block';
424
+ });
425
+
426
+ helpCloseBtn.addEventListener('click', () => {
427
+ hideHelpPanel();
428
+ });
429
+
430
+ resetCameraBtn.addEventListener('click', () => {
431
+ hideTooltipPanel();
432
+ if (viewerModule.resetViewerCamera) {
433
+ viewerModule.resetViewerCamera();
434
+ }
435
+ });
436
+
437
+ // β¦Ώ toggle button
438
+ let tooltipsVisible = !!config.showTooltipsDefault;
439
+ if (tooltipsToggleBtn.style.display !== 'none') {
440
+ if (!tooltipsVisible) {
441
+ tooltipsToggleBtn.style.opacity = '0.5';
442
+ }
443
+ tooltipsToggleBtn.addEventListener('click', () => {
444
+ hideTooltipPanel();
445
+ tooltipsVisible = !tooltipsVisible;
446
+ tooltipsToggleBtn.style.opacity = tooltipsVisible ? '1' : '0.5';
447
+ document.dispatchEvent(new CustomEvent('toggle-tooltips', { detail: { visible: tooltipsVisible } }));
448
+ });
449
+ }
450
+
451
+ // Close tooltip panel on button click
452
+ tooltipCloseBtn.addEventListener('click', () => {
453
+ hideTooltipPanel();
454
+ });
455
+
456
+ // Listen for tooltip-selection events and show tooltip panel
457
+ document.addEventListener('tooltip-selected', (evt) => {
458
+ const { title, description, imgUrl } = evt.detail;
459
+ tooltipTextDiv.innerHTML = <strong>${title}</strong><br>${description};
460
+ if (imgUrl) {
461
+ tooltipImage.src = imgUrl;
462
+ tooltipImage.style.display = 'block';
463
+ } else {
464
+ tooltipImage.style.display = 'none';
465
+ }
466
+ tooltipPanel.style.display = 'flex';
467
+
468
+ // Attach drag-based hide listener
469
+ dragHide = (e) => {
470
+ if ((e.pointerType === 'mouse' && e.buttons !== 0) ||
471
+ (e.pointerType === 'touch')) {
472
+ hideTooltipPanel();
473
+ }
474
+ };
475
+ viewerContainerElem.addEventListener('pointermove', dragHide);
476
+ });
477
+
478
+ // Hide on any wheel event (zoom)
479
+ if (canvasEl) {
480
+ canvasEl.addEventListener('wheel', () => {
481
+ hideTooltipPanel();
482
+ }, { passive: true });
483
+ }
484
+
485
+ // Escape key also exits fullscreen
486
+ document.addEventListener('keydown', (e) => {
487
+ if ((e.key === 'Escape' || e.key === 'Esc') && isFullscreen) {
488
+ exitFullscreen();
489
+ }
490
+ });
491
+
492
+ // Window resize β†’ resize PlayCanvas canvas
493
+ window.addEventListener('resize', () => {
494
+ if (isFullscreen && viewerModule.app) {
495
+ viewerModule.app.resizeCanvas(window.innerWidth, window.innerHeight);
496
+ } else if (viewerModule.app) {
497
+ const cw = viewerContainerElem.clientWidth;
498
+ const ch = viewerContainerElem.clientHeight;
499
+ viewerModule.app.resizeCanvas(cw, ch);
500
+ }
501
+ });
502
+
503
+ // Save β€œinitial state” after a brief delay
504
+ setTimeout(() => {
505
+ saveCurrentState();
506
+ document.dispatchEvent(new CustomEvent('toggle-tooltips', { detail: { visible: tooltipsVisible } }));
507
+ }, 200);
508
 
509
+ })();