如何自动调整嵌入式 WordPress 帖子的 iframe 高度

我对此已经好奇了很久。这是一个概念验证(请注意,它并没有解决从 iframe 中删除滚动条的问题)。

在您嵌入的帖子中添加一个脚本标签:

<script>
    function sendHeight() {
        const body = document.body,
            html = document.documentElement;

        const height = Math.max(body.scrollHeight, body.offsetHeight,
            html.clientHeight, html.scrollHeight, html.offsetHeight);

        window.parent.postMessage({
            'iframeHeight': height,
            'iframeId': 'zalgFrame' // 如果有多个 iframe,请使用唯一标识符
        }, '*'); // 考虑为安全起见指定父域
    }

    // 发送初始高度
    window.onload = sendHeight;

    // 可选:在调整大小或其他事件时更新高度
    window.onresize = sendHeight;
</script>

我在脚本中使用了标识符 "zalgFrame"

在您的 Discourse 主题中:

<script type="text/discourse-plugin" version="1.29.0">
let iframeHeight, iframeId;
window.addEventListener('message', (event) => {
  if (event.origin !== "http://wp-discourse.test") return; // 我的测试域,请更新为您的域或注释掉
  // 获取从 wp-discourse.test 传递过来的 iframe 高度,并确认 iframeId 与我设置的 iframeId 匹配
  if (event.data.iframeHeight && event.data.iframeId === 'zalgFrame') {
      // 打开控制台,访问带有 iframe 的 Discourse 页面
      // 您应该能看到随着您调整窗口大小,父站点正在发送更新的高度
      console.log("we got an event:" + event.data.iframeHeight);
      iframeHeight = event.data.iframeHeight;
      iframeId = event.data.iframeId;
  }
  }, false);
</script>

在 Discourse 帖子中:

<div data-iframe-test-one>
<iframe src="http://wp-discourse.test/zalg_iframe/this-is-a-test-this-is-only-a-test/" width="100%" height="1659"></iframe>
</div>

因此,可以从父窗口获取渲染后 iframe 的实际高度。

我不知道如何将事件监听器中的数据高度获取到 api.decorateCookedElement 的调用中。我不确定这是否能解决长 iframe 的垂直滚动条问题。如果我尝试硬编码一个较大的高度(1600px)到 iframe 元素中,仍然会出现滚动条。

编辑:为了完整起见:

<script type="text/discourse-plugin" version="1.29.0">
api.decorateCookedElement(
  (e) => {
    let iframeHeight, iframeId;

    function handleMessage(event) {
      if (event.origin !== "http://wp-discourse.test") return;
      if (event.data.iframeHeight && event.data.iframeId === "zalgFrame") {
        iframeHeight = event.data.iframeHeight;
        iframeId = event.data.iframeId;
        // 基于假设只有一个 iframe 包裹在 data-zalgFram div 中
        let iframe = e.querySelector("[data-zalgFrame] iframe");
        if (iframe) {
          iframe.style.height = `${iframeHeight}px`;
        }
        // 设置完 iframe 的实际渲染高度后
        // 移除事件监听器
        window.removeEventListener("message", handleMessage, false);
      }
    }
    window.addEventListener("message", handleMessage, false);
  },
  { id: "component-id", onlyStream: true }
);
</script>

对于高度超过 ~1000px 的内容,似乎无法避免 Discourse 添加滚动条,因此我不推荐这种方法。

我认为对 OP 的回答是,这在某种程度上是可能的,但可能没什么用。(除了我了解了 window.postMessage() 方法 :slight_smile: