在IE 11中打印Iframe只打印第一页

Printing Iframe in IE 11 only prints first page

本文关键字:打印 Iframe 第一页 IE      更新时间:2023-09-26

我有以下代码来打印弹出窗口的内容:

var frame = this._urlElement;
if (frame) {
    var content = frame.contentWindow.document.getElementById("content");
    if (content) {
        MarvalSoftware.UI.Dom.setStyles(content, { 'overflow': 'visible' });
    }
    frame.contentWindow.focus();
    frame.contentWindow.print();
}

其中_urlElement是iframe,其内容doc具有overflow: auto。当我在IE11中打印到PDF时,我只看到第一页,内容没有被干净地剪掉,打印的PDF上也看不到任何滚动条。如果我尝试打印预览,即使在iframe内部,我也会看到整个页面和弹出窗口的轮廓。

我试图从Iframe打印的页面有一个主页面,其中有一个contentdiv和overflow: auto。当我像Chrome和IE那样打印时,我会在打印输出上看到一个滚动条,而打印输出只有一页,所以在我的页面样式表中,我用打印的媒体查询overflow: visible来覆盖溢出规则。然后,当我在Chrome上打印时,滚动条不见了,打印出来的是两页。在IE中,滚动条也不见了,但打印出来的内容在打印的第1页末尾被随意切断。

当我修改我的打印代码以创建一个新的IFrame,并将其插入要打印的文档中,将样式表和正文复制到新的IFrame,然后打印新的ifame时,即使在IE上,也会打印完整的文档。也就是说,新的iframe不包含在主页面的任何元素中,那么,除了overflow之外,我可以在主页中查找其他样式吗?

顺便说一句,我似乎只有在使用Windows自己的"PDF打印机"打印到PDF时才会经历这种行为。

最可能的原因:绝对定位

根据问题描述和OP的评论,我怀疑#content元素和/或其一个或多个祖先元素(可能包括bodyhtml)具有CSS属性/值position: absolute;。这往往会导致Internet Explorer在第一个页面之后切断所有内容,而其他浏览器则打印所有内容。

解决方案:最简单的解决方案是删除绝对定位,至少对于打印介质是这样。如果这不是一个选项,那么另一种选择是调整绝对定位元素的CSS height属性。在没有看到标记和CSS的情况下,我不能说哪个元素需要设置多高,但很可能是100%auto,或者两者的某种组合。


其他可能性:iframe失去焦点

如果在print()函数触发之前,iframe的焦点以某种方式丢失,则可能会导致OP中描述的那种特定于浏览器的行为。如果将print()函数作为iframe contentWindow的方法调用,则大多数浏览器都会打印iframe内容。另一方面,IE将始终打印当前聚焦的任何窗口*。

解决方案:与其让打印功能直接打印iframe,不如让它嵌入一个临时打印按钮,并通过虚拟点击触发它,就像这样:

var frame = this._urlElement;
if (frame) {
    var content = frame.contentWindow.document.getElementById("content");
    if (content) {
        MarvalSoftware.UI.Dom.setStyles(content, { 'overflow': 'visible' });
    }
    frame.contentDocument.body.insertAdjacentHTML(
      'beforeend',
      '<div id="print" onclick="window.focus();window.print();"></div>'
    );
    var printButton = frame.contentDocument.getElementById('print');
    printButton.click();
    printButton.parentNode.removeChild(printButton);
}

这实际上并没有消除设置焦点的必要,但我认为这可能值得一试,因为OP在他的评论中表示,当从iframe内触发时,打印可以工作。

替代解决方案:此解决方案通过用iframe的文档临时替换父文档来工作。它确实消除了对iframe的关注,但它是一个更极端的解决方案,我预计会在非常大和复杂的页面上遇到一些问题。

var frame = this._urlElement;
if (frame) {
    var content = frame.contentWindow.document.getElementById("content");
    if (content) {
        MarvalSoftware.UI.Dom.setStyles(content, { 'overflow': 'visible' });
    }
    var doc = document.documentElement;
    document.replaceChild(frame.contentDocument.documentElement, doc);
    window.setTimeout(function() {
        window.print();
        document.replaceChild(doc, document.documentElement);
    }, 100);
}

*从用户界面打印时,默认情况下IE始终打印顶级窗口。要打印iframe的内容,您必须选择它(例如,单击框架并点击CTRL+A),然后在打印对话框中选择"选定",或在打印预览中选择"在屏幕上选定"。

试试这个:

var content = document.getElementById('content');
try {
    content.contentWindow.document.execCommand('print', false, null);
} catch (e) {
    content.contentWindow.print();
}