Como ajustar automaticamente a altura do iframe para posts incorporados do WordPress

Estive pensando sobre isso por um tempo. Aqui está uma prova de conceito (note que ela não resolve o problema de remover as barras de rolagem dos iframes).

Adicione uma tag de script à postagem que você está incorporando:

<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' // Use um identificador exclusivo se você tiver vários iframes
        }, '*'); // Considere especificar o domínio pai para segurança
    }

    // Envia a altura inicial
    window.onload = sendHeight;

    // Opcional: Atualiza a altura em redimensionamento ou outros eventos
    window.onresize = sendHeight;
</script>

Estou usando o identificador "zalgFrame" no script.

Em seu tema do 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; // meu domínio de teste, atualize para o seu domínio ou comente
  // obtém a altura do iframe que é passada de `wp-discourse.test` e confirma que o iframeId corresponde ao iframeID que defini lá    
  if (event.data.iframeHeight && event.data.iframeId === 'zalgFrame') {
      // visite a página do Discourse com o iframe com seu console aberto
      // você deverá ver as alturas atualizadas sendo enviadas do site pai conforme você redimensiona a janela
      console.log("recebemos um evento:" + event.data.iframeHeight); 
      iframeHeight = event.data.iframeHeight;
      iframeId = event.data.iframeId;
  }
  }, false);
</script>

Em uma postagem do 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>

Portanto, é possível obter a altura real do iframe renderizado da janela pai.

Não sei como obter a altura dos dados do listener de eventos em uma chamada para api.decorateCookedElement, porém. Não tenho certeza se isso funcionaria para remover a barra de rolagem vertical de iframes longos. Se eu tentar codificar uma altura grande (1600px) no elemento iframe, ainda acabo com uma barra de rolagem.

Editar: para fins de completude:

<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;
        // com base na suposição de que haverá apenas 1 iframe envolvido na div data-zalgFram
        let iframe = e.querySelector("[data-zalgFrame] iframe");
        if (iframe) {
          iframe.style.height = `${iframeHeight}px`;
        }
        // após definir a altura real renderizada do iframe
        // remova o listener de eventos
        window.removeEventListener("message", handleMessage, false);
      }
    }
    window.addEventListener("message", handleMessage, false);
  },
  { id: "component-id", onlyStream: true }
);
</script>

Para qualquer coisa com mais de ~1000px de altura, não parece haver nenhuma maneira de evitar que uma barra de rolagem seja adicionada pelo Discourse, então não estou recomendando a abordagem.

Acho que a resposta para o OP é que é meio que possível, mas provavelmente não realiza muito. (Exceto que aprendi sobre o método window.postMessage() :slight_smile: