Print pages and page fragments using an IFrame and jQuery

In my current Grails project I am using jQueryUI to display information in a dialog window. When opening the dialog window, the content of the dialog is loaded via Ajax.
One requirement we had to implement was a print button in some of those dialogs.

When pressing the print button, only the content of the dialog should be printed.

Simply triggering the browser’s print dialog when pressing the button didn’t work, because the whole page gets printed and the content of the dialog is not visible at all.

The solution I found is based on an IFrame and a JavaScript-Function:
Add a print IFrame to every page (you should add it to your central layout file). I recommend adding it to the bottom of the page.
Size it to 1*1 so that it is not visible.

<iframe width="1" height="1" id="printFrame" />

If you are using Grails, add the IFrame to your main.gsp layout file and place it before the closing body tag.

Include the following JavaScript function in pages where you need printing functionality:

function printUrl(url) {
	$('#printFrame').attr('src', url);
	$('#printFrame').load(function() {
		var frame = document.getElementById('printFrame');
		if (!frame) {
			alert("Error: Can't find printing frame.");
			return;
		}
		frame = frame.contentWindow;
		frame.focus();
		frame.print();
	});
}

This function is called with a url that is used to retrieve the page or page fragment to be printed.
The page gets loaded into the printing IFrame and the browser’s printing functionality is triggered.
If you are using Grails, add the code shown above to your application.js file.

Add a print-button to your page:

<input type="button" value="print" onClick="printUrl('URL_OF_PRINT_SOURCE')"/>

Replace URL_OF_PRINT_SOURCE with the url where the page or page fragment to be printed is located.

If you are using Grails, you can easily link to a controller action with the createLink method (replace CONTROLLERNAME and ACTIONNAME):

<input type="button" value="print" onClick="printUrl('${createLink(controller: 'CONTROLLERNAME', action: 'ACTIONNAME')}')"/>

In my case, I had to print the dialog contents which is loaded from a controller-action, so I could reuse the existing controller action for printing.

Short URL for this post: http://wp.me/p4nxik-mp
This entry was posted in Groovy and Grails, Java Web Frameworks and tagged , , , , . Bookmark the permalink.

5 Responses to Print pages and page fragments using an IFrame and jQuery

  1. Hi, Nice solution, but you could also grab the content of your dialog:

    var dialog $(‘#dialog’).clone()

    $(‘#printFrame’).empty().append(dialog).focus().print()

    That way you do not have to reload the dialog content…

    PS. The code above comes from the top of my head – it is not tested, I have not even tried if it works :-)

  2. Bob Patin says:

    Hi,
    I’m trying to use your function with a form, in this way:

    When someone submits the form, the IDs of the records on the screen are gathered, and submitted to the PRINT page using a GET, like this:

    batch_print?r=print0=123&print1=125&print2=126… and so on

    Is there a way to use your function with a form, so that when the user submits it, it’ll print my page? So far I haven’t been able to figure it out.

    Thanks,

    Bob Patin

  3. Nice work, I had tried a dozen different solutions/variations but this worked just how I wanted it to. thanks

  4. Sebastian says:

    Replace line 3:
    $(‘#printFrame’).load(function() {
    by
    $(‘#printFrame’).unbind(‘load’).load(function() {

    This is my full function:
    function printUrl(url) {
    var ifr = $(‘#printFrame’);
    ifr.attr(‘src’, url);

    ifr.unbind(‘load’).load(function() {
    setTimeout(function(){
    var frame = document.getElementById(‘printFrame’);
    if (!frame) {
    alert(“Error: Can’t find printing frame.”);
    return;
    }
    frame = frame.contentWindow;
    frame.focus();
    frame.print();
    },1000);
    });
    }

  5. Good work..But if you have pdf data in base64 format …
    Example:

    How can i print this iframe ?

Leave a Reply