WWW FAQs: How do I add a link to print only one part of a web page?

2007-03-30: "I want to print only one image, or one div, from a web page— not the whole thing. I'm not just talking about eliminating navigation here— I might have 100 images and want to be able to print them all individually! How do I do that?"

I had my doubts that this was pratical without code on the server side. But I've found a solution that works well in Internet Explorer, Safari and Firefox.

The trick is to open up a new window (or tab) from your JavaScript code and fill that window with a simple page that displays the image in question. The code for the new, temporary window also contains JavaScript... which prints out the temporary window's contents and then closes the window.

Generating the HTML for a new window "on the fly" is a powerful technique with many applications. And it's not hard to do:


var pw = window.open("about:blank", "_new");
pw.document.open();
pw.document.write("my HTML code goes here...");
pw.document.close();

However, there are three catches:

1. You can't put a </script> tag inside a quoted string in JavaScript code. That is, the following code will not do what you want:


pw.document.write(
  "<html>" +
  "<head>" +
  "<script>" +
  "... javascript code for the new page ..."
  "</script>");

Why not? Because the web browser sees </script>, and the show's over! As soon as the web browser spots that tag, the browser considers the JavaScript code in the main page to be at an end.

Fortunately, there's an easy workaround:


pw.document.write(
  "... other HTML code ..." +
  "<script>" +
  "... javascript code for the new page ..."
  "</scr" + "ipt>");

What's happening here? We split the closing </script> tag into two separate quoted strings. That way, the HTML parser of the web browser doesn't react to it... not until it becomes the source code for the new window.

2. The onLoad problem. We want to call window.print() and window.close() from the onLoad handler of the new window... right? You could be forgiven for thinking that— it makes perfect sense!

Unfortunately, Firefox doesn't actually display the full content of the new page until onLoad has returned. So the print dialog box appears on top of an apparently blank page. The actual printout is fine, but the user doesn't understand what they are seeing— so they are likely to cancel the print operation.

Luckily we can solve this problem too. Instead of printing and closing the window right away, we use JavaScript's setTimeout function. The setTimeout function executes a piece of code after a certain number of milliseconds (thousandths of a second) have passed:


setTimeout("myfunction()", 10);

Ten milliseconds is a very short time— right away, in other words. In practice, we don't really want a delay. We just want to make sure the image has actually appeared in the temporary window before the printing dialog box pops up.

3. Which image am I anyway? To make this code easy to use all over our pages, we'd like to automatically figure out which image has called the printme() function from its onClick handler. But earlier versions of Internet Explorer and... well... every other browser in the world have different ways of handling events. We get this right by checking for both an event object passed to the function and Microsoft's window.event object. We must also check for both the target property (which is the element that was clicked on in standards-compliant browsers) and the srcElement property (which is the same thing in Internet Explorer).

Enough Talk, Let's Print!

Here's the code for a complete page that implements this technique. When you click on the image, the image pops up in a temporary window, and the print dialog box pops up immediately afterwards. Whether you choose to print or not, the temporary window then closes, returning you to the original page. This works in reasonably current versions of Internet Explorer (including both 6 and 7), Firefox, and Safari. Note that some very early versions of Safari might not play along.


<html>
<head>
<title>Print Image Only</title>
<script>
function makepage(src)
{
  // We break the closing script tag in half to prevent
  // the HTML parser from seeing it as a part of
  // the *main* page.

  return "<html>\n" +
    "<head>\n" +
    "<title>Temporary Printing Window</title>\n" +
    "<script>\n" +
    "function step1() {\n" +
    "  setTimeout('step2()', 10);\n" +
    "}\n" +
    "function step2() {\n" +
    "  window.print();\n" +
    "  window.close();\n" +
    "}\n" +
    "</scr" + "ipt>\n" +
    "</head>\n" +
    "<body onLoad='step1()'>\n" +
    "<img src='" + src + "'/>\n" +
    "</body>\n" +
    "</html>\n";
}

function printme(evt)
{
  if (!evt) {
    // Old IE
    evt = window.event;
  }    
  var image = evt.target;
  if (!image) {
    // Old IE
    image = window.event.srcElement;
  }
  src = image.src;
  link = "about:blank";
  var pw = window.open(link, "_new");
  pw.document.open();
  pw.document.write(makepage(src));
  pw.document.close();
}
</script>
</head>
<body>
<h1>Print Image Only</h1>
When you click on the image below, just the image should print.
And the temporary window used in the process should go away
afterwards, whether you allow the print operation to go ahead
or not.
<p>
<noscript>
<b>You have JavaScript turned off.</b> So this won't work.
That is to be expected.
</noscript>
<p>
<img src="http://www.boutell.com/boutell/images/fortune.jpg" onClick="printme(event)"/>
</body>
</html>

What If I Want To Print More Than An Image?

This article shows how to print one image on a page. But it's also possible to print something more complicated— like an entire div element.

The trick to printing an entire div is to fetch its HTML code with the innerHTML property. You can then include that HTML in the new document you build for the temporary window. It's not hard to do this - just give the div an id attribute, and pass that id attribute to your version of the printme function so that you can fetch the appropriate div.

Conclusion

That's it— you're ready to print only what you want to print, on demand! Just remember to provide a reasonable fallback mechanism for users without JavaScript, unless the "print one image" feature is not a crucial part of your site. Indeed, you could simply tell such users to right-click on the image and select "View Image," then "Print," and then the "Back" button. Put those instructions in a noscript element, so no one else has to read them, and you're good to go! (Mac users may need to hold their single mouse button down rather than clicking the right mouse button.)

Share |

Legal Note: yes, you may use sample HTML, Javascript, PHP and other code presented above in your own projects. You may not reproduce large portions of the text of the article without our express permission.

Got a LiveJournal account? Keep up with the latest articles in this FAQ by adding our syndicated feed to your friends list!


Follow us on Twitter | Contact Us

Copyright 1994-2014 Boutell.Com, Inc. All Rights Reserved.