8
\$\begingroup\$

I have a need to print the content of a jQueryUI Dialog to a printer, and I couldn't find anything to my liking. I developed the following simple jQuery plugin which prints one or more provided HTML elements, and am using it to print the jQueryUI Dialog DIV element. The code is below, and a live example is located here.

It works on FF 26.0. However, after printing a couple of times, FF asks the user if popups should be disabled, which I wish not to happen. Also, it doesn't work with older IE, and likely other browsers. Don't worry because, when printing, you still need to click the operating system print dialog, so you won't waste any paper!

Please provide any recommendations on how this plugin could be improved.

Actual Plugin:

/*
* jQuery printIt
* Print's the selected elements to the printer
* Copyright Michael Reed, 2014
* Dual licensed under the MIT and GPL licenses.
*/
(function($){
    var defaults = {
        elems           :null, //Element to print HTML
        copy_css        :false,//Copy CSS from original element
        external_css    :null  //New external css file to apply
    };

    var methods = {
        init : function (options) {
            var settings = $.extend({}, defaults, options)
            elems=$(settings.elems);
            return this.each(function () {
                $(this).click(function(e) {
                    var iframe   = document.createElement('iframe');
                    document.body.appendChild(iframe);
                    $(iframe).load(function(){
                        elems.each(function(){
                            iframe.contentWindow.document.body.appendChild(this.cloneNode(true));
                        });
                        if(settings.copy_css) {
                            var arrStyleSheets = document.getElementsByTagName("link");
                            for (var i = 0; i < arrStyleSheets.length; i++){
                                iframe.contentWindow.document.head.appendChild(arrStyleSheets[i].cloneNode(true));
                            }
                            var arrStyle = document.getElementsByTagName("style");
                            for (var i = 0; i < arrStyle.length; i++){    
                                iframe.contentWindow.document.head.appendChild(arrStyle[i].cloneNode(true));
                            }
                        }
                        if(settings.external_css) {
                            var style  = document.createElement("link")
                            style.rel  = 'stylesheet';
                            style.type = 'text/css';
                            style.href = settings.external_css;
                            iframe.contentWindow.document.head.appendChild(style);
                        }
                        var script   = document.createElement('script');
                        script.type  = 'text/javascript';
                        script.text  = 'window.print();';
                        iframe.contentWindow.document.head.appendChild(script);
                        $(iframe).hide();
                    });
                });
            });
        },
        destroy : function () {
            //Anything else I should do here?
            delete settings;
            return this.each(function () {});
        }
    };

    $.fn.printIt = function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || ! method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' +  method + ' does not exist on jQuery.printIt');
        }    
    };
    }(jQuery)
);

To configure:

$(function () {
    $("#openDialog").click(function () {
        $("#myDialog").dialog('open')
    });
    $("#myDialog").dialog({
        modal: true,
        autoOpen: false
    });
    $('#printIt').printIt({
        elems: $("#myDialog"),
        copy_css: true,
        external_css: 'test2.css'
    });
});
\$\endgroup\$

1 Answer 1

2
+25
\$\begingroup\$

From a once over:

  • I am not a native English speaker but //Element to print HTML confused me. Maybe //HTML elements to be printed?
  • delete settings; is meaningless in destroy ( see comment )
  • elems=$(settings.elems); should be var elems = $(settings.elems); otherwise you pollute the global namespace
  • You declare var i twice in a for loop
  • You should consider removing the iframe in destroy

All in all very clean, maintainable code.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ delete settings will always be meaningless as its a scope variable. He should remove that altogether \$\endgroup\$
    – megawac
    Jan 17, 2014 at 13:57
  • \$\begingroup\$ Thanks tomdemuyt. elems is in fact the element which will be printed, not the print button. How do you think it could be modified to be more cross browser compliant with earlier IE and even current FF (i.e. causes FF to generate popup asking whether it should prevent script from generating popups). \$\endgroup\$ Jan 17, 2014 at 14:49
  • \$\begingroup\$ I do not believe you can avoid the FF popups at all, I tested your plugin in Chrome, it works. \$\endgroup\$
    – konijn
    Jan 17, 2014 at 21:25
  • \$\begingroup\$ Yea, It works with recent Chrome as well is IE 9, 10, and 11. My main objective was allowing it to work with FF. The line that is causing it is script.text = 'window.print();'; \$\endgroup\$ Jan 18, 2014 at 18:57
  • \$\begingroup\$ 3500! Congrats! \$\endgroup\$ Jan 19, 2014 at 17:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.