Iframes elásticos (aumento automático de altura)

Link Original

﷽ Às vezes, é necessário usar iframes ao construir alguns aplicativos da web. Freqüentemente, eles estão ocultos, mas às vezes os iframes também podem ser úteis visíveis.

Para o Node Knockout 2013, trabalhei com o Meteorhacks na caixa de comentários aberta . É como uma alternativa Disqus auto-hospedada. Mantivemos a visualização dos comentários dentro de um iframe para garantir que não colidisse com os estilos principais do site e por motivos de segurança. O sistema de comentários é em tempo real. Portanto, os comentários visíveis mudam com frequência e é necessário que o iframe que contém esses comentários seja redimensionado para evitar barras de rolagem.

Se estivermos na mesma origem, uma das coisas que podemos fazer é verificar continuamente se scrollHeight do corpo do documento do quadro filho muda e atualizar a altura do iframe.

(function (iframe) {

var prevHeight = null;

setInterval
(function () {
if(prevHeight!==iframe.contentDocument.body.scrollHeight){
prevHeight
= iframe.contentDocument.body.scrollHeight;
iframe
.style.height = prevHeight + 'px';
}
});

})(document.getElementById('iframe'));

Por causa das abordagens de segurança adotadas por navegadores da web modernos, isso não funcionará se você tiver o iframe e a janela pai em origens diferentes. Este é um aprimoramento de segurança, não um bug, portanto, não podemos esperar que seja corrigido no futuro.

Se as páginas pertencerem a origens diferentes, a janela pai não terá permissão para acessar informações sobre o conteúdo dentro do iframe. Ficarei assustado se puder e definitivamente evitar o uso de um navegador da web .

Como uma solução de origem cruzada, o que podemos fazer é mover a função que rastreia as alterações de altura para a página carregada dentro do iframe ( assumindo que você pode controlar as páginas de quadro pai e filho ). E use postMessage para atualizar a altura da janela principal. Para manter as coisas mais interessantes, vou usar o mozilla jschannel para organizar as mensagens postMessage.

Primeiro, inclua jschannel adicionando esta tag de script a ambas as páginas (janela pai e página dentro do iframe).

<script src="//cdnjs.cloudflare.com/ajax/libs/jschannel/1.0.0-git-commit1-8c4f7eb/jschannel.min.js"></script>

E este trecho dentro dos scripts de página de quadro filho que cria o jschannel, detecta mudanças na altura do corpo e envia mensagens para a página pai via jschannel.

(function () {

function DO_NOTHING () {}

var channel = null;
var prevHeight = null;

document
.addEventListener('DOMContentLoaded', function () {
channel
= Channel.build({
window
: window.parent
,origin: '*'
,scope: 'test_scope'
});
setInterval
(watchDocumentHeight, 250);
})

function watchDocumentHeight() {
if (prevHeight !== document.body.scrollHeight) {
channel
.call({
method
: 'resize'
,params: document.body.scrollHeight
,success: DO_NOTHING
});
prevHeight
= document.body.scrollHeight;
}
}

})();

E este dentro dos scripts da página pai para preparar o jschannel, aguardar mensagens e atualizar a altura.

(function (iframe) {

var channel = null;

document
.addEventListener('DOMContentLoaded', function () {
channel
= Channel.build({
window
: iframe.contentWindow
,origin: '*'
,scope: 'test_scope'
,onReady: onChannelReady
});
})

function onChannelReady () {
channel
.bind('resize', onResize);
}

function onResize (trans, data) {
iframe
.style.height = data + 'px';
}

})(document.getElementById('iframe'));

Isso tudo é realmente necessário? Podemos tornar o código muito mais curto se usarmos window.postMessage diretamente, mas se você estiver usando iframes, muito provavelmente precisará usar if para mais do que alterar a altura. O Mozilla jschannel pode ajudá-lo quando se trata de organizar canais postMessage.