Print preview popup

  2015-06-11

best practices quality

When developing web applications you would sometimes need to generate some sort of “downloadable” report. Very often upon hearing this requirement developers start thinking of some complex solutions such as generating a PDF file on the server and sending it to the client with “Content-Disposition:attachment”. This leads to the use of tools like wkhtmltopdf or worse yet, Crystal Report. While these tools are useful, for majority of the cases they are an overkill.

Many developers forget the simple fact that any web page can printed to a PDF file (assuming that the client machine has Adobe Acrobat or an analog). This means all we need to do is create a web page with the right content and styling.

Generating print preview

Often when printing a web page you only want to print a specific portion of the that page. To do that you can simply create a new window with window.open and insert your HTML into it. Additionally you would probably want to add some print-specific CSS rules, so that your report looks like a report and not a web page.

Enter Print Preview Window

Below code is a reusable javascript snippet that allows opening print preview of a specific DOM element.

/*********************************************************************************************************
# Print Preview Window
Print preview window opens up in a separate window as a popup. It can be used to quickly send any DOM element for printing.

## How to use
To use, simply create a button/link/etc with attribute `data-print` and pass options object `{ selector: "#element-to-print" }`.
Whenever that button is clicked the popup with the print privew will open. Example:

<button data-print='{"selector":"#report"}'>Print</button>
*********************************************************************************************************/
(function() {
    var getAbsoluteUrl = function(href) {
        var link = document.createElement("a");
        link.href = href;
        return link.href;
    };

    var popup = null;

    $("body").on("click", "[data-print]", function (e) {
        e.preventDefault();

        // Get options.
        var options = JSON.parse($(this).attr("data-print"));
        var selector = options.selector;

        // Open popup window.
        if (popup == null || popup.closed) {
            popup = window.open("", "printpreview", "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes");
        } else {
            popup.focus();
            return;
        }

        // Define basic page layout.
        var page = $('<div>' +
            '<div id="header"><img src="logo.png" /></div>' +
            '<div id="content"></div>' +
            '</div>');

        // Add report to the popup.
        page.find("#content").html($(selector).html());
        $(popup.document.body).html(page.html());

        // Copy all stylesheets from this page.
        $("link[rel=stylesheet]").each(function(key, value) {
            var relativeUrl = $(value).attr("href");
            var absoluteUrl = getAbsoluteUrl(relativeUrl);

            $(popup.document.head).append('<link rel="stylesheet" href="' + absoluteUrl + '" type="text/css" />');
        });

        // Add custom "print" stylesheet.
        $(popup.document.head).append('<link rel="stylesheet" href="/styles/print.css" type="text/css" />');
    });
}());

Now all you need to do is add a print button to your page, which users can click to open the print preview window.

<button data-print='{"selector":"#report"}'>Print</button>

That’s pretty much it.

Side-thoughts

As software developers we must always strive to reduce complexity of our solutions, but very often we over-complicate things without even realising it. It is important to slow down from time to time and see how things can be done differently. It also important to remember that very often our clients/end-users don’t really know what they want and just don’t know what’s possible, so we must always try understand the core problem behind user requirements. This way we can solve their problems more effectively and hopefully with less effort.

22bugs.co © 2017. All rights reserved.