Tentei algumas soluções, mas não tive sucesso. Estou me perguntando se existe uma solução por aí, de preferência com um tutorial fácil de seguir.
Tentei algumas soluções, mas não tive sucesso. Estou me perguntando se existe uma solução por aí, de preferência com um tutorial fácil de seguir.
Respostas:
Você tem três alternativas:
Esta é uma biblioteca simples para manter os iFrames dimensionados de acordo com seu conteúdo. Ele usa as APIs PostMessage e MutationObserver, com fallback para o IE8-10. Ele também tem opções para a página de conteúdo solicitar que o iframe contido tenha um determinado tamanho e também pode fechar o iframe quando terminar de usá-lo.
https://github.com/davidjbradshaw/iframe-resizer
O Easy XDM usa uma coleção de truques para permitir a comunicação entre domínios diferentes em vários navegadores e há exemplos de como usá-lo para redimensionar o iframe:
http://easyxdm.net/wp/2010/03/17/resize-iframe-based-on-content/
http://kinsey.no/blog/index.php/2010/02/19/resizing-iframes-using-easyxdm/
O Easy XDM funciona usando PostMessage em navegadores modernos e uma solução baseada em Flash como alternativa para navegadores mais antigos.
Veja também este tópico sobre Stackoverflow (também há outros, esta é uma pergunta comum). Além disso, o Facebook parece usar uma abordagem semelhante .
Outra opção seria enviar a altura do iframe para o seu servidor e, em seguida, pesquisar desse servidor a partir da página da web pai com JSONP (ou usar uma longa pesquisa, se possível).
Eu tenho a solução para definir a altura do iframe dinamicamente com base em seu conteúdo. Isso funciona para o conteúdo de domínio cruzado. Existem alguns passos a seguir para o conseguir.
Suponha que você tenha adicionado iframe na página da web "abc.com/page"
<div>
<iframe id="IframeId" src="http://xyz.pqr/contactpage" style="width:100%;" onload="setIframeHeight(this)"></iframe>
</div>
Em seguida, você deve vincular o evento de "mensagem" do Windows à página da web "abc.com/page"
window.addEventListener('message', function (event) {
//Here We have to check content of the message event for safety purpose
//event data contains message sent from page added in iframe as shown in step 3
if (event.data.hasOwnProperty("FrameHeight")) {
//Set height of the Iframe
$("#IframeId").css("height", event.data.FrameHeight);
}
});
No carregamento do iframe, você deve enviar uma mensagem para o conteúdo da janela do iframe com a mensagem "FrameHeight":
function setIframeHeight(ifrm) {
var height = ifrm.contentWindow.postMessage("FrameHeight", "*");
}
window.addEventListener('message', function (event) {
// Need to check for safety as we are going to process only our messages
// So Check whether event with data(which contains any object) contains our message here its "FrameHeight"
if (event.data == "FrameHeight") {
//event.source contains parent page window object
//which we are going to use to send message back to main page here "abc.com/page"
//parentSourceWindow = event.source;
//Calculate the maximum height of the page
var body = document.body, html = document.documentElement;
var height = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
// Send height back to parent page "abc.com/page"
event.source.postMessage({ "FrameHeight": height }, "*");
}
});
O que fiz foi comparar o iframe scrollWidth até que ele mudasse de tamanho enquanto eu configurava incrementalmente a altura do IFrame. E funcionou bem para mim. Você pode ajustar o incremento para o que desejar.
<script type="text/javascript">
function AdjustIFrame(id) {
var frame = document.getElementById(id);
var maxW = frame.scrollWidth;
var minW = maxW;
var FrameH = 100; //IFrame starting height
frame.style.height = FrameH + "px"
while (minW == maxW) {
FrameH = FrameH + 100; //Increment
frame.style.height = FrameH + "px";
minW = frame.scrollWidth;
}
}
</script>
<iframe id="RefFrame" onload="AdjustIFrame('RefFrame');" class="RefFrame"
src="http://www.YourUrl.com"></iframe>
Eu tenho um script que cai no iframe com seu conteúdo. Ele também garante que iFrameResizer existe (ele o injeta como um script) e, em seguida, faz o redimensionamento.
Vou apresentar um exemplo simplificado abaixo.
// /js/embed-iframe-content.js
(function(){
// Note the id, we need to set this correctly on the script tag responsible for
// requesting this file.
var me = document.getElementById('my-iframe-content-loader-script-tag');
function loadIFrame() {
var ifrm = document.createElement('iframe');
ifrm.id = 'my-iframe-identifier';
ifrm.setAttribute('src', 'http://www.google.com');
ifrm.style.width = '100%';
ifrm.style.border = 0;
// we initially hide the iframe to avoid seeing the iframe resizing
ifrm.style.opacity = 0;
ifrm.onload = function () {
// this will resize our iframe
iFrameResize({ log: true }, '#my-iframe-identifier');
// make our iframe visible
ifrm.style.opacity = 1;
};
me.insertAdjacentElement('afterend', ifrm);
}
if (!window.iFrameResize) {
// We first need to ensure we inject the js required to resize our iframe.
var resizerScriptTag = document.createElement('script');
resizerScriptTag.type = 'text/javascript';
// IMPORTANT: insert the script tag before attaching the onload and setting the src.
me.insertAdjacentElement('afterend', ifrm);
// IMPORTANT: attach the onload before setting the src.
resizerScriptTag.onload = loadIFrame;
// This a CDN resource to get the iFrameResizer code.
// NOTE: You must have the below "coupled" script hosted by the content that
// is loaded within the iframe:
// https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.contentWindow.min.js
resizerScriptTag.src = 'https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.min.js';
} else {
// Cool, the iFrameResizer exists so we can just load our iframe.
loadIFrame();
}
}())
Então, o conteúdo do iframe pode ser injetado em qualquer lugar dentro de outra página / site usando o script como:
<script
id="my-iframe-content-loader-script-tag"
type="text/javascript"
src="/js/embed-iframe-content.js"
></script>
O conteúdo do iframe será injetado abaixo de onde quer que você coloque a tag do script.
Espero que isto seja útil para alguém. 👍
<script ... data-src="http://google.com">
e preenchi o iframe src com ele.
iframe-resizer@4.2.10
Aqui está minha solução simples nesta página. http://lab.ohshiftlabs.com/iframesize/
É assim que funciona;
Basicamente, se você pode editar a página em outro domínio, você pode colocar outra página iframe que pertence ao seu servidor que economiza altura para cookies. Com um intervalo de leitura de cookies quando ele é atualizado, atualize a altura do iframe. Isso é tudo.
Baixar; http://lab.ohshiftlabs.com/iframesize/iframesizepost.zip
Editar: dezembro de 2019
A solução acima usa basicamente outro iframe dentro de um iframe. O terceiro iframe pertence ao domínio da página superior, que você chama esta página com uma string de consulta que salva o valor do tamanho em um cookie, a página externa verifica essa consulta com algum intervalo. Mas não é uma boa solução, então você deve seguir esta:
Na página inicial:
window.addEventListener("message", (m)=>{iframeResizingFunction(m)});
Aqui você pode verificar m.origin
de onde vem.
Página na moldura:
window.parent.postMessage({ width: 640, height:480 }, "*")
Embora, por favor, não se esqueça de que essa não é uma maneira tão segura. Para torná-lo seguro, atualize o valor * (targetOrigin) com o valor desejado. Siga a documentação: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Eu encontrei outra solução do lado do servidor para desenvolvimento web usando PHP para obter o tamanho de um iframe.
Primeiro, use o script de servidor PHP para uma chamada externa via função interna: (como um file_get_contents
with, mas curl e dom).
function curl_get_file_contents($url,$proxyActivation=false) {
global $proxy;
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7");
curl_setopt($c, CURLOPT_REFERER, $url);
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
if($proxyActivation) {
curl_setopt($c, CURLOPT_PROXY, $proxy);
}
$contents = curl_exec($c);
curl_close($c);
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
@$dom->loadHTML($contents);
$form = $dom->getElementsByTagName("body")->item(0);
if ($contents) //si on a du contenu
return $dom->saveHTML();
else
return FALSE;
}
$url = "http://www.google.com"; //Exernal url test to iframe
<html>
<head>
<script type="text/javascript">
</script>
<style type="text/css">
#iframe_reserve {
width: 560px;
height: 228px
}
</style>
</head>
<body>
<div id="iframe_reserve"><?php echo curl_get_file_contents($url); ?></div>
<iframe id="myiframe" src="http://www.google.com" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" style="overflow:none; width:100%; display:none"></iframe>
<script type="text/javascript">
window.onload = function(){
document.getElementById("iframe_reserve").style.display = "block";
var divHeight = document.getElementById("iframe_reserve").clientHeight;
document.getElementById("iframe_reserve").style.display = "none";
document.getElementById("myiframe").style.display = "block";
document.getElementById("myiframe").style.height = divHeight;
alert(divHeight);
};
</script>
</body>
</html>
Você precisa exibir sob div ( iframe_reserve
) o html gerado pela chamada de função usando um simplesecho curl_get_file_contents("location url iframe","activation proxy")
Depois de fazer isso, uma função de evento de corpo onload com javascript toma a altura do iframe da página apenas com um simples controle do conteúdo div ( iframe_reserve
)
Então, eu costumava divHeight = document.getElementById("iframe_reserve").clientHeight;
obter a altura da página externa que vamos chamar depois de mascarar o contêiner div ( iframe_reserve
). Depois disso, carregamos o iframe com sua altura boa, só isso.
Encontrei esse problema enquanto trabalhava em algo no trabalho (usando o React). Basicamente, temos algum conteúdo html externo que salvamos em nossa tabela de documentos no banco de dados e, em seguida, inserimos na página em certas circunstâncias quando você está no conjunto de dados Documentos.
Portanto, dados n
inlines, dos quais até n
poderiam conter html externo, precisávamos criar um sistema para redimensionar automaticamente o iframe de cada inline assim que o conteúdo fosse totalmente carregado em cada um. Depois de girar minhas rodas um pouco, foi assim que acabei fazendo isso:
message
ouvinte de evento no índice de nosso aplicativo React que verifica se há uma chave específica que definiremos no iframe do remetente.<script>
tag que aguardará o window.onload
disparo dos iframes . Assim que disparar, usamos postMessage
para enviar uma mensagem para a janela pai com informações sobre o id do iframe, altura computada, etc.id
do iframe que passamos no MessageEvent
objetoiframe
, basta definir a altura a partir do valor que é passado do iframe postMessage
.// index
if (window.postMessage) {
window.addEventListener("message", (messageEvent) => {
if (
messageEvent.data.origin &&
messageEvent.data.origin === "company-name-iframe"
) {
const iframe = document.getElementById(messageEvent.data.id)
// this is the only way to ensure that the height of the iframe container matches its body height
iframe.style.height = `${messageEvent.data.height}px`
// by default, the iframe will not expand to fill the width of its parent
iframe.style.width = "100%"
// the iframe should take precedence over all pointer events of its immediate parent
// (you can still click around the iframe to segue, for example, but all content of the iframe
// will act like it has been directly inserted into the DOM)
iframe.style.pointerEvents = "all"
// by default, iframes have an ugly web-1.0 border
iframe.style.border = "none"
}
})
}
// in component that renders n iframes
<iframe
id={`${props.id}-iframe`}
src={(() => {
const html = [`data:text/html,${encodeURIComponent(props.thirdLineData)}`]
if (window.parent.postMessage) {
html.push(
`
<script>
window.onload = function(event) {
window.parent.postMessage(
{
height: document.body.scrollHeight,
id: "${props.id}-iframe",
origin: "company-name-iframe",
},
"${window.location.origin}"
);
};
</script>
`
)
}
return html.join("\n")
})()}
onLoad={(event) => {
// if the browser does not enforce a cross-origin policy,
// then just access the height directly instead
try {
const { target } = event
const contentDocument = (
target.contentDocument ||
// Earlier versions of IE or IE8+ where !DOCTYPE is not specified
target.contentWindow.document
)
if (contentDocument) {
target.style.height = `${contentDocument.body.scrollHeight}px`
}
} catch (error) {
const expectedError = (
`Blocked a frame with origin "${window.location.origin}" ` +
`from accessing a cross-origin frame.`
)
if (error.message !== expectedError) {
/* eslint-disable no-console */
console.err(
`An error (${error.message}) ocurred while trying to check to see ` +
"if the inner iframe is accessible or not depending " +
"on the browser cross-origin policy"
)
}
}
}}
/>