1

I am new To JQuery and Primefaces.

The Below Code(printer.js) is used in Primefaces for Printing the desired Target <p:printer target="targetId">

I am trying to Print the content of a Primefaces Panel which is inside a Dialog Box, it is working fine in IE8 and other browsers, but in IE9 and above it is throwing an Error as "Internet Stopped Working"

How can i Fix this issue ? Can any one Explain what Does that printer.js Do ?

printer.js

 (function(b){var a;
                    b.fn.jqprint=function(d){a=b.extend({},b.fn.jqprint.defaults,d);
                    var c=(this instanceof jQuery)?this:b(this);
                        if(a.operaSupport&&b.browser.opera){
                            var e=window.open("","jqPrint-preview");
                                e.document.open();
                                var g=e.document
                        }else{
                            var f=b("<iframe  />");
                            if(!a.debug){
                                f.css({position:"absolute",width:"0px",height:"0px",left:"-600px",top:"-600px"})
                            }
                            f.appendTo("body");
                            var g=f[0].contentWindow.document
                        }
                        if(a.importCSS){
                            if(b("link[media=print]").length>0){
                                b("link[media=print]").each(function(){g.write("<link type='text/css' rel='stylesheet' href='"+b(this).attr("href")+"' media='print' />")})
                            }else{
                                b("link").each(function(){g.write("<link type='text/css' rel='stylesheet' href='"+b(this).attr("href")+"' />")})\
                                }
                        }
                        if(a.printContainer){
                            g.write(c.outer())
                        }else{
                            c.each(function(){g.write(b(this).html())})
                        }g.close();
                        (a.operaSupport&&b.browser.opera?e:f[0].contentWindow).focus();setTimeout(function(){(a.operaSupport&&b.browser.opera?e:f[0].contentWindow).print();if(e){e.close()}},1000)
                    };
                    b.fn.jqprint.defaults={debug:false,importCSS:true,printContainer:true,operaSupport:true};
                    jQuery.fn.outer=function(){return b(b("<div></div>").html(this.clone())).html()}
                })(jQuery);
09Q71AO534
  • 4,300
  • 13
  • 44
  • 68
  • I have used for print functionality of data of p:dataTable, same code works in both IE8 and IE9. I used like this : here listId is the id of a – Walker May 20 '14 at 08:06
  • @Walker is working fine if it is not used in a Dialog Box.I had Posted the Code in [Another Question](http://stackoverflow.com/questions/23693590/primefaces-pprinter-inside-a-dialog-is-not-working-in-ie) – 09Q71AO534 May 20 '14 at 12:13
  • It is even working fine in Mozilla and Other Browsers even if it is used in Dialog Box. But IE9 and above it is not supporting to Print instead it is throwing an Error as -"Internet Explorer Stopped Working" @Walker – 09Q71AO534 May 20 '14 at 12:15
  • 1
    This is my [Code](http://stackoverflow.com/questions/23693590/primefaces-pprinter-inside-a-dialog-is-not-working-in-ie)Which i had Tried in a Dialog. Any Suggestions will be Helpfull – 09Q71AO534 May 21 '14 at 06:52
  • 1
    @First the Above CODE Question possible may be a duplicate, but what i am seeking here in this question is how is that Printer.JS works – 09Q71AO534 May 21 '14 at 06:55

1 Answers1

6

How Does printer.js work

printer.js essentially does this.

  • Creates an iframe and append to body (or open new window for opera)
  • Appends the page's linked stylesheets (checks for media=print first, else all apppends all the stylesheets)
  • appends the selected objects (or it's content depending on passed options) to the iframe/window
  • Set focus on the window, and call .print() which should tell the browser to print that "document" in this case the contents of the iframe/window

So for the demo in PrimeFace's website,

the code

<p:commandButton value="Print" type="button">
    <p:printer target="image" />
</p:commandButton>

<p:graphicImage id="image" name="demo/images/nature/nature10.jpg" />

Would create the inline code attached to the resulting "button"

PrimeFaces.expressions.SearchExpressionFacade
  .resolveComponentsAsSelector('image') //resolves to $(document.getElementById())
  .jqprint();
return false;

And to for completeness' sake I commented on printer.js source code

var options;
$.fn.jqprint.defaults = {
    debug: false,
    importCSS: true,
    printContainer: true,
    operaSupport: true
};
jQuery.fn.outer = function () {
    return $($("<div></div>").html(this.clone())).html()
}

$.fn.jqprint = function (passedOptions) {
 //make options from passedOptions and default options
 options = $.extend({}, $.fn.jqprint.defaults, passedOptions);

 //get a jQuery object of the objects to be printed. in this case #image.
 var objects_to_be_printed = (this instanceof jQuery) ? this : $(this);

 //create window or iframe and get the document obj
 if (options.operaSupport && $.browser.opera) {
     var open_window = window.open("", "jqPrint-preview");
     open_window=document.open();
     var document_obj = open_window.document
 } else {
     var iframe= $("<iframe  />");
     if (!options.debug) {
         iframe.css({
             position: "absolute",
             width: "0px",
             height: "0px",
             left: "-600px",
             top: "-600px"
         })
     }
     iframe.appendTo("body");
     var document_obj = iframe[0].contentWindow.document
 }

 //append document's CSS to frame/window
 if (options.importCSS) {
     if ($("link[media=print]").length > 0) {
         $("link[media=print]").each(function () {
             document_obj
               .write("<link type='text/css' rel='stylesheet' href='" + $(this).attr("href") + "' media='print' />")
         })
     } else {
         $("link").each(function () {
             document_obj
               .write("<link type='text/css' rel='stylesheet' href='" + $(this).attr("href") + "' />")
         })
     }
 }

 //appaned selected objects into frame/window
 if (options.printContainer) {
     document_obj.write(objects_to_be_printed.outer())
 } else {
     objects_to_be_printed.each(function () {
         document_obj.write($(this).html())
     })
 }
 document_obj.close(); //close document stream and render data

 //focus on new frame/window
 (options.operaSupport && $.browser.opera ? open_window : iframe[0].contentWindow).focus();

 //wait for 1second before opening printing page
 setTimeout(function () {
     (options.operaSupport && $.browser.opera ? open_window : iframe[0].contentWindow).print();
     if (open_window) {
         open_window.close() //close window if window was used
     }
 }, 1000)
};

What is causing IE9 to fail?

Honestly in this case I'm not that sure. I figure, in this instance, it's just that IE handles window.print() differently. So searching for "window.print() ie9" should be more fruitful than "printer.js ie9". This stackoverflow questions seems to have a lot of options we could try.

I don't have a windows machine handy to test, but for example, following this highly upvoted answer, the opera code seems to be the most compatible (but perhaps as stated in its comment, iframe is preferred as some browsers may think it's a popup perhaps). In that case, perhaps modifying printer.js and adding || $.browser.msie to every instance of options.operaSupport && $.browser.opera might help. Might be a hack but since it is already using browser detection might as well go with it. so it will look something like

 if( options.operaSupport && $.browser.opera || $.browser.msie ) {
 ...
 (options.operaSupport && $.browser.opera || $.browser.msie 
     ? open_window : iframe[0].contentWindow).focus();
 ...
 (options.operaSupport && $.browser.opera || $.browser.msie 
     ? open_window : iframe[0].contentWindow).print();

Hope that helps.

Community
  • 1
  • 1
mfirdaus
  • 4,574
  • 1
  • 25
  • 26