我的任务是将几个HTML文档合并到一个页面中进行打印。我的第一次尝试失败了 - 我试图将每个页面内容隔离在他们自己的<div>
标签和修改后的样式表规则中以匹配。我使用iframe隔离每个文档的第二次尝试看起来明显更好,但是从iframe堆栈的父框架打印时,页面会被放大,而不是在自己的窗口中单独打印文档。
以下是我正在使用的文档示例:http://dl.dropbox.com/u/291229/print-test/index.html
您可以在Firefox中进行打印预览,看看我的意思。如果您在其自己的选项卡/窗口中打开第一帧并打印预览,则轮廓框很适合页面。在iframe堆栈的父窗口中执行相同操作会显示在页面边界外流动的单元格。
免责声明:我没有对这些网页进行编码。是的,我知道他们很可怕。遗憾的是,该项目没有时间或预算来重新编写页面,以实现打印一组文档的单页目标。我可能会暂时要求用户单独打印每个页面以进行适当的缩放,但我仍然想了解可能导致此问题的原因。
答案 0 :(得分:9)
问题是浏览器使用容器iframe的宽度来确定如何缩放该帧的内容以进行打印。因此,框架需要明确确定其宽度。
不幸的是,动态计算出打印宽度非常棘手并且涉及一些hackery。您可能最好只设置固定宽度的组件页面并将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-block
和white-space: nowrap
的方式不同于Chromium / WebKit的固定宽度元素(这就是为什么一个文档看起来真的很难用前面的代码)。接下来注意到Firefox喜欢在其iframe中提供一点保证金。我不太熟悉执行此操作的Firefox代码(花费我的时间来攻击Chromium),但我通常的解决方案(除了避免使用框架)只是在边距上额外增加25px。像这样的一点点似乎是解决这类问题的流行黑客。
现在,代码中实际上更好的部分:
首先,它现在存储旧体,将身体提升到div上进行测量,然后恢复旧体。这应避免CSS不灵活的问题,并应保证更可预测的行为。其次,这对于高度和宽度做了同样的事情(我之前的假设是硬编码的宽度才有效,但无论如何这都是一个更灵活的解决方案。)
为什么这还不错?
删除white-space: nowrap
将在Chromium / WebKit上打印文本。它仍然打印很好,但它不完全正确,因为一些额外的文本将包装。为了使其成为真正可行的解决方案,您仍然需要执行浏览器检测代码。
同样,我建议使用此代码快速找出适当的宽度和高度,然后测试并硬编码每个浏览器的正确尺寸。这是一个丑陋的解决方案,但它最终是这种情况下唯一真正强大的解决方案。
答案 1 :(得分:1)
我相信你可以(再次)通过向中间的一个iFrame添加静态宽度来“欺骗”浏览器...这会强制打印版本调整大小,将所有信息重新带回页面......我只修改了这个iFrame并重新调整了尺寸(注意宽度:150%):
<iframe src="order/form.html" style="height: 1707px;width:150%">