MikaFil commited on
Commit
fffc65b
Β·
verified Β·
1 Parent(s): 68329a0

Update interface.js

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