Adaptar tamaño de un iFrame a la página contenida

Cuando uno incluye una página web dentro de otra con un marco de tipo IFrame, se suele encontrar el problema de que tiene que ponerle un tamaño al IFrame sin saber cuál tendrá realmente la página de dentro (que de hecho puede variar). Y entonces aparecen unas bonitas barras de desplazamiento para hacer scroll dentro del IFrame. Esas odiosas barras dentro de una página que de por sí ya tenía barras.

Si uno lo intenta arreglar con JavaScript, y la página contenida no viene exactamente del mismo host que la contenedora, aparecen cuestiones de seguridad: los navegadores no permiten a la página contenida (que es la que conoce su propio tamaño) actuar sobre la contenedora. Lo que se llama Cross-Origin Resource Sharing, o CORS. Así que no puede ir alegremente desde la contenida a modificar el IFrame para que tenga el tamaño adecuado.

Internet está lleno de explicaciones sobre cómo solventar esto. A pesar de ello, no todos están explicados con claridad, y me hicieron falta unas cuantas pruebas para hacerlo funcionar. (Por cierto, no deja de ser una chapuza, y los propios IFrames no me gustan nada; como decía Bartleby, “preferiría no hacerlo”, pero en fin).

Total, que aquí está mi resumen.

La página contenida tiene que avisar a su contenedor para decirle su propio tamaño. Así que en la página contenida se podría incluir un código como este:

function notificarAlturaAlContenedor() {
 window.top.postMessage(document.body.offsetHeight + 50, "*");
}

if (document.addEventListener) {
 document.addEventListener("DOMContentLoaded", notificarAlturaAlContenedor, false);
 window.addEventListener("load", notificarAlturaPadre, false);
} else {
 document.attachEvent("onreadystatechange", notificarAlturaAlContenedor);
 window.attachEvent("onload", notificarAlturaAlContenedor);
}

La función notificarAlturaAlContenedor es la que importa, y envía un mensaje a la ventana contenedora. Este envío de mensajes parece ser el único mecanismo que se admite para CORS.

Debajo hay código que se ejecuta para asignar dicha función a los eventos que indican cuándo se ha cargado la página. Es decir, hacen que cuando se ha cargado la página (la contenida) se invoque a notificarAlturaAlContenedor() (si no… no la llamaría nadie). No he estudiado a fondo este código, y no sé si es realmente imprescindible todo él; sospecho que utiliza diversas opciones para asegurarse de que funciona en diversos navegadores.

Por supuesto, si la página contenida cambia dinámicamente de tamaño por medio de su propio JavaScript o lo que sea, en ese momento puede invocar explícitamente a notificarAlturaAlContenedor() para actualizar su tamaño.

Ya tenemos una página que “avisa” a su contenedor, enviándole un mensaje con su tamaño (ese “50” es arbitrario, es un margen adicional para asegurarse de que las barras de scroll no aparezcan). Falta que el contenedor, es decir, la página principal que tiene su IFrame, reciba este aviso y actúe en consecuencia, haciendo el IFrame más grande (o más pequeño).

Y para eso se puede poner esto en la página contenedora:

window.addEventListener('message', function(event) {
   document.getElementById("idDelIFrame").height=event.data;
 }, false);

Ese código añade una función que “escucha” los mensajes que le llegan. Dicha función es una función anónima, con el código escrito ahí mismo; y lo que hace la función es buscar el IFrame contenedor (que en este ejemplo se supone que tendrá id=”idDelIFrame”) y fijarle la nueva altura, que no es más que el contenido del mensaje (data).

Esto me ha funcionado. A partir de ahí, se puede estudiar con más calma qué es todo eso que sale ahí, pero creo que la base de lo que se está haciendo queda mínimamente comprensible. Como digo, hay mil ejemplos por ahí, seguramente mejores; pero al haber mil… yo al menos no los he entendido todos. Así que me lo apunto.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s


A %d blogueros les gusta esto: