2008-10-16 24 views
16

Uno de los problemas más difíciles en mi experiencia de javascript ha sido el cálculo correcto (es decir, el "explorador cruzado") de iframe height. En mis aplicaciones, tengo un gran iframe generado dinámicamente y quiero que todos hagan una especie de aumento de tamaño al final del evento de carga para ajustar su altura y ancho.Calcular una altura de iframe entre exploradores

En el caso de altura computar mi mejor solución es la siguiente (con la ayuda de jQuery):

function getDocumentHeight(doc) { 
    var mdoc = doc || document; 
    if (mdoc.compatMode=='CSS1Compat') {  
     return mdoc.body.offsetHeight; 
    } 
    else { 
    if ($.browser.msie) 
     return mdoc.body.scrollHeight; 
    else 
     return Math.max($(mdoc).height(), $(mdoc.body).height()); 
    } 
} 

Busqué en Internet sin éxito. También probé la biblioteca de Yahoo que tiene algunos métodos para las dimensiones de documentos y ventanas, pero no es satisfactoria. Mi solución funciona decentemente, pero a veces calcula una altura más alta. he estudiado y un montón de propiedades en cuanto a altura del documento en Firefox/IE/Safari probado: documentElement.clientHeight, documentElement.offsetHeight, documentElement.scrollHeight, body.offsetHeight, body.scrollHeight, ... también jQuery no tiene un comportamiento coherente en diversas navegador con las llamadas $(document.body).height(), $('html', doc).height(), $(window).height()

que llamar a la función anterior no sólo a el final del evento de carga, pero también en el caso de elementos DOM insertados dinámicamente o elementos ocultos o mostrados. Este es un caso que a veces rompe el código que solo funciona en el evento de carga.

¿Alguien tiene una verdadera solución de navegador cruzado (al menos Firefox/IE/Safari)? Algunos consejos o sugerencias?

+0

Estoy trabajando en este tema ahora. ¿Encontraste una solución? – Shakakai

Respuesta

4

Aunque me gusta su solución, siempre he encontrado que las IFRAME son más problemáticas de lo que valen.

¿Por qué? 1. El problema del tamaño. 2. el iframe tiene ese atributo src de qué preocuparse. es decir, camino absoluto. 3. la complejidad extra con las páginas.

Mi solución - DIVs que se cargan dinámicamente a través de llamadas AJAX. DIVs tamaño automático. Aunque el código AJAX requiere el trabajo de JavaScript (que se puede hacer a través de marcos) son relativos a donde se encuentra el sitio. 3 es un lavado, estás intercambiando complejidad en páginas hasta JavaScript.

En lugar de < IFRAME ... > uso < div id = "mystuff"/>

hacer la llamada Ajax para llenar el div mystuff con los datos y dejar que el navegador se preocupe por ella.

+1

He considerado la posibilidad DIV pero no conozco una solución fácil para el problema de ID (de elementos DOM): al compartir el mismo espacio de nombres, DIV probablemente tenga muchos conflictos de id. Considere que tengo muchos iframes abiertos al mismo tiempo. Sin embargo, su solución vale la pena ser considerada cuidadosamente. –

+2

No puede cargar contenido AJAX desde un sitio externo; es una violación a la seguridad del navegador (scripts entre sitios). son probablemente la única solución del lado del cliente que permite la carga de contenido externo. – artur

+0

@artur ¿qué hay de AJAJ? – Knu

0

Aquí hay una solución que parece funcionar. Básicamente, scrollHeight es el valor correcto en la mayoría de los casos. Sin embargo, en IE (específicamente 6 y 7), si el contenido simplemente está contenido en nodos de texto, la altura no se calcula y solo se establece de forma predeterminada en la altura establecida en CSS o en el atributo "altura" en el iframe. Esto fue encontrado a través de prueba y error, así que tómalo por lo que vale.

function getDocumentHeight(doc) { 
    var mdoc = doc || document; 
    var docHeight = mdoc.body.scrollHeight; 

    if ($.browser.msie) { 
     // IE 6/7 don't report body height correctly. 
     // Instead, insert a temporary div containing the contents. 

     var child = $("<div>" + mdoc.body.innerHTML + "</div>", mdoc); 
     $("body", mdoc).prepend(child); 
     docHeight = child.height(); 
     child.remove(); 
    } 

    return docHeight; 
} 
0

He encontrado esta solución para trabajar en, por ejemplo, 6+, ff 3.5+, safari 4+. Estoy creando y agregando un iframe al documento. El siguiente código se ejecuta al final del evento de carga de jQuery después de alguna otra manipulación dom. El tiempo de espera es necesario para mí debido a la manipulación dom adicional que tiene lugar en el evento de carga.

// sizing - slight delay for good scrollheight 
setTimeout(function() { 
    var intContentHeight = objContentDoc.body.scrollHeight; 
    var $wrap = $("#divContentWrapper", objContentFrameDoc); 
    var intMaxHeight = getMaxLayeredContentHeight($wrap); 
    $this.height(intContentHeight > intMaxHeight ? intMaxHeight : intContentHeight); 

    // animate 
    fireLayeredContentAnimation($wrap); 
}, 100); 

que tienen algunas limitaciones de tamaño a tener en cuenta, que es lo que la llamada getMaxLayeredContentHeight está comprobando para mí. Espero que ayude.

1

Dado que en tu ejemplo al que está accediendo al documento dentro del IFRAME supongo que estás hablando conocer la altura del documento y no del propio marco. Además, eso significa que el contenido proviene de su propio sitio web y usted tiene control sobre sus contenidos.

Entonces, ¿por qué no simplemente coloca un DIV alrededor de su contenido y luego usa el cliente? ¿Altura de ese DIV?

Código se carga en su IFRAME:

... 
<body> 
    <div id="content"> 
    ... 
    </div> 
</body> 

El documento de nivel superior:

function getDocumentHeight(mdoc) { 
    return mdoc.getElementById("content").clientHeight; 
} 

Por cierto, esta parte de su función de ejemplo, no tiene sentido como "documento" no se refiere a la IFRAME: var mdoc = doc || document;

2

Esto ha sido sin una respuesta aceptada por un tiempo, así que quería aportar la solución que terminé yendo después de algunas investigaciones. Esta es cruz-navegador y multi-dominio (por ejemplo, cuando los puntos de iframe en el contenido de un dominio diferente)

Terminé usando el mensaje de html5 mecanismo de paso envuelto en una jQuery pluging que lo hace compatible con los navegadores más antiguos que utilizan varios métodos (algunos de ellos se describen en este hilo).

La solución final es muy simple.

En el host (padre) página:

// executes when a message is received from the iframe, to adjust 
// the iframe's height 
    $.receiveMessage(
     function(event){ 
      $('my_iframe').css({ 
       height: event.data 
      }); 
    }); 

// Please note this function could also verify event.origin and other security-related checks. 

En la página iframe:

$(function(){ 

    // Sends a message to the parent window to tell it the height of the 
    // iframe's body 

    var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined); 

    $.postMessage(
     $('body').outerHeight(true) + 'px', 
     '*', 
     target 
    ); 

}); 

He probado esto en Chrome 13+, Firefox 3.6+, Internet Explorer 7 , 8 y 9 en XP y W7, safari en OSX y W7. ;)

Cuestiones relacionadas