埋め込み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と一致するか確認します
  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;
        // data-zalgFram divでラップされたiframeは1つだけという仮定に基づいています
        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: