\n'
+ '
SPEAKER SCRIPT · 逐字稿
\n'
@@ -257,10 +267,11 @@
+ ' var total = ' + total + ';\n'
+ ' var idx = ' + startIdx + ';\n'
+ ' var CHANNEL_NAME = ' + JSON.stringify(CHANNEL_NAME) + ';\n'
++ ' var SRCDOC_TPL = ' + JSON.stringify(iframeSrcdocTemplate) + ';\n'
+ ' var bc; try { bc = new BroadcastChannel(CHANNEL_NAME); } catch(e) {}\n'
+ '\n'
-+ ' var curInner = document.getElementById("pv-cur-inner");\n'
-+ ' var nxtInner = document.getElementById("pv-nxt-inner");\n'
++ ' var iframeCur = document.getElementById("iframe-cur");\n'
++ ' var iframeNxt = document.getElementById("iframe-nxt");\n'
+ ' var pvNotes = document.getElementById("pv-notes");\n'
+ ' var pvCount = document.getElementById("pv-count");\n'
+ ' var pvTitle = document.getElementById("pv-title");\n'
@@ -273,63 +284,58 @@
+ ' pvTimer.textContent = String(Math.floor(s/60)).padStart(2,"0") + ":" + String(s%60).padStart(2,"0");\n'
+ ' }, 1000);\n'
+ '\n'
-+ ' /* Compute scale to fit 1920x1080 into actual container size */\n'
++ ' /* Scale iframe (1920x1080) to fit its container */\n'
+ ' function fitScale(container) {\n'
+ ' var cw = container.clientWidth, ch = container.clientHeight;\n'
+ ' if (!cw || !ch) return 0.3;\n'
+ ' return Math.min(cw / 1920, ch / 1080);\n'
+ ' }\n'
+ '\n'
-+ ' /* Render a slide inside a proper .deck wrapper at 1920x1080 */\n'
-+ ' function renderSlide(container, html) {\n'
-+ ' container.innerHTML = "
" + html + "
";\n'
-+ ' var sl = container.querySelector(".slide");\n'
-+ ' if (sl) { sl.classList.add("is-active"); }\n'
++ ' function setIframeSrcdoc(iframe, slideHTML) {\n'
++ ' var doc = SRCDOC_TPL.replace("%%SLIDE_HTML%%", slideHTML);\n'
++ ' iframe.srcdoc = doc;\n'
+ ' }\n'
+ '\n'
++ ' var endEl = null;\n'
+ ' function update(n) {\n'
+ ' n = Math.max(0, Math.min(total - 1, n));\n'
+ ' idx = n;\n'
-+ ' /* Current slide */\n'
-+ ' renderSlide(curInner, slideData[n].html);\n'
++ ' /* Current slide — render in iframe */\n'
++ ' setIframeSrcdoc(iframeCur, slideData[n].html);\n'
+ ' /* Next slide */\n'
-+ ' var existingEnd = nxtInner.parentElement.querySelector(".pv-next-end");\n'
+ ' if (n + 1 < total) {\n'
-+ ' if (existingEnd) existingEnd.remove();\n'
-+ ' nxtInner.style.display = "";\n'
-+ ' renderSlide(nxtInner, slideData[n + 1].html);\n'
++ ' iframeNxt.style.display = "";\n'
++ ' if (endEl) { endEl.remove(); endEl = null; }\n'
++ ' setIframeSrcdoc(iframeNxt, slideData[n + 1].html);\n'
+ ' } else {\n'
-+ ' nxtInner.style.display = "none";\n'
-+ ' if (!existingEnd) {\n'
-+ ' var end = document.createElement("div");\n'
-+ ' end.className = "pv-next-end";\n'
-+ ' end.textContent = "— END —";\n'
-+ ' nxtInner.parentElement.appendChild(end);\n'
++ ' iframeNxt.style.display = "none";\n'
++ ' if (!endEl) {\n'
++ ' endEl = document.createElement("div");\n'
++ ' endEl.className = "pv-next-end";\n'
++ ' endEl.textContent = "— END —";\n'
++ ' document.getElementById("pv-next").appendChild(endEl);\n'
+ ' }\n'
+ ' }\n'
+ ' /* Notes */\n'
+ ' pvNotes.innerHTML = slideData[n].notes || "
(这一页还没有逐字稿)";\n'
+ ' pvCount.textContent = (n + 1) + " / " + total;\n'
+ ' pvTitle.textContent = slideData[n].title;\n'
-+ ' /* Recompute scale */\n'
+ ' reScale();\n'
+ ' }\n'
+ '\n'
+ ' function reScale() {\n'
+ ' var cs = fitScale(document.getElementById("pv-current"));\n'
-+ ' curInner.style.transform = "scale(" + cs + ")";\n'
++ ' iframeCur.style.transform = "scale(" + cs + ")";\n'
+ ' var ns = fitScale(document.getElementById("pv-next"));\n'
-+ ' nxtInner.style.transform = "scale(" + ns + ")";\n'
++ ' iframeNxt.style.transform = "scale(" + ns + ")";\n'
+ ' }\n'
+ '\n'
-+ ' /* Sync from audience window */\n'
+ ' if (bc) {\n'
+ ' bc.onmessage = function(e) {\n'
+ ' if (e.data && e.data.type === "go") update(e.data.idx);\n'
+ ' };\n'
+ ' }\n'
+ '\n'
-+ ' /* Keyboard in presenter window */\n'
+ ' function go(n) {\n'
+ ' update(n);\n'
+ ' if (bc) bc.postMessage({ type: "go", idx: idx });\n'
@@ -346,7 +352,6 @@
+ ' });\n'
+ '\n'
+ ' window.addEventListener("resize", reScale);\n'
-+ ' /* Initial render */\n'
+ ' setTimeout(function(){ update(idx); }, 100);\n'
+ '})();\n'
+ '' + 'script>\n'