File size: 5,640 Bytes
c5da84a
 
 
 
465cac7
c5da84a
 
 
d10bcd5
c5da84a
 
 
465cac7
 
 
c5da84a
 
 
465cac7
 
 
c5da84a
 
 
 
465cac7
 
 
 
 
 
 
 
 
 
c5da84a
 
 
465cac7
c5da84a
639d776
465cac7
639d776
 
c5da84a
 
465cac7
c5da84a
639d776
465cac7
d10bcd5
 
 
465cac7
 
 
 
 
 
 
 
 
 
 
d10bcd5
 
465cac7
 
 
 
 
d10bcd5
 
 
fffc65b
c5da84a
639d776
c5da84a
465cac7
d10bcd5
 
 
465cac7
fffc65b
d10bcd5
c5da84a
fffc65b
 
639d776
 
 
 
465cac7
 
 
 
 
 
 
 
 
c5da84a
 
48b3594
465cac7
 
 
 
 
c5da84a
fffc65b
1f40e45
fffc65b
d10bcd5
 
fffc65b
 
465cac7
fffc65b
090021b
fffc65b
090021b
 
639d776
465cac7
 
fffc65b
c5da84a
fffc65b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// ==============================
// interface.js
// ==============================

// Store a reference to the <script> tag that loaded this file
const currentScriptTag = document.currentScript;

(async function() {
  // ─── 1. Locate the <script> and read data-config ───────────────────────────────
  let scriptTag = currentScriptTag;
  if (!scriptTag) {
    const scripts = document.getElementsByTagName('script');
    for (let i = 0; i < scripts.length; i++) {
      if (scripts[i].src.includes('interface.js') && scripts[i].hasAttribute('data-config')) {
        scriptTag = scripts[i];
        break;
      }
    }
    if (!scriptTag && scripts.length > 0) {
      scriptTag = scripts[scripts.length - 1];
    }
  }

  const configUrl = scriptTag.getAttribute('data-config');
  let config = {};
  if (configUrl) {
    try {
      const response = await fetch(configUrl);
      config = await response.json();
    } catch (error) {
      console.error("Error loading config file:", error);
      return;
    }
  } else {
    console.error("No config file provided. Please set a data-config attribute on the <script> tag.");
    return;
  }

  // ─── 2. If config.css_url is provided, inject a <link> to that CSS ─────────────
  if (config.css_url) {
    const linkEl = document.createElement('link');
    linkEl.rel = "stylesheet";
    linkEl.href = config.css_url;
    document.head.appendChild(linkEl);
  }

  // ─── 3. Generate a unique instanceId for this widget ───────────────────────────
  const instanceId = Math.random().toString(36).substr(2, 8);

  // ─── 4. Compute the aspect ratio (padding-bottom %) ────────────────────────────
  let aspectPercent = "100%";
  if (config.aspect) {
    if (config.aspect.includes(":")) {
      const parts = config.aspect.split(":");
      const w = parseFloat(parts[0]);
      const h = parseFloat(parts[1]);
      if (!isNaN(w) && !isNaN(h) && w > 0) {
        aspectPercent = (h / w * 100) + "%";
      }
    } else {
      const aspectValue = parseFloat(config.aspect);
      if (!isNaN(aspectValue) && aspectValue > 0) {
        aspectPercent = (100 / aspectValue) + "%";
      }
    }
  } else {
    const parentContainer = scriptTag.parentNode;
    const containerWidth  = parentContainer.offsetWidth;
    const containerHeight = parentContainer.offsetHeight;
    if (containerWidth > 0 && containerHeight > 0) {
      aspectPercent = (containerHeight / containerWidth * 100) + "%";
    }
  }

  // ─── 5. Create the widget container ────────────────────────────────────────────
  const widgetContainer = document.createElement('div');
  widgetContainer.id = 'ply-widget-container-' + instanceId;
  widgetContainer.classList.add('ply-widget-container');
  widgetContainer.style.height = "0";
  widgetContainer.style.paddingBottom = aspectPercent;
  widgetContainer.setAttribute('data-original-aspect', aspectPercent);

  const tooltipsButtonHTML = config.tooltips_url
    ? `<button id="tooltips-toggle-${instanceId}" class="widget-button tooltips-toggle">β¦Ώ</button>`
    : '';

  // **Entire block below is now properly wrapped as a single template literal:**
  widgetContainer.innerHTML = `
    <div id="viewer-container-${instanceId}" class="viewer-container">
      <div id="progress-dialog-${instanceId}" class="progress-dialog">
        <progress id="progress-indicator-${instanceId}" max="100" value="0"></progress>
      </div>
      <button id="fullscreen-toggle-${instanceId}" class="widget-button fullscreen-toggle">⇱</button>
      <button id="help-toggle-${instanceId}" class="widget-button help-toggle">?</button>
      <button id="reset-camera-btn-${instanceId}" class="widget-button reset-camera-btn">
        <span class="reset-icon">⟲</span>
      </button>
      ${tooltipsButtonHTML}
      <div id="menu-content-${instanceId}" class="menu-content">
        <span id="help-close-${instanceId}" class="help-close">Γ—</span>
        <div class="help-text"></div>
      </div>
    </div>
    <div id="tooltip-panel" class="tooltip-panel" style="display: none;">
      <div class="tooltip-content">
        <span id="tooltip-close" class="tooltip-close">Γ—</span>
        <div id="tooltip-text" class="tooltip-text"></div>
        <img id="tooltip-image" class="tooltip-image" src="" alt="" style="display: none;" />
      </div>
    </div>
  `;  // <-- closing backtick and semicolon here fixes the stray '<'

  // Append to DOM
  scriptTag.parentNode.appendChild(widgetContainer);

  // ─── 6. Grab refs & hook up listeners ────────────────────────────────────────
  // (all your existing event-listener code remains unchanged here…)

  // ─── 7. Load viewer.js ──────────────────────────────────────────────────────
  try {
    const viewerModule = await import('./viewer.js');
    await viewerModule.initializeViewer(config, instanceId);
  } catch (err) {
    console.error("Failed to load viewer.js or initialize the 3D viewer:", err);
  }

  // ─── 8. Rest of interface.js… ────────────────────────────────────────────────

})();