2011-07-11 12 views
6

Me encargaron combinar varios documentos HTML en una sola página para imprimir. Mi primer intento falló miserablemente - Intenté aislar los contenidos de la página cada uno dentro de su propia etiqueta <div> y modificar las reglas de la hoja de estilo para que coincidan. Mi segundo intento, usar iframes para aislar cada documento, se ve significativamente mejor, pero las páginas se agrandan al imprimir desde el marco principal de la pila de iframes, en lugar de imprimir los documentos individualmente en sus propias ventanas.La ventana primaria impresa de las páginas iframed causa una escala extraña

He aquí un ejemplo de los documentos con los que trabajo: http://dl.dropbox.com/u/291229/print-test/index.html

Usted puede hacer una vista previa de impresión en Firefox para ver a qué me refiero. Si abre el primer cuadro en su propia pestaña/ventana e imprime la vista previa, los cuadros resaltados se ajustan bien dentro de la página. Hacer lo mismo en la ventana padre de la pila iframe muestra las celdas que fluyen fuera de los límites de la página.

Descargo de responsabilidad: No codifiqué estas páginas. Sí, sé que son horrendos. Lamentablemente, el proyecto no tiene el tiempo ni el presupuesto para volver a hacer las páginas de forma que se cumpla el objetivo de una sola página para imprimir un conjunto de documentos. Es posible que de forma temporal solicite a los usuarios que impriman cada página por separado para una escala adecuada, pero aún me gustaría entender qué podría estar causando este problema.

+0

500! ¡se ve bien! ¿puedes poner estos archivos en zip y publicar el enlace aquí? Definitivamente intentarlo! – Tarun

+0

Aquí hay un archivo comprimido de los archivos: http://dl.dropbox.com/u/291229/print-test.zip – Kevin

+0

lo siento, no lo pude arreglar. Lo mejor que recomiendo es intentar cargar contenido mediante ajax en lugar de usar iframes. – Tarun

Respuesta

9

El problema es que los navegadores usan el ancho del iframe del contenedor para determinar cómo escalar el contenido de ese marco para imprimir. Por lo tanto, los marcos necesitan tener sus anchos explícitamente determinados.

Desafortunadamente, calcular dinámicamente los anchos de impresión es bastante complicado e implica algunos hackers. Tal vez sea mejor simplemente diseñar un ancho fijo de páginas de componentes y codificar el ancho del iframe para eso.

Sin embargo, si usted realmente necesita dinámicamente el tamaño, puede ejecutar el siguiente código después de que el documento se ha cargado (probado en Chrome):

var iframes = document.getElementsByTagName("iframe"); 
for(var i = 0; i < iframes.length; ++i) { 
    var curFrame = iframes[i]; 
    var curBody = curFrame.contentDocument.body; 
    curBody.innerHTML = '<div id="iframe-print-content" style="display:inline-block; overflow:hidden; white-space: nowrap;">' 
         + curBody.innerHTML + '</div>'; 
    var printContent = curFrame.contentDocument.getElementById("iframe-print-content"); 
    var curWidth = printContent.offsetWidth + printContent.offsetLeft; 
    iframes[i].style.width=(curWidth + "px"); 
} 

Después de ejecutar este, puede imprimir normalmente o llamar window.print() o haz lo que quieras


Nota: Este método de trabajo no es en IE6 o IE7, ya que no son compatibles con inline-block. (También hay algunos otros navegadores antiguos que tampoco). Puede, por supuesto, tratar

display:-moz-inline-stack; display:inline-block; zoom:1; *display:inline; overflow:hidden; white-space: nowrap; 

lugar, lo que probablemente se hará cargo de la mayor parte de estos casos, pero no hacer promesas para los navegadores antiguos.

Buena suerte, lamento escuchar que se quedó atascado con el código en esas páginas.




Editar: La solución anterior es un poco inconstante en Firefox.

Solución para Firefox (probado & trabajando en Firefox 5):

var iframes = document.getElementsByTagName("iframe"); 
for(var i = 0; i < iframes.length; ++i) { 
    var curFrame = iframes[i]; 
    var curBody = curFrame.contentDocument.body; 
    var oldHTML = curBody.innerHTML; 
    curBody.innerHTML = '<div id="iframe-print-content" style="display:inline-block; overflow:hidden;">' +  oldHTML + '</div>'; 
    var printContent = curFrame.contentDocument.getElementById("iframe-print-content"); 
    var curWidth = printContent.offsetWidth + printContent.offsetLeft + 25; 
    var curHeight = printContent.offsetHeight + printContent.offsetTop + 25; 
    curBody.innerHTML = oldHTML; 
    iframes[i].style.width=(curWidth + "px"); 
    iframes[i].style.height=(curHeight + "px"); 
} 

Para una explicación completa de por qué este enfoque general funciona, ver mi respuesta anterior.

¿Qué es diferente de la solución anterior y por qué?

En primer lugar, las características específicas de Firefox:
Hay algunas diferencias clave. El primero es darse cuenta de que Firefox maneja display: inline-block y white-space: nowrap de manera diferente que Chromium/WebKit para elementos de ancho fijo (razón por la cual un documento parecía realmente inestable con el código anterior). Luego se da cuenta de que a Firefox le gusta dar un poco de margen dentro de sus iframes. No estoy muy familiarizado con el código de Firefox que hace esto (me paso el día pirateando Chromium), pero mi solución habitual (aparte de evitar los fotogramas) es solo dar un 25px extra en los márgenes. Una pequeña suma como esta parece ser un truco popular para solucionar este tipo de problema.

Ahora, las partes del código que son realmente mejores:
En primer lugar, esta ahora almacena el cuerpo de edad, levanta el cuerpo sobre un div para tomar medidas, a continuación, restaura el cuerpo de edad. Esto debería evitar problemas con CSS inflexible y debería garantizar un comportamiento más predecible. En segundo lugar, esto ahora hace lo mismo para la altura que para el ancho (mi anterior suposición de que los anchos de codificación difícil funcionarían no era bueno, y de todos modos esta es una solución más flexible).

¿Por qué sigue siendo malo?

Quitar el white-space: nowrap hará que el texto se ajuste en la impresión en Chromium/WebKit. Todavía se imprime bien, pero no es exactamente correcto, ya que algún texto adicional se ajustará. Para que esto sea una solución realmente viable, aún tiene que hacer el código de detección del navegador.

De nuevo, recomiendo usar este código para descubrir rápidamente los anchos y alturas apropiados, y luego probar y codificar los tamaños correctos para cada navegador. Es una solución desagradable, pero en última instancia es la única solución verdaderamente robusta en esta situación.

+0

Gracias por la respuesta. Si se da cuenta, las hojas de estilo de cada página iframed individual ya tienen anchos explícitamente definidos en sus contenedores. Algunos tienen '6.9in', algunos tienen' 940px', algunos tienen '7.55in'. Le daré a los iframes un ancho explícito, pero ¿alguna idea sobre los contenedores? – Kevin

+0

Quieres ser un poco cuidadoso; los anchos de los contenedores no son exactamente lo que desea: por ejemplo, en view.html, tiene un margen izquierdo adicional que se agrega (de ahí mi uso de 'offsetLeft'). En general, debe usar el tamaño de contenedor explícito solo cuando realmente lo necesite (view.html, por ejemplo, para que esa tabla funcione). Por el contrario, cuando no lo haces (por ejemplo, orderexp.html, que no tiene un tamaño explícito), debes dejar que 'inline-block' haga lo suyo, ya que generalmente se verá mejor para la impresión. IMO de todos modos. –

+0

Parece que su solución está bien impresa en Chrome, pero algo es poco convincente en Firefox. No he intentado IE todavía. Estos documentos son un desastre ... :( – Kevin

1

Creo que puede (otra vez) "engañar" el navegador agregando un ancho estático a uno de los iFrames en el medio ... Esto fuerza a la versión de impresión a cambiar el tamaño, volviendo a poner toda su información en la página. Modifiqué solo este iFrame y trajé el tamaño nuevamente (observe el ancho: 150%):

<iframe src="order/form.html" style="height: 1707px;width:150%"> 
+0

+1 Esto es realmente un truco muy bueno. Todavía necesita dea l con el problema de altura variable (a veces se encuentra en Firefox), pero definitivamente es un buen truco para saber. –

Cuestiones relacionadas