Como faço para redimensionar um iframe de outro domínio
-Editar
Role para baixo para algumas soluções .. ou leia sobre como NÃO fazer isso: D
Depois de muitas horas hackeando o código, a conclusão é que qualquer coisa dentro do iframe não está acessível, mesmo as barras de rolagem renderizadas no meu domínio. Eu tentei muitas técnicas sem sucesso.
Para economizar seu tempo, nem mesmo siga este caminho, basta usar sendMessages para comunicações entre domínios. Existem plug-ins para HTML <5 que eu uso - vá até o final para ver um bom exemplo :)
Nos últimos dias, venho tentando integrar um iframe a um site. Esta é uma solução de curto prazo, enquanto o outro lado desenvolve e API (pode levar meses ...) E porque esta é uma solução de curto prazo que queremos usar o easyXDM- Eu tenho acesso ao outro domínio, mas é difícil pedir-lhes adicionar cabeçalho p3p como está .....
3 iframes
A solução mais próxima que encontrei foram os 3 iframes - mas é mental de chrome e safari, então não posso usar isso.
aberto em cromo
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179
Meça as barras de rolagem
Encontrei outro post sobre como usar a altura de rolagem para tentar redimensionar o formulário .. em teoria funciona bem, mas não consegui aplicá-lo corretamente usando a altura de rolagem dos iframes ..
document.body.scrollHeight
Isso obviamente usa a altura dos corpos (não é possível acessar essas propriedades 100% é baseado na exibição do cliente canvaz e não na altura do documento x-domains)
Tentei usar jquery para obter a altura dos iframes
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
valores de retorno diferentes em cromo e ie - ou simplesmente não fazem sentido. O problema é que tudo dentro do quadro é negado - até mesmo a barra de rolagem ...
Estilos Computados
Mas se eu inspecionar um elemento no cromo do iframe, ele bladdy me mostra as dimensões dos documentos dentro do iframe (usando jquery x-domain para obter iframe.heigh - acesso negado) Não há nada no CSS computado
Agora, como o cromo calcula isso? (o navegador de edição refaz a renderização da página usando seu mecanismo de renderização de compilação para calcular todas essas configurações - mas não são anexados a qualquer lugar para evitar fraude entre domínios .. então ..)
HTML4
Eu li a especificação do HTML4.x e lá diz que deve haver valores somente leitura expostos por meio de document.element, mas seu acesso é negado por jquery
Frame Proxy
Eu segui o caminho de proxy do site de volta e calculando o que está OK ... até que um usuário efetue login através do iframe e o proxy obtenha uma página de login em vez do conteúdo real. Além disso, para alguns, chamar a página duas vezes não é aceitável
http://www.codeproject.com/KB/aspnet/asproxy.aspx
http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/
Renderizar novamente a página
Eu não fui tão longe, mas existem mecanismos jscript por aí que irão olhar a fonte e renderizar novamente a página com base no arquivo fonte. mas exigiria hackear esses jscripts .. e isso não é uma situação ideal para entidades comerciais ... e alguns applets Java puros invole ou renderização do lado do servidor
http://en.wikipedia.org/wiki/Server-side_JavaScript
http://htmlunit.sourceforge.net/ <-java não jscript
EDITAR ATUALIZAÇÃO DE 09-2013
Tudo isso pode ser feito com soquetes HTML5. Mas easyXDM é um ótimo substituto para páginas de reclamação não HTML5.
Solução 1 Ótima solução!
Usando easyXDM
Em seu servidor, você configura uma página na forma de
<html>
<head>
<script src="scripts/easyXDM.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
var transport = new easyXDM.Socket(/** The configuration */{
remote: "http://www.OTHERDOMAIN.com/resize_intermediate.html?url=testpages/resized_iframe_1.html",
//ID of the element to attach the inline frame to
container: "embedded",
onMessage: function (message, origin) {
var settings = message.split(",");
//Use jquery on a masterpage.
//$('iframe').height(settings[0]);
//$('iframe').width(settings[1]);
//The normal solution without jquery if not using any complex pages (default)
this.container.getElementsByTagName("iframe")[0].style.height = settings[0];
this.container.getElementsByTagName("iframe")[0].style.width = settings[1];
}
});
</script>
</head>
<body>
<div id="embedded"></div>
</body>
e no domínio do chamador, eles só precisam adicionar o html intermiedate_frame e o easyXDM.js no mesmo lugar. Como uma pasta pai - então você pode acessar diretórios relativos ou uma pasta contida apenas para você.
OPÇÃO 1
Se você não quiser adicionar scripts a todas as páginas, olhe para a opção 2!
Em seguida, eles podem simplesmente adicionar um jscript simples ao final de cada página que você deseja que o redimensionamento ocorra. Não há necessidade de incluir o easyxdm em cada uma dessas páginas.
<script type="text/javascript">
window.onload = function(){ parent.socket.postMessage( (parseInt(document.body.clientHeight)) + "," + ( document.body.clientWidth ) ); };
</script>
Eu modifiquei os parâmetros que ele envia. Se você quiser que a largura funcione corretamente, as páginas do outro domínio precisam incluir a largura da página em um estilo em que se pareça com:
<style type="text/css">
html, body {
overflow: hidden;
margin: 0px;
padding: 0px;
background-color: rgb(75,0,85);
color:white;
width:660px
}
a {
color:white;
visited:white;
}
</style>
Isso funciona muito bem para mim. Se a largura não for incluída, o quadro se comporta um pouco estranho e tenta adivinhar o que deveria ser ... e não encolherá se você precisar.
OPÇÃO 2
Modifique o quadro intermediário para pesquisar as alterações
Seu quadro intermediário deve ser parecido com isto.
<!doctype html>
<html>
<head>
<title>Frame</title>
<script type="text/javascript" src="easyXDM.js">
</script>
<script type="text/javascript">
var iframe;
var socket = new easyXDM.Socket({
//This is a fallback- not needed in many cases
swf: "easyxdm.swf",
onReady: function(){
iframe = document.createElement("iframe");
iframe.frameBorder = 0;
document.body.appendChild(iframe);
iframe.src = "THE HOST FRAME";
iframe.onchange = messageBack();
},
onMessage: function(url, origin){
iframe.src = url;
}
});
//Probe child.frame for dimensions.
function messageBack(){
socket.postMessage ( iframe.contentDocument.body.clientHeight + "," + iframe.contentDocument.body.clientWidth);
};
//Poll for changes on children every 500ms.
setInterval("messageBack()",500);
</script>
<style type="text/css">
html, body {
overflow: hidden;
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
iframe {
width: 100%;
height: 100%;
border: 0px;
}
</style>
</head>
<body>
</body>
</html>
O intervalo poderia ser mais eficiente para verificar se o tamanho mudou e enviar apenas se as dimensões forem alteradas em vez de postar mensagens a cada 500 ms. Se você implementar essa verificação, poderá alterar a votação para até 50 ms! diverta-se
Trabalhe em vários navegadores e é rápido. Ótimos recursos de depuração !!
Excellent Work to Sean Kinsey who made the script!!!
Solução 2 (funciona, mas não muito bem)
Então, basicamente, se você tiver um acordo mútuo com o outro domínio, poderá adicionar uma biblioteca para lidar com sendmessage. Se você não tem nenhum acesso ao outro domínio .. Continue procurando por mais hacks- porque não consegui encontrar ou justificar totalmente os que encontrei.
Então, o outro domínio incluirá estes na tag Head
<script src="scripts/jquery-1.5.2.min.js" type="text/javascript"></script>
<script src="scripts/jquery.postmessage.min.js" type="text/javascript"></script>
<script src="scripts/club.js" type="text/javascript"></script>
No club.js há apenas algumas chamadas personalizadas que fiz para chamadas de redimensionamento e contém ..
$(document).ready(function () {
var parent_url = decodeURIComponent( document.location.hash.replace( /^#/, '' ) ),link;
//Add source url hash to each url to authorise callback when navigating inside the frame.Without this clicking any links will break the communication and no messages will be received
$('a[href]').each(function(){
this.href = this.href + document.location.hash ;
});
//Get the dimensions and send back to calling page.
var h1 = document.body.scrollHeight;
var w1 = document.body.scrollWidth;
$.postMessage({ if_height: h1, if_width: w1 }, parent_url, parent );
});
E sua página fará todo o trabalho duro e tem um bom roteiro ...
//This is almost like request.querystring used to get the iframe data
function querySt(param, e) {
gy = e.split("&");
for (i = 0; i < gy.length; i++) {
ft = gy[i].split("=");
if (ft[0] == param) {
return ft[1];
}
}
}
$(function () {
// Keep track of the iframe dimensions.
var if_height;
var if_width;
// Pass the parent page URL into the Iframe in a meaningful way (this URL could be
// passed via query string or hard coded into the child page, it depends on your needs).
src = 'http://www.OTHERDOAMIN.co.uk/OTHERSTARTPAGE.htm' + '#' + encodeURIComponent(document.location.href),
// Append the Iframe into the DOM.
iframe = $('<iframe " src="' + src + '" width="100%" height="100%" scrolling="no" frameborder="0"><\/iframe>').appendTo('#iframe');
// Setup a callback to handle the dispatched MessageEvent event. In cases where
// window.postMessage is supported, the passed event will have .data, .origin and
// .source properties. Otherwise, this will only have the .data property.
$.receiveMessage(function (e) {
// Get the height from the passsed data.
//var h = Number(e.data.replace(/.*if_height=(\d+)(?:&|$)/, '$1'));
var h = querySt("if_height", e.data);
var w = querySt("if_width", e.data);
if (!isNaN(h) && h > 0 && h !== if_height) {
// Height has changed, update the iframe.
iframe.height(if_height = h);
}
if (!isNaN(w) && w > 0 && w !== if_width) {
// Height has changed, update the iframe.
iframe.width(if_width = w);
}
//For debugging only really- can remove the next line if you want
$('body').prepend("Recieved" + h + "hX" + w + "w .. ");
// An optional origin URL (Ignored where window.postMessage is unsupported).
//Here you must put the other domain.com name only! This is like an authentication to prevent spoofing and xss attacks!
}, 'http://www.OTHERDOMAIN.co.uk');
});
OPÇÃO 3
Agora é uma pequena biblioteca JS para gerenciar o redimensionamento de iframes entre domínios, ainda requer que o iFrame tenha um pouco de JavaScript, no entanto, isso é apenas 2,8k (765 bytes Gzipados) de JS nativo que não tem nenhuma dependência e não faz nada até que seja chamado pela página pai. Isso significa que é um bom convidado em sistemas de outras pessoas.
Este código usa mutationObserver para detectar mudanças no DOM e também procura eventos de redimensionamento, para que o iFrame permaneça dimensionado para o conteúdo. Funciona no IE8 +.
fonte
Respostas:
A questão é - não há outra maneira a não ser usar mensagens entre domínios para isso, pois você precisa obter a altura computada de um documento em um domínio para um documento em um domínio diferente.
Então, ou você faz isso usando
postMessage
(funciona em todos os navegadores modernos) ou gasta 5 minutos adaptando o exemplo de iframe de redimensionamento do easyXDM.A outra parte só precisa copiar alguns arquivos para o domínio e adicionar uma única linha de código ao documento.
fonte
Semelhante ao que Sean mencionou, você pode usar postMessage. Passei muito tempo tentando maneiras diferentes de redimensionar iframe com vários domínios, mas não tive sorte até que encontrei esta ótima postagem de David Walsh: http://davidwalsh.name/window-iframe
Esta é uma combinação do meu código e da solução de David. Minha solução é voltada especificamente para redimensionar iframes.
Na página filha, encontre a altura da página e passe-a para a página pai (que contém o iframe). Substitua element_id pelo id do seu elemento (html, body, qualquer que seja).
<script> function adjust_iframe_height(){ var actual_height = document.getElementById('element_id).scrollHeight; parent.postMessage(actual_height,"*"); //* allows this to post to any parent iframe regardless of domain } </script> <body onload="adjust_iframe_height();"> //call the function above after the content of the child loads
Na janela pai, adicione este código. Substitua iframe_id pelo seu ID iframe:
<script> // Create IE + others compatible event handler var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; var eventer = window[eventMethod]; var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message"; // Listen to message from child window eventer(messageEvent,function(e) { console.log('parent received message!: ',e.data); document.getElementById('iframe_id').height = e.data + 'px'; },false); </script>
Se você abrir o console, verá a altura sendo impressa no log do console. Isso irá ajudá-lo na depuração, por isso deixei isso lá.
Atenciosamente, Baker
fonte
Tendo procurado várias soluções diferentes para isso, acabei escrevendo uma pequena biblioteca simples para levar em conta vários casos de uso diferentes. Como eu precisava de uma solução que suportasse iframes gerados por vários usuários em uma página do portal, o navegador suportado redimensionava e poderia lidar com o carregamento de JavaScript da página host após o iframe. Também adiciono suporte para dimensionamento para largura e uma função de retorno de chamada e permito a substituição de body.margin, pois você provavelmente desejará definir como zero.
https://github.com/davidjbradshaw/iframe-resizer
O código iframe é apenas um pequeno JavaScript autocontido, de modo que é um bom convidado nas páginas de outras pessoas.
O script é então inicializado na página do host com as seguintes opções disponíveis.
iFrameResize({ log : true, // For development autoResize : true, // Trigering resize on events in iFrame contentWindowBodyMargin: 8, // Set the default browser body margin style (in px) doHeight : true, // Calculates dynamic height doWidth : false, // Calculates dynamic width enablePublicMethods : true, // Enable methods within iframe hosted page interval : 32, // interval in ms to recalculate body height, 0 to disable refreshing scrolling : false, // Enable the scrollbars in the iFrame callback : function(messageData){ // Callback fn when message is received $('p#callback').html( '<b>Frame ID:</b> ' + messageData.iframe.id + ' <b>Height:</b> ' + messageData.height + ' <b>Width:</b> ' + messageData.width + ' <b>Event type:</b> ' + messageData.type ); } });
fonte
Em vez de usar scroll = no no iframe, eu mudo para "auto". Então, eu obtenho o tamanho da janela real
$(window).height();
e use isso como o atributo de altura do iframe.
Bem, o resultado é ...
Nunca teremos a rolagem "página", apenas a rolagem "iframe". Quando você navega, não importa quem é o pergaminho, mas o importante é que há apenas 1.
Bem, existe o problema do usuário simplesmente redimensionar a janela enquanto navega. Para resolver isso, eu uso:
setInterval(getDocHeight, 1);
Você acha que essa solução vai causar algum bug? Está funcionando para mim, e no iframe eu tinha um contect dinâmico gerado pelo php. Tenho medo de futuros bugs com isso ...
fonte
Hoje em dia existem apenas 4 soluções que conheço:
Somente o terceiro pode resolver muitos problemas. Por exemplo, você pode criar um iFrame responsivo ; feche-o por dentro ou você pode se comunicar com ele . Mas para fazer isso, você precisa do iframe no Iframe e da solução alternativa "cookies de terceiros" (opcional).
Criei um artigo sobre isso com um exemplo: iFrame de domínio cruzado baseado em eventos
fonte
Você já olhou para os atributos HTML5 de 'ajuste ao objeto'? Dimensiona vídeo / imagens para o iframe, em vez de dimensionar o iframe (ótimo se você pegar uma imagem de tamanho médio que acaba tendo 5.000px de largura). A opção "ajustar" (outras são "cobrir" e "preencher") usa uma abordagem de caixa de correio para ajustar a fonte, preservando as proporções. Para visualização sem HTML5, parece que há um monte de polyfills disponíveis. Este é ótimo, mas um bug no final do Edge o manteve incompatível com o New Nightmare da Microsoft por cerca de um ano, agora: https://github.com/anselmh/object-fit
EDIT: Para contornar problemas de domínio cruzado, você sempre pode simplesmente fazer o trabalho em um script de conteúdo de extensão do Chrome, pois ele pensa que é parte da página em que você está colocando seu iframe.
fonte
HTTPS outro link obtém altura para iframe autoheight
Conteúdo https://-a.com :
<!DOCTYPE html> <html> <head> <title>Test Page</title> </head> <body> Test Page: <hr/> <iframe id="iframe" src="https://-b.com" style="width:100%;min-height:600px;border:none;" scrolling="no" ></iframe> <script> // browser compatibility: get method for event // addEventListener(FF, Webkit, Opera, IE9+) and attachEvent(IE5-8) var myEventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; // create event listener var myEventListener = window[myEventMethod]; // browser compatibility: attach event uses onmessage var myEventMessage = myEventMethod == "attachEvent" ? "onmessage" : "message"; // register callback function on incoming message myEventListener(myEventMessage, function (e) { // we will get a string (better browser support) and validate // if it is an int - set the height of the iframe #my-iframe-id if (e.data === parseInt(e.data)) document.getElementById('iframe').height = e.data + "px"; }, false); </script> </body> </html>
https://-b.com conteúdo iframe:
<!DOCTYPE html> <html> <head> <title>Test Iframe Content</title> <script type="text/javascript"> // all content including images has been loaded window.onload = function() { // post our message to the parent window.parent.postMessage( // get height of the content document.body.scrollHeight // set target domain ,"*" ) }; </script> </head> <body> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>1 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>2 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>3 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>4 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>5 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>6 </body> </html>
Mesa de trabalho:
xcom http> ycom https WORK
xcom https> ycom https WORK
xcom http> ycom http WORK
xcom https> ycom http WORK
fonte
Você está procurando encontrar a altura da página contida no iframe? Eu tenho um javascript funcionando que verifica a altura do conteúdo do iframe e, em seguida, define a altura do iframe para a altura do conteúdo.
var Height = document.getElementById('iFrameId').contentWindow.document.body.scrollHeight; document.getElementById('iFrameId').height = Height;
No entanto, isso só funciona se a página que você está mostrando no iframe estiver no mesmo domínio. Caso contrário, você não poderá acessar as informações necessárias. Conseqüentemente, o erro de acesso negado.
fonte
Para redimensionar um iframe, aqui está um script simples:
isso vai na cabeça: (isso foi escrito para um script php, para html, altere o 'para "e o \" para' ...
<script type='text/javascript'> <!-- function resizeIframe(id){ /* this.obj=obj //this.obj.width=null //this.obj.width=window.frames[\"sizeframe1\"].document.body.scrollWidth this.obj.style.height=\"\" // for Firefox and Opera setTimeout(\"this.obj.style.height=this.obj.contentWindow.document.body.scrollHeight+(notIE?heightOffset:0)\",10) // setTimeout required for Opera */ el=document.getElementById(id) el.style.height='200px' // for Firefox and Opera setTimeout('el.style.height=el.contentWindow.document.body.scrollHeight+\"px\"',1) // setTimeout required for Opera } // --> </script>"
fim da cabeça
isso vai no corpo (lembre-se, isso foi escrito para um script php, para html mude todo o 'para "e o \" para' ...)
<iframe onload='resizeIframe(this.id)' allowTransparency=\"true\" name='ccpaymentwindow' id='sizeframe1' marginwidth='1' marginheight='1' height='700' width='690' border='0' frameborder='1' scrolling='no' src='ccmslink.php?variable1=" . $variable1 . "'></iframe>
bônus: há algumas dicas acima. Como está configurado para script php, você pode fazer muito com ele ... para aprender mais, faça mais ...
a chave para isso é "sizeframe1" .... para vários "redimensionadores" na mesma página, copie o mesmo script, mas altere o id no iframe e o nome no script no cabeçalho e viola! você tem vários redimensionadores na mesma página ... funciona muito bem!
tem phun.
fonte