2011-07-11 37 views
6

我的任务是将几个HTML文档组合成一个页面进行打印。我的第一次尝试惨败 - 我试图隔离每个页面内的<div>标签和修改后的样式表规则以匹配。我第二次尝试使用iframe来隔离每个文档,看起来好得多,但是在从iframe堆栈的父框架打印时将页面放大,而不是在自己的窗口中单独打印文档。iframed页面的打印父窗口导致奇数缩放

这里是我的工作文件的一个例子:http://dl.dropbox.com/u/291229/print-test/index.html

你可以在Firefox中打印预览明白我的意思。如果您在其自己的选项卡/窗口中打开第一帧并打印预览,则轮廓框完全适合页面。在iframe堆栈的父窗口中执行相同操作可以显示页面边界之外的单元格。

声明:我没有编码这些页面。是的,我知道他们是可怕的。不幸的是,该项目没有时间或预算来重写页面,从而达到打印一组文档的单个页面的目标。我可能会暂时要求用户分别打印每个页面以适当缩放,但我仍想了解可能导致此问题的原因。

+0

500!看起来不错!你能否把这些文件用zip压缩并在这里发布链接?肯定会试一试! – Tarun

+0

下面是一个文件的zip文件:http://dl.dropbox.com/u/291229/print-test.zip – Kevin

+0

抱歉无法修复它。最好的建议是尝试通过ajax而不是使用iframe加载内容。 – Tarun

回答

9

问题是浏览器使用容器iframe的宽度来确定如何缩放该框架的内容以进行打印。因此,帧需要明确确定其宽度。

不幸的是,动态计算出打印宽度非常棘手,涉及到一些骇客。你可能会更好,只需构造一个固定宽度的组件页面并对iframe宽度进行硬编码即可。

但是,如果你真的需要动态大小它们,你可以运行下面的代码文件加载之后(在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"); 
} 

运行之后,就可以正常打印或致电window.print()或者做任何你想做的事情。


:此方法将在IE6还是IE7不大的工作,因为他们不支持inline-block。 (还有一些其他的老浏览器也没有)。你可以,当然,尝试

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

相反,这可能会照顾大多数情况下,但我不作任何承诺,对旧版浏览器。

祝你好运,很抱歉听到你被这些页面上的代码卡住了。




编辑:将上述溶液是在Firefox有点靠不住。

解决方案适用于Firefox(测试&在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"); 
} 

对于为什么这个一般方法的工作原理的完整说明,请参见上面我的回答。

与上述解决方案有什么不同,为什么?

首先,Firefox的细节:
有几个关键的不同。第一个是注意到Firefox处理display: inline-blockwhite-space: nowrap与用于固定宽度元素的Chromium/WebKit不同的方式(这就是为什么一个文档看起来非常不符合前面的代码)。接下来就是注意到Firefox喜欢在iframe中留出一点余量。我对Firefox的代码并不是很熟悉(花费我的时间去研究Chromium),但是我通常的解决方案(除了避免使用框架外)只是在边距上增加了25px。像这样的一笔钱似乎是解决这类问题的一种流行手段。

现在,代码实际上是更好的部件:
首先,这表现在存储老的身体,抬起身到一个div进行测量,然后恢复旧体。这应该避免不灵活的CSS问题,并应保证更可预测的行为。其次,它现在对宽度的高度做了同样的事情(我之前的假设是硬编码的宽度不起作用,并且这是一个更灵活的解决方案)。

为什么这仍然不好?

拿走white-space: nowrap将使文本在Chromium/WebKit上打印。它仍然打印良好,但它不完全正确,因为一些额外的文本将包装。为了使这是一个真正可行的解决方案,您仍然必须执行浏览器检测代码。

此外,我建议使用此代码快速找出合适的宽度和高度,然后测试并硬编码每个浏览器的正确尺寸。这是一个丑陋的解决方案,但它最终是这种情况下唯一真正强大的解决方案。

+0

感谢您的回答。如果你会注意到,每个单独的iframed页面的样式表已经在其容器中明确定义了宽度。有的有'6.9in',有的有'940px',有的有'7.55in'。我会给iframe一个明确的宽度,但对容器有任何想法? – Kevin

+0

你想要小心一点;容器宽度并不完全符合你的要求:例如,在view.html上,你有一个额外的左边距被分解(因此我使用'offsetLeft')。 一般来说,只有当你确实需要它时,才应该使用显式的容器大小调整(例如,view.html使该表工作)。相比之下,如果你没有(例如orderexp.html,没有明确的尺寸),你应该让'inline-block'完成它的工作,因为它通常会更好地进行打印。无论如何,国际海事组织无论如何都应该使用国际海事组织。 –

+0

看起来您的解决方案在Chrome中打印效果不错,但Firefox中的某些东西有点过分。还没有试过IE。这些文件是如此混乱... :( – Kevin

1

我相信你可以(再次)通过在中间的一个iFrame上添加一个静态宽度来“欺骗”浏览器......这迫使打印版本调整大小,将所有信息重新放到页面上。 。我只修改了这个iFrame,并将尺寸调回(注意宽度:150%):

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

+1这实际上是一个很好的黑客攻击,它仍然需要dea升可变高度问题(有时在Firefox上遇到),但它绝对是一个很好的技巧知道。 –

相关问题