16

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'.

user990423
  • 1,397
  • 2
  • 12
  • 32
ProfK
  • 49,207
  • 121
  • 399
  • 775
  • Please could you provide code (HTML, CSS and JavaScript) to enable us to replicate the issue you are having? – Hidden Hobbes Nov 18 '15 at 13:23
  • 1
    @HiddenHobbes I have provided the JavaScript, but this is a massive ten year old legacy project. For me to provide the other code would take hours, and pages and pages. I am trying to replicate in a new page without legacy master pages and if necessary I will supply that. – ProfK Nov 18 '15 at 13:31
  • 3
    That would be good, without seeing the exact problem it will be difficult to provide a useful solution for your particular issue. – Hidden Hobbes Nov 18 '15 at 13:43
  • Have you tried to use a particular CSS to print? Like `@media print { css code; }` – Marcos Regis Nov 18 '15 at 14:02
  • 1
    @MarcosRegis I have, as I said in the question. I override the master page's `content: { overflow: auto; }` to `@media print { content: { overflow: visible; } }`, but that just stops the printed page on any browser having a scrollbar and not showing all. – ProfK Nov 18 '15 at 14:43
  • Sorry, I saw that you did a print css style, but whithout the `@media`. BTW, in my print css styles I always do a *Reset* in all styles before create the final css in `@media`. Can you give more details about your css? – Marcos Regis Nov 18 '15 at 14:49
  • 1
    Is the print being called from the iframe, or from the page that contains the iframe? I wonder if that might make a difference. Just a guess. – deebs Nov 18 '15 at 14:51
  • @deebs From the page containing the IFrame. This is a popup window (a real window, not a modal div) with a print button. If I put a print button and script on doc in the Iframe, the printing works fine. – ProfK Nov 18 '15 at 14:56
  • 1
    I'm pretty new to all of this still so bear with me, but could this make a difference... -ms-overflow-style: none (from https://msdn.microsoft.com/en-us/library/windows/apps/hh441298.aspx). Sounds like it's more of an issue with the Windows PDF printer than the CSS of the page – deebs Nov 18 '15 at 15:54
  • 1
    Please check this Solution http://stackoverflow.com/questions/25399936/print-pdf-from-iframe. – Ghayel Nov 18 '15 at 18:34
  • 1
    @Ghayel that post looks like it's about printing a PDF document that's embedded in an HTML page, whereas *this* post is about printing an HTML document to a PDF printer. They may sound similar, but they're actually very different. – DoctorDestructo Nov 20 '15 at 01:19
  • 1
    Two things that might cause behavior like this: 1) the `#content` element and/or its ancestors (up to and including `body` and `html`) have a `height` other than `auto` and an `overflow` other than `visible`; 2) something (an `onblur` function, maybe?) is stealing focus back from the iframe before it prints (this would only be a problem for IE-- other browsers don't need the iframe to be focused). – DoctorDestructo Nov 20 '15 at 03:29
  • 1
    A few other CSS properties that can wreak havoc on multi-page printouts are `display: inline-block;` (which behaves just like `page-break-inside: avoid;`), `position: absolute;`, and `position: fixed;`-- though I'd expect them to mess up all browsers, not just IE. – DoctorDestructo Nov 20 '15 at 04:11
  • @DoctorDestructo Ouch. I have lots of absolute positioning to survive in the popup window, I'll have a look at what I can avoid, thanks. – ProfK Nov 20 '15 at 04:56
  • 1
    If you could provide some code or a POC which can help replicate the issue or even closely replicate the issue then it would be much easier, also I think you can provide some screen shots highlighting the issue which will help to understand your issue more deeply .. – hagrawal7777 Nov 22 '15 at 22:21
  • What styles do you have? I have read in the past of one you should remove. I think I remember it. – makertech81 Nov 25 '15 at 02:14

2 Answers2

16

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.

DoctorDestructo
  • 4,166
  • 25
  • 43
  • Thank you. I will check within a few hours and see what works. I suspect an `absolute` somewhere. – ProfK Nov 25 '15 at 06:24
  • I haven't sorted this all out yet, but under dire warning I must award the bounty, and you get that for the most comprehensive and explanatory answer. I'll probably accept it a bit later after some research. – ProfK Nov 25 '15 at 14:17
  • Thanks much! I had same problem caused by position:absolute on body and html tags. Changed position to relative and the bug has gone. – Stalinko Jun 03 '16 at 15:11
0

try this:

var content = document.getElementById('content');

try {
    content.contentWindow.document.execCommand('print', false, null);
} catch (e) {
    content.contentWindow.print();
}          
Jason Evans
  • 28,906
  • 14
  • 90
  • 154
Abd
  • 513
  • 1
  • 7
  • 26