Pregunta

Estoy trabajando en una aplicación similar a iGoogle.El contenido de otras aplicaciones (en otros dominios) se muestra mediante iframes.

¿Cómo cambio el tamaño de los iframes para que se ajusten a la altura del contenido de los iframes?

Intenté descifrar el javascript que utiliza Google, pero está confuso y la búsqueda en la web ha sido infructuosa hasta ahora.

Actualizar: Tenga en cuenta que el contenido se carga desde otros dominios, por lo que el política del mismo origen aplica.

¿Fue útil?

Solución

Tuvimos este tipo de problema, pero ligeramente a la inversa de su situación: estábamos proporcionando contenido iframe a sitios en otros dominios, por lo que política del mismo origen También fue un problema.Después de pasar muchas horas buscando en Google, finalmente encontramos una solución (algo...) viable, que quizás puedas adaptar a tus necesidades.

Existe una forma de evitar la misma política de origen, pero requiere cambios tanto en el contenido iframe como en la página de marco, por lo que si no tiene la capacidad de solicitar cambios en ambos lados, este método no le será muy útil. Me temo que.

Hay una peculiaridad del navegador que nos permite eludir la misma política de origen: javascript puede comunicarse con páginas de su propio dominio o con páginas que tiene enmarcadas, pero nunca con páginas en las que está enmarcada, por ejemplo.si usted tiene:

 www.foo.com/home.html, which iframes
 |-> www.bar.net/framed.html, which iframes
     |-> www.foo.com/helper.html

entonces home.html puede comunicarse con framed.html (iframe) y helper.html (mismo dominio).

 Communication options for each page:
 +-------------------------+-----------+-------------+-------------+
 |                         | home.html | framed.html | helper.html |
 +-------------------------+-----------+-------------+-------------+
 | www.foo.com/home.html   |    N/A    |     YES     |     YES     |
 | www.bar.net/framed.html |    NO     |     N/A     |     YES     |
 | www.foo.com/helper.html |    YES    |     YES     |     N/A     |
 +-------------------------+-----------+-------------+-------------+

framed.html puede enviar mensajes a helper.html (iframe) pero no home.html (el niño no puede comunicarse entre dominios con los padres).

La clave aquí es que helper.html puede recibir mensajes de framed.html, y también puede comunicarse con home.html.

Básicamente, cuando framed.html carga, calcula su propia altura, indica helper.html, que transmite el mensaje a home.html, que luego puede cambiar el tamaño del iframe en el que framed.html se sienta.

La forma más sencilla que encontramos de pasar mensajes desde framed.html a helper.html fue a través de un argumento de URL.Para hacer esto, framed.html tiene un iframe con src='' especificado.cuando es onload dispara, evalúa su propia altura y establece el src del iframe en este punto en helper.html?height=N

Hay una explicación aquí. de cómo Facebook lo maneja, ¡que puede ser un poco más claro que el mío arriba!


Código

En www.foo.com/home.html, se requiere el siguiente código javascript (por cierto, esto se puede cargar desde un archivo .js en cualquier dominio):

<script>
  // Resize iframe to full height
  function resizeIframe(height)
  {
    // "+60" is a general rule of thumb to allow for differences in
    // IE & and FF height reporting, can be adjusted as required..
    document.getElementById('frame_name_here').height = parseInt(height)+60;
  }
</script>
<iframe id='frame_name_here' src='http://www.bar.net/framed.html'></iframe>

En www.bar.net/framed.html:

<body onload="iframeResizePipe()">
<iframe id="helpframe" src='' height='0' width='0' frameborder='0'></iframe>

<script type="text/javascript">
  function iframeResizePipe()
  {
     // What's the page height?
     var height = document.body.scrollHeight;

     // Going to 'pipe' the data to the parent through the helpframe..
     var pipe = document.getElementById('helpframe');

     // Cachebuster a precaution here to stop browser caching interfering
     pipe.src = 'http://www.foo.com/helper.html?height='+height+'&cacheb='+Math.random();

  }
</script>

Contenido de www.foo.com/helper.html:

<html> 
<!-- 
This page is on the same domain as the parent, so can
communicate with it to order the iframe window resizing
to fit the content 
--> 
  <body onload="parentIframeResize()"> 
    <script> 
      // Tell the parent iframe what height the iframe needs to be
      function parentIframeResize()
      {
         var height = getParam('height');
         // This works as our parent's parent is on our domain..
         parent.parent.resizeIframe(height);
      }

      // Helper function, parse param from request string
      function getParam( name )
      {
        name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
        var regexS = "[\\?&]"+name+"=([^&#]*)";
        var regex = new RegExp( regexS );
        var results = regex.exec( window.location.href );
        if( results == null )
          return "";
        else
          return results[1];
      }
    </script> 
  </body> 
</html>

Otros consejos

Si no necesita manejar el contenido de iframe de un dominio diferente, pruebe este código, resolverá el problema completamente y es simple:

<script language="JavaScript">
<!--
function autoResize(id){
    var newheight;
    var newwidth;

    if(document.getElementById){
        newheight=document.getElementById(id).contentWindow.document .body.scrollHeight;
        newwidth=document.getElementById(id).contentWindow.document .body.scrollWidth;
    }

    document.getElementById(id).height= (newheight) + "px";
    document.getElementById(id).width= (newwidth) + "px";
}
//-->
</script>

<iframe src="usagelogs/default.aspx" width="100%" height="200px" id="iframe1" marginheight="0" frameborder="0" onLoad="autoResize('iframe1');"></iframe>

https://developer.mozilla.org/en/DOM/window.postMessage

  

window.postMessage()

     

window.postMessage es un método para habilitar de forma segura la comunicación de origen cruzado. Normalmente, los scripts en diferentes páginas solo pueden acceder entre sí si y solo si las páginas que los ejecutaron se encuentran en ubicaciones con el mismo protocolo (generalmente ambos http), número de puerto (80 es el valor predeterminado para http) y host (módulo documento.dominio establecido por ambas páginas al mismo valor). window.postMessage proporciona un mecanismo controlado para sortear esta restricción de manera segura cuando se usa correctamente.

     

Summary

     

window.postMessage, cuando se llama, hace que se envíe un MessageEvent en la ventana de destino cuando se completa cualquier script pendiente que se debe ejecutar (por ejemplo, controladores de eventos restantes si se llama a window.postMessage desde un controlador de eventos, tiempos de espera pendientes previamente establecidos , etc.) MessageEvent tiene el tipo de mensaje, una propiedad de datos que se establece en el valor de cadena del primer argumento proporcionado a window.postMessage, una propiedad de origen correspondiente al origen del documento principal en la ventana que llama a window.postMessage en la ventana de tiempo. Se llamó a postMessage y una propiedad de origen que es la ventana desde la que se llama a window.postMessage. (Otras propiedades estándar de eventos están presentes con sus valores esperados).

La biblioteca iFrame-Resizer usa postMessage para mantener un iFrame ajustado a su contenido, junto con MutationObserver para detectar cambios en el contenido y no depende de jQuery.

https://github.com/davidjbradshaw/iframe-resizer

jQuery: bondad de scripting entre dominios

http://benalman.com/projects/jquery-postmessage-plugin/

Tiene una demostración de cambio de tamaño de la ventana del iframe ...

http://benalman.com/code/projects/jquery-postmessage / examples / iframe /

Este artículo muestra cómo eliminar la dependencia de jQuery ... Plus tiene mucha información útil y enlaces a otras soluciones.

http://www.onlineaspect.com/2010/01 / 15 / postmessage compatible con versiones anteriores /

Ejemplo de barebones ...

http://onlineaspect.com/uploads/postmessage/parent.html

Borrador de trabajo HTML 5 en window.postMessage

http: //www.whatwg. org / specs / web-apps / current-work / multipage / comms.html # crossDocumentMessages

John Resig en mensajería entre ventanas

http://ejohn.org/blog/cross-window-messaging/

La forma más sencilla de usar jQuery:

$("iframe")
.attr({"scrolling": "no", "src":"http://www.someotherlink.com/"})
.load(function() {
    $(this).css("height", $(this).contents().height() + "px");
});

La solución en http: // www. phinesolutions.com/use-jquery-to-adjust-the-iframe-height.html funciona muy bien (usa jQuery):

<script type=”text/javascript”>
  $(document).ready(function() {
    var theFrame = $(”#iFrameToAdjust”, parent.document.body);
    theFrame.height($(document.body).height() + 30);
  });
</script>

No sé si necesita agregar 30 a la longitud ... 1 funcionó para mí.

FYI : si ya tiene una " height " atributo en su iFrame, esto simplemente agrega style = " height: xxx " ;. Esto podría no ser lo que quieres.

puede llegar un poco tarde, ya que todas las otras respuestas son anteriores :-) pero ... aquí & # 180; es mi solución. Probado en FF real, Chrome y Safari 5.0.

css:

iframe {border:0; overflow:hidden;}

javascript:

$(document).ready(function(){
    $("iframe").load( function () {
        var c = (this.contentWindow || this.contentDocument);
        if (c.document) d = c.document;
        var ih = $(d).outerHeight();
        var iw = $(d).outerWidth();
        $(this).css({
            height: ih,
            width: iw
        });
    });
});

Espero que esto ayude a cualquiera.

Finalmente encontré otra solución para enviar datos al sitio web principal desde iframe usando window.postMessage(message, targetOrigin);. Aquí explico cómo lo hice.

Sitio A = http://foo.com Sitio B = http://bar.com

SiteB se está cargando dentro del sitioUn sitio web

El sitio web de SiteB tiene esta línea

window.parent.postMessage("Hello From IFrame", "*"); 

o

window.parent.postMessage("Hello From IFrame", "http://foo.com");

Entonces el sitio A tiene el siguiente código

// Here "addEventListener" is for standards-compliant web browsers and "attachEvent" is for IE Browsers.
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];


var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

// Listen to message from child IFrame window
eventer(messageEvent, function (e) {
   alert(e.data);
   // Do whatever you want to do with the data got from IFrame in Parent form.
}, false); 

Si desea agregar una conexión de seguridad, puede usar esto si la condición en eventer(messageEvent, function (e) {})

if (e.origin == 'http://iframe.example.com') {
    alert(e.data); 
    // Do whatever you want to do with the data got from IFrame in Parent form.
}

Para IE

Dentro de IFrame:

 window.parent.postMessage('{"key":"value"}','*');

Exterior:

 eventer(messageEvent, function (e) {
   var data = jQuery.parseJSON(e.data);
   doSomething(data.key);
 }, false);

Aquí hay una solución simple que utiliza una hoja de estilo generada dinámicamente y que sirve el mismo servidor que el contenido del iframe. Simplemente la hoja de estilo & Quot; conoce & Quot; qué hay en el iframe y conoce las dimensiones que se usarán para diseñar el iframe. Esto evita las mismas restricciones de la política de origen.

http://www.8degrees.co.nz/2010/06/09/dynamically-resize-an-iframe-depending-on-its-content/

Por lo tanto, el código iframe suministrado tendría una hoja de estilo que lo acompañaría así ...

<link href="http://your.site/path/to/css?contents_id=1234&dom_id=iframe_widget" rel="stylesheet" type="text/css" />
 <iframe id="iframe_widget" src="http://your.site/path/to/content?content_id=1234" frameborder="0" width="100%" scrolling="no"></iframe>

Esto requiere que la lógica del lado del servidor pueda calcular las dimensiones del contenido representado del iframe.

Esta respuesta solo es aplicable para sitios web que usan Bootstrap. La función de inserción receptiva de Bootstrap hace el trabajo. Se basa en el ancho (no en la altura) del contenido.

<!-- 16:9 aspect ratio -->
<div class="embed-responsive embed-responsive-16by9">
  <iframe class="embed-responsive-item" src="http://www.youtube.com/embed/WsFWhL4Y84Y"></iframe>
</div>

jsfiddle: http://jsfiddle.net/00qggsjj/2/

http://getbootstrap.com/components/#responsive-embed

Estoy implementando la solución frame-in-frame de ConroyP para reemplazar una solución basada en la configuración de document.domain, pero descubrí que es bastante difícil determinar la altura del contenido del iframe correctamente en diferentes navegadores (pruebas con FF11, Ch17 y IE9 en este momento).

ConroyP utiliza:

var height = document.body.scrollHeight;

Pero eso solo funciona en la carga de la página inicial. Mi iframe tiene contenido dinámico y necesito cambiar el tamaño del iframe en ciertos eventos.

Lo que terminé haciendo fue usar diferentes propiedades JS para los diferentes navegadores.

function getDim () {
    var body = document.body,
        html = document.documentElement;

    var bc = body.clientHeight;
    var bo = body.offsetHeight;
    var bs = body.scrollHeight;
    var hc = html.clientHeight;
    var ho = html.offsetHeight;
    var hs = html.scrollHeight;

    var h = Math.max(bc, bo, bs, hc, hs, ho);

    var bd = getBrowserData();

    // Select height property to use depending on browser
    if (bd.isGecko) {
        // FF 11
        h = hc;
    } else if (bd.isChrome) {
        // CH 17
        h = hc;
    } else if (bd.isIE) {
        // IE 9
        h = bs;
    }

    return h;
}

getBrowserData () es la función de detección del navegador " inspirado " por http://docs.sencha.com/core/ de Ext Core source / Ext.html # method-Ext-apply

Eso funcionó bien para FF e IE, pero luego hubo problemas con Chrome. Uno de ellos era un problema de tiempo, aparentemente le toma un tiempo a Chrome configurar / detectar la altura del iframe. Y luego Chrome tampoco devolvió la altura del contenido en el iframe correctamente si el iframe era más alto que el contenido. Esto no funcionaría con contenido dinámico cuando la altura se reduzca.

Para resolver esto, siempre configuro el iframe a una altura baja antes de detectar la altura del contenido y luego establezco la altura del iframe en su valor correcto.

function resize () {
    // Reset the iframes height to a low value.
    // Otherwise Chrome won't detect the content height of the iframe.
    setIframeHeight(150);

    // Delay getting the dimensions because Chrome needs
    // a few moments to get the correct height.
    setTimeout("getDimAndResize()", 100);
}

El código no está optimizado, es de mi prueba de desarrollo :)

¡Espero que alguien encuentre esto útil!

<html>
<head>
<script>
function frameSize(id){
var frameHeight;

document.getElementById(id).height=0 + "px";
if(document.getElementById){
    newheight=document.getElementById(id).contentWindow.document.body.scrollHeight;    
}

document.getElementById(id).height= (frameHeight) + "px";
}
</script>
</head>

<body>

<iframe id="frame"  src="startframe.html" frameborder="0" marginheight="0" hspace=20     width="100%" 

onload="javascript:frameSize('frame');">

<p>This will work, but you need to host it on an http server, you can do it locally.    </p>
</body>
</html>

Los gadgets de iGoogle tienen que implementar activamente el cambio de tamaño, por lo que supongo que en un modelo de dominio cruzado no se puede hacer esto sin que el contenido remoto participe de alguna manera. Si su contenido puede enviar un mensaje con el nuevo tamaño a la página del contenedor utilizando técnicas típicas de comunicación entre dominios, entonces el resto es simple.

Cuando desee alejar una página web para ajustarla al tamaño del iframe:

  1. Debe cambiar el tamaño del iframe para adaptarlo al contenido
  2. Entonces debe alejar todo el iframe con el contenido de la página web cargada

Aquí hay un ejemplo:

<div id="wrap">
   <IFRAME ID="frame" name="Main" src ="http://www.google.com" />
</div>

<style type="text/css">
    #wrap { width: 130px; height: 130px; padding: 0; overflow: hidden; }
    #frame { width: 900px; height: 600px; border: 1px solid black; }
    #frame { zoom:0.15; -moz-transform:scale(0.15);-moz-transform-origin: 0 0; }
</style>

Aquí hay un enfoque jQuery que agrega la información en json a través del atributo src del iframe. Aquí hay una demostración, redimensionar y desplazar esta ventana ... la url resultante con json se ve así ... http: // fiddle. jshell.net/zippyskippy/RJN3G/show/#{docHeight:5124,windowHeight:1019,scrollHeight:571}#

Aquí está el código fuente del violín http://jsfiddle.net/zippyskippy/RJN3G/

function updateLocation(){

    var loc = window.location.href;
    window.location.href = loc.replace(/#{.*}#/,"") 
        + "#{docHeight:"+$(document).height() 
        + ",windowHeight:"+$(window).height()
        + ",scrollHeight:"+$(window).scrollTop()
        +"}#";

};

//setInterval(updateLocation,500);

$(window).resize(updateLocation);
$(window).scroll(updateLocation);

obtener la altura del contenido del iframe y luego dárselo a este iframe

 var iframes = document.getElementsByTagName("iframe");
 for(var i = 0, len = iframes.length; i<len; i++){
      window.frames[i].onload = function(_i){
           return function(){
                     iframes[_i].style.height = window.frames[_i].document.body.scrollHeight + "px";
                     }
      }(i);
 }

Trabajar con jquery en carga (navegador cruzado):

 <iframe src="your_url" marginwidth="0"  marginheight="0" scrolling="No" frameborder="0"  hspace="0" vspace="0" id="containiframe" onload="loaderIframe();" height="100%"  width="100%"></iframe>

function loaderIframe(){
var heightIframe = $('#containiframe').contents().find('body').height();
$('#frame').css("height", heightFrame);
 }  

al cambiar el tamaño en la página receptiva:

$(window).resize(function(){
if($('#containiframe').length !== 0) {
var heightIframe = $('#containiframe').contents().find('body').height();
 $('#frame').css("height", heightFrame);
}
});

Usando jQuery:

parent.html

<body>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<style>
iframe {
    width: 100%;
    border: 1px solid black;
}
</style>
<script>
function foo(w, h) {
    $("iframe").css({width: w, height: h});
    return true;  // for debug purposes
}
</script>
<iframe src="child.html"></iframe>
</body>

child.html

<body>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
$(function() {
    var w = $("#container").css("width");
    var h = $("#container").css("height");

    var req = parent.foo(w, h);
    console.log(req); // for debug purposes
});
</script>
<style>
body, html {
    margin: 0;
}
#container {
    width: 500px;
    height: 500px;
    background-color: red;
}
</style>
<div id="container"></div>
</body>

Esto es un poco complicado, ya que debe saber cuándo se cargó la página del iframe, lo cual es difícil cuando no tiene el control de su contenido. Es posible agregar un controlador de carga al iframe, pero lo he intentado en el pasado y tiene un comportamiento muy diferente en todos los navegadores (sin adivinar quién es el más molesto ...). Probablemente tenga que agregar una función a la página de iframe que realiza el cambio de tamaño e inyectar algún script en el contenido que escucha cargar eventos o cambiar el tamaño de eventos, que luego llama a la función anterior. Estoy pensando en agregar una función a la página ya que desea asegurarse de que sea segura, pero no tengo idea de lo fácil que será hacerlo.

Algo parecido a esto creo que debería funcionar.

parent.document.getElementById(iFrameID).style.height=framedPage.scrollHeight;

Cargue esto con la carga de su cuerpo en el contenido del iframe.

Tengo una solución fácil y requiere que determine el ancho y la altura en el enlace, intente (funciona con la mayoría de los navegadores):

<a href='#' onClick=" document.getElementById('myform').src='t2.htm';document.getElementById('myform').width='500px'; document.getElementById('myform').height='400px'; return false">500x400</a>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top