I have the following code to print the content of a popup window:
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();
}
where _urlElement
is an iframe, and its content doc has overflow: auto
. When I print to PDF in IE11, I only see the first page, and the content is not cleanly cut off, nor are any scrollbars visible on the printed PDF. If I try Print Preview, even inside the iframe, I see the whole page with the outline of the popup window.
The page I am trying to print from the Iframe has a master page, with a content
div with overflow: auto
. When I print like that, Chrome and IE, I see a scrollbar on the print-out, and the print-out is only one page, so in my page's stylesheet, I override that overflow rule with a media query for print, to overflow: visible
. Then, when I print on Chrome, the scrollbar is gone, and the printout is two pages. In IE, the scrollbar is also gone, but the print-out is unceremoniously cut off at the end of printed page 1.
When I modify my print code to create a new IFrame, and insert it into the document to be printed, copy the stylesheets and body over to the new iframe, and print the new iframe, then even on IE, the full document is printed. That is, the new iframe is not contained in any elements of the master page, so, is there any other styling in the master page I can look for that could cause this, other than overflow
?
BTW, I seem to only experience this behaviour when I print to PDF, using Windows's own 'PDF printer'.
Most likely cause: absolute positioning
Based on the problem description and OP's comments, I suspect the #content
element and/or one or more of its ancestor elements (possibly including body
or html
) has the CSS property/value position: absolute;
. This tends to cause Internet Explorer to cut off everything after the first page, while other browsers print everything.
Solution: The easiest solution would be remove the absolute positioning, at least for print media. If that's not an option, then the alternative would be to adjust the CSS height
property of the absolutely positioned element(s). Without seeing the markup and CSS, I can't say what height needs to be set on which element(s), but chances are, it's going to be either 100%
or auto
, or some combination of the two.
Other possibility: iframe losing focus
If the iframe's focus is being lost somehow before the print()
function fires, it could cause the sort of browser-specific behavior described in the OP. Most browsers will print an iframe's content if you call the print()
function as a method of the iframe's contentWindow
. IE, on the other hand, will always print whatever window is currently in focus*.
Solution: Instead of having the print function print the iframe directly, have it embed a temporary print button and trigger it with a virtual click, like so:
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);
}
This doesn't actually eliminate the need to set the focus, but I figured it might be worth a try since the OP indicated in his comments that the printing works when triggered from within the iframe.
Alternative solution: This one works by temporarily replacing the parent document with the iframe's document. It does eliminate the need to focus on the iframe, but it's a much more extreme solution, and I'd expect to run into some issues with very large and complex pages.
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);
}
* When printing from the user interface, IE always prints the top level window by default. To print an iframe's content, you have to select it (e.g. by clicking in the frame and hitting CTRL+A) and then choose "Selected" in the print dialog, or "As selected on screen" in the print preview.
try this:
var content = document.getElementById('content');
try {
content.contentWindow.document.execCommand('print', false, null);
} catch (e) {
content.contentWindow.print();
}