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 +.