4

I've created this code to print data from an iFrame

function (data) {
    var frame = $("<iframe>", {
        name: "iFrame",
        class: "printFrame"
    });

    frame.appendTo("body");

    var head = $("<head></head>");

    _.each($("head link[rel=stylesheet]"), function (link) {
        var csslink = $("<link/>", { rel: "stylesheet", href: $(link).prop("href") })
        head.append(csslink);
    ;});

    frame.contents().find("head")
        .replaceWith(head);

    frame.contents().find("body")
        .append(this.html());

    window.frames["iFrame"].focus();
    window.frames["iFrame"].print();
}

This creates an iFrame, adds a head to where it sets all the css links that are needed for this website. Then it creates the body.

Trouble is, the styling won't get applied to the print, unless I break at line frame.contents().find("head").replaceWith(head), which means that something in that part is running asynchronously.

Question is, can I somehow get the code to wait for a short while before running that line, or is there perhaps another way to do this? Unfortunately I'm not all that familiar with iFrames, so I have no clue what it's trying to do there.

Hofftari
  • 106
  • 8
  • https://stackoverflow.com/questions/9616426/javascript-print-iframe-contents-only – Sagar Sinha Jul 03 '17 at 12:27
  • 1
    @SagarSinha not sure what you want by linking that page. Could you perhaps explain some more or comment about what part of that thread you're trying to refer to? – Hofftari Jul 03 '17 at 12:37

3 Answers3

2

This turned out to be a real hassle. I've always been reluctant to using iframes, but since there are many resources saying that using an iframe for printing more stuff than what's on the screen, we figured we'd give it a try.

This was instead solved by putting the data inside a hidden div which then was shown before a window.print(). At the same time, all other elements on the page were given a "hidden-print" class which is a class we're already using to hide elements for prints.

This might not be as elegant for the user (The div will show briefly before the user exits the print dialogue), but it's a way more simpler code to use and manage.

Hofftari
  • 106
  • 8
1

I think you could / should move the last focus() and print() calls to a onload handler for the iframe, to get it to happen after styles are loaded and applied.

Rasmus Kaj
  • 4,224
  • 1
  • 20
  • 23
1

I've just run into the same issue and did the following:

setTimeout(() => {
  window.frames["iFrame"].focus();
  window.frames["iFrame"].print();
}, 500)

This appears to have sorted it for me. I hate using timeout and the length is guess work at best but as it's not system critical it's something I can run with for now.

webnoob
  • 15,747
  • 13
  • 83
  • 165