Spaces:
Running
Running
Update interface.js
Browse files- interface.js +29 -38
interface.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
| 5 |
const currentScriptTag = document.currentScript;
|
| 6 |
|
| 7 |
(async function() {
|
| 8 |
-
//
|
| 9 |
let scriptTag = currentScriptTag;
|
| 10 |
if (!scriptTag) {
|
| 11 |
const scripts = document.getElementsByTagName('script');
|
|
@@ -27,15 +27,13 @@ const currentScriptTag = document.currentScript;
|
|
| 27 |
const response = await fetch(configUrl);
|
| 28 |
config = await response.json();
|
| 29 |
} catch (error) {
|
| 30 |
-
console.error("Error loading config file:", error);
|
| 31 |
return;
|
| 32 |
}
|
| 33 |
} else {
|
| 34 |
-
console.error("No config file provided. Please set a data-config attribute on the <script> tag.");
|
| 35 |
return;
|
| 36 |
}
|
| 37 |
|
| 38 |
-
//
|
| 39 |
if (config.css_url) {
|
| 40 |
const linkEl = document.createElement('link');
|
| 41 |
linkEl.rel = "stylesheet";
|
|
@@ -43,10 +41,10 @@ const currentScriptTag = document.currentScript;
|
|
| 43 |
document.head.appendChild(linkEl);
|
| 44 |
}
|
| 45 |
|
| 46 |
-
//
|
| 47 |
const instanceId = Math.random().toString(36).substr(2, 8);
|
| 48 |
|
| 49 |
-
//
|
| 50 |
let aspectPercent = "100%";
|
| 51 |
if (config.aspect) {
|
| 52 |
if (config.aspect.includes(":")) {
|
|
@@ -71,7 +69,7 @@ const currentScriptTag = document.currentScript;
|
|
| 71 |
}
|
| 72 |
}
|
| 73 |
|
| 74 |
-
//
|
| 75 |
const widgetContainer = document.createElement('div');
|
| 76 |
widgetContainer.id = 'ply-widget-container-' + instanceId;
|
| 77 |
widgetContainer.classList.add('ply-widget-container');
|
|
@@ -81,11 +79,11 @@ const currentScriptTag = document.currentScript;
|
|
| 81 |
|
| 82 |
// Conditionally include the βtooltips-toggleβ button only if config.tooltips_url is defined
|
| 83 |
const tooltipsButtonHTML = config.tooltips_url
|
| 84 |
-
?
|
| 85 |
: '';
|
| 86 |
|
| 87 |
-
// Add the 3D-viewer HTML + tooltip + help HTML
|
| 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,12 +106,12 @@ const currentScriptTag = document.currentScript;
|
|
| 108 |
<img id="tooltip-image" class="tooltip-image" src="" alt="" style="display: none;" />
|
| 109 |
</div>
|
| 110 |
</div>
|
| 111 |
-
|
| 112 |
|
| 113 |
// Append the widget container immediately after the <script> tag
|
| 114 |
scriptTag.parentNode.appendChild(widgetContainer);
|
| 115 |
|
| 116 |
-
//
|
| 117 |
const viewerContainerElem = document.getElementById('viewer-container-' + instanceId);
|
| 118 |
const fullscreenToggle = document.getElementById('fullscreen-toggle-' + instanceId);
|
| 119 |
const helpToggle = document.getElementById('help-toggle-' + instanceId);
|
|
@@ -129,7 +127,7 @@ const currentScriptTag = document.currentScript;
|
|
| 129 |
const tooltipImage = document.getElementById('tooltip-image');
|
| 130 |
const tooltipCloseBtn = document.getElementById('tooltip-close');
|
| 131 |
|
| 132 |
-
//
|
| 133 |
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
| 134 |
const isMobile = isIOS || /Android/i.test(navigator.userAgent);
|
| 135 |
|
|
@@ -141,25 +139,22 @@ const currentScriptTag = document.currentScript;
|
|
| 141 |
// Fill help text with instructions plus the two new French lines
|
| 142 |
if (isMobile) {
|
| 143 |
helpTextDiv.innerHTML =
|
| 144 |
-
- Pour vous dΓ©placer, glissez deux doigts sur l'Γ©cran.<br>
|
| 145 |
-
- Pour orbiter, utilisez un doigt.<br>
|
| 146 |
-
- Pour zoomer, pincez avec deux doigts.<br>
|
| 147 |
-
|
| 148 |
-
- β² RΓ©initialise la camΓ©ra.<br>
|
| 149 |
-
- β± Passe en plein Γ©cran.<br>
|
| 150 |
-
;
|
| 151 |
} else {
|
| 152 |
helpTextDiv.innerHTML =
|
| 153 |
-
- orbitez avec le clic droit<br>
|
| 154 |
-
- zoomez avec la molette<br>
|
| 155 |
-
- dΓ©placez vous avec le clic gauche<br>
|
| 156 |
-
|
| 157 |
-
- β² RΓ©initialise la camΓ©ra.<br>
|
| 158 |
-
- β± Passe en plein Γ©cran.<br>
|
| 159 |
-
;
|
| 160 |
}
|
| 161 |
|
| 162 |
-
// Ensure instructions panel is visible by default
|
| 163 |
menuContent.style.display = 'block';
|
| 164 |
viewerContainerElem.style.display = 'block';
|
| 165 |
|
|
@@ -178,20 +173,19 @@ const currentScriptTag = document.currentScript;
|
|
| 178 |
menuContent.style.display = 'none';
|
| 179 |
}
|
| 180 |
|
| 181 |
-
//
|
| 182 |
let viewerModule;
|
| 183 |
try {
|
| 184 |
viewerModule = await import('https://mikafil-viewer-gs.static.hf.space/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 |
const canvasId = 'canvas-' + instanceId;
|
| 192 |
const canvasEl = document.getElementById(canvasId);
|
| 193 |
|
| 194 |
-
//
|
| 195 |
if (tooltipsToggleBtn) {
|
| 196 |
if (!config.tooltips_url) {
|
| 197 |
tooltipsToggleBtn.style.display = 'none';
|
|
@@ -202,14 +196,12 @@ const currentScriptTag = document.currentScript;
|
|
| 202 |
}
|
| 203 |
}
|
| 204 |
|
| 205 |
-
//
|
| 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 |
savedState = {
|
| 215 |
widget: {
|
|
@@ -317,7 +309,7 @@ const currentScriptTag = document.currentScript;
|
|
| 317 |
isFullscreen = false;
|
| 318 |
}
|
| 319 |
|
| 320 |
-
//
|
| 321 |
fullscreenToggle.addEventListener('click', () => {
|
| 322 |
hideTooltipPanel();
|
| 323 |
isFullscreen ? exitFullscreen() : enterFullscreen();
|
|
@@ -358,7 +350,7 @@ const currentScriptTag = document.currentScript;
|
|
| 358 |
|
| 359 |
document.addEventListener('tooltip-selected', (evt) => {
|
| 360 |
const { title, description, imgUrl } = evt.detail;
|
| 361 |
-
tooltipTextDiv.innerHTML =
|
| 362 |
if (imgUrl) {
|
| 363 |
tooltipImage.src = imgUrl;
|
| 364 |
tooltipImage.style.display = 'block';
|
|
@@ -393,10 +385,9 @@ const currentScriptTag = document.currentScript;
|
|
| 393 |
}
|
| 394 |
});
|
| 395 |
|
| 396 |
-
// Save βinitial stateβ after a brief delay
|
| 397 |
setTimeout(() => {
|
| 398 |
saveCurrentState();
|
| 399 |
document.dispatchEvent(new CustomEvent('toggle-tooltips', { detail: { visible: !!config.showTooltipsDefault } }));
|
| 400 |
}, 200);
|
| 401 |
|
| 402 |
-
})();
|
|
|
|
| 5 |
const currentScriptTag = document.currentScript;
|
| 6 |
|
| 7 |
(async function() {
|
| 8 |
+
// 1. Locate the <script> and read data-config
|
| 9 |
let scriptTag = currentScriptTag;
|
| 10 |
if (!scriptTag) {
|
| 11 |
const scripts = document.getElementsByTagName('script');
|
|
|
|
| 27 |
const response = await fetch(configUrl);
|
| 28 |
config = await response.json();
|
| 29 |
} catch (error) {
|
|
|
|
| 30 |
return;
|
| 31 |
}
|
| 32 |
} else {
|
|
|
|
| 33 |
return;
|
| 34 |
}
|
| 35 |
|
| 36 |
+
// 2. If config.css_url is provided, inject a <link> to that CSS
|
| 37 |
if (config.css_url) {
|
| 38 |
const linkEl = document.createElement('link');
|
| 39 |
linkEl.rel = "stylesheet";
|
|
|
|
| 41 |
document.head.appendChild(linkEl);
|
| 42 |
}
|
| 43 |
|
| 44 |
+
// 3. Generate a unique instanceId for this widget
|
| 45 |
const instanceId = Math.random().toString(36).substr(2, 8);
|
| 46 |
|
| 47 |
+
// 4. Compute the aspect ratio (padding-bottom %)
|
| 48 |
let aspectPercent = "100%";
|
| 49 |
if (config.aspect) {
|
| 50 |
if (config.aspect.includes(":")) {
|
|
|
|
| 69 |
}
|
| 70 |
}
|
| 71 |
|
| 72 |
+
// 5. Create the widget container (no GIF preview, no close button)
|
| 73 |
const widgetContainer = document.createElement('div');
|
| 74 |
widgetContainer.id = 'ply-widget-container-' + instanceId;
|
| 75 |
widgetContainer.classList.add('ply-widget-container');
|
|
|
|
| 79 |
|
| 80 |
// Conditionally include the βtooltips-toggleβ button only if config.tooltips_url is defined
|
| 81 |
const tooltipsButtonHTML = config.tooltips_url
|
| 82 |
+
? `<button id="tooltips-toggle-${instanceId}" class="widget-button tooltips-toggle">β¦Ώ</button>`
|
| 83 |
: '';
|
| 84 |
|
| 85 |
+
// Add the 3D-viewer HTML + tooltip + help HTML (WRAP IN BACKTICKS!)
|
| 86 |
+
widgetContainer.innerHTML = `
|
| 87 |
<div id="viewer-container-${instanceId}" class="viewer-container">
|
| 88 |
<div id="progress-dialog-${instanceId}" class="progress-dialog">
|
| 89 |
<progress id="progress-indicator-${instanceId}" max="100" value="0"></progress>
|
|
|
|
| 106 |
<img id="tooltip-image" class="tooltip-image" src="" alt="" style="display: none;" />
|
| 107 |
</div>
|
| 108 |
</div>
|
| 109 |
+
`;
|
| 110 |
|
| 111 |
// Append the widget container immediately after the <script> tag
|
| 112 |
scriptTag.parentNode.appendChild(widgetContainer);
|
| 113 |
|
| 114 |
+
// 6. Grab references to new DOM elements
|
| 115 |
const viewerContainerElem = document.getElementById('viewer-container-' + instanceId);
|
| 116 |
const fullscreenToggle = document.getElementById('fullscreen-toggle-' + instanceId);
|
| 117 |
const helpToggle = document.getElementById('help-toggle-' + instanceId);
|
|
|
|
| 127 |
const tooltipImage = document.getElementById('tooltip-image');
|
| 128 |
const tooltipCloseBtn = document.getElementById('tooltip-close');
|
| 129 |
|
| 130 |
+
// 6a. Detect mobile vs. desktop
|
| 131 |
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
| 132 |
const isMobile = isIOS || /Android/i.test(navigator.userAgent);
|
| 133 |
|
|
|
|
| 139 |
// Fill help text with instructions plus the two new French lines
|
| 140 |
if (isMobile) {
|
| 141 |
helpTextDiv.innerHTML =
|
| 142 |
+
'- Pour vous dΓ©placer, glissez deux doigts sur l\'Γ©cran.<br>' +
|
| 143 |
+
'- Pour orbiter, utilisez un doigt.<br>' +
|
| 144 |
+
'- Pour zoomer, pincez avec deux doigts.<br>' +
|
| 145 |
+
tooltipInstruction +
|
| 146 |
+
'- β² RΓ©initialise la camΓ©ra.<br>' +
|
| 147 |
+
'- β± Passe en plein Γ©cran.<br>';
|
|
|
|
| 148 |
} else {
|
| 149 |
helpTextDiv.innerHTML =
|
| 150 |
+
'- orbitez avec le clic droit<br>' +
|
| 151 |
+
'- zoomez avec la molette<br>' +
|
| 152 |
+
'- dΓ©placez vous avec le clic gauche<br>' +
|
| 153 |
+
tooltipInstruction +
|
| 154 |
+
'- β² RΓ©initialise la camΓ©ra.<br>' +
|
| 155 |
+
'- β± Passe en plein Γ©cran.<br>';
|
|
|
|
| 156 |
}
|
| 157 |
|
|
|
|
| 158 |
menuContent.style.display = 'block';
|
| 159 |
viewerContainerElem.style.display = 'block';
|
| 160 |
|
|
|
|
| 173 |
menuContent.style.display = 'none';
|
| 174 |
}
|
| 175 |
|
| 176 |
+
// 7. Dynamically load viewer.js
|
| 177 |
let viewerModule;
|
| 178 |
try {
|
| 179 |
viewerModule = await import('https://mikafil-viewer-gs.static.hf.space/viewer.js');
|
| 180 |
await viewerModule.initializeViewer(config, instanceId);
|
| 181 |
} catch (err) {
|
|
|
|
| 182 |
return;
|
| 183 |
}
|
| 184 |
|
| 185 |
const canvasId = 'canvas-' + instanceId;
|
| 186 |
const canvasEl = document.getElementById(canvasId);
|
| 187 |
|
| 188 |
+
// 8. Conditional display of tooltips-toggle button
|
| 189 |
if (tooltipsToggleBtn) {
|
| 190 |
if (!config.tooltips_url) {
|
| 191 |
tooltipsToggleBtn.style.display = 'none';
|
|
|
|
| 196 |
}
|
| 197 |
}
|
| 198 |
|
| 199 |
+
// 9. Fullscreen / state-preservation logic
|
| 200 |
let isFullscreen = false;
|
| 201 |
let savedState = null;
|
| 202 |
|
| 203 |
function saveCurrentState() {
|
| 204 |
if (isFullscreen) return;
|
|
|
|
|
|
|
| 205 |
const originalAspect = widgetContainer.getAttribute('data-original-aspect') || aspectPercent;
|
| 206 |
savedState = {
|
| 207 |
widget: {
|
|
|
|
| 309 |
isFullscreen = false;
|
| 310 |
}
|
| 311 |
|
| 312 |
+
// 10. Hook up event listeners
|
| 313 |
fullscreenToggle.addEventListener('click', () => {
|
| 314 |
hideTooltipPanel();
|
| 315 |
isFullscreen ? exitFullscreen() : enterFullscreen();
|
|
|
|
| 350 |
|
| 351 |
document.addEventListener('tooltip-selected', (evt) => {
|
| 352 |
const { title, description, imgUrl } = evt.detail;
|
| 353 |
+
tooltipTextDiv.innerHTML = `<strong>${title}</strong><br>${description}`;
|
| 354 |
if (imgUrl) {
|
| 355 |
tooltipImage.src = imgUrl;
|
| 356 |
tooltipImage.style.display = 'block';
|
|
|
|
| 385 |
}
|
| 386 |
});
|
| 387 |
|
|
|
|
| 388 |
setTimeout(() => {
|
| 389 |
saveCurrentState();
|
| 390 |
document.dispatchEvent(new CustomEvent('toggle-tooltips', { detail: { visible: !!config.showTooltipsDefault } }));
|
| 391 |
}, 200);
|
| 392 |
|
| 393 |
+
})();
|