How to create an unobtrusive print this page link with JavaScript

When a client requests that I duplicate functionality that should be (and is) handled by web browsers, I always try to avoid doing it by explaining why I believe it is better to leave such functionality to the browser. Most of the time I succed, but occasionally I don't.

One common request that duplicates browser functionality is a "Print this page" link. Most developers have probably added such links more than once during their career. Doing so isn't necessarily "wrong", and it won't bring serious harm to any kittens or other cute animals, but it is very unusual to see print links implemented in an unobtrusive way, so here is how to do that.

First a look at the obtrusive way. Most of the time print links are hardcoded in the HTML, and look something like this:

  1. <a href="javascript:window.print()">Print this page</a>

While that does work for most users, it doesn't separate content from behaviour. It also uses the fake javascript: protocol. But worst of all, it will confuse people browsing without JavaScript. The link will still be there, but when they click it, nothing happens.

The simple solution to this problem is to use JavaScript to create the link (or button, which arguably may be a more suitable element). The following script takes an element id and the link text as arguments, creates a link with an onclick event handler that triggers the browser's print function, and appends it to the element:

  1. var addPrintLink = {
  2. init:function(sTargetEl,sLinkText) {
  3. if (!document.getElementById || !document.createTextNode) {return;} // Check for DOM support
  4. if (!document.getElementById(sTargetEl)) {return;} // Check that the target element actually exists
  5. if (!window.print) {return;} // Make sure the browser supports window.print
  6. var oTarget = document.getElementById(sTargetEl);
  7. var oLink = document.createElement('a');
  8. = 'print-link'; // Give the link an id to allow styling
  9. oLink.href = '#'; // Make the link focusable for keyboard users
  10. oLink.appendChild(document.createTextNode(sLinkText));
  11. oLink.onclick = function() {window.print(); return false;} // Return false prevents the browser from following the link and jumping to the top of the page after printing
  12. oTarget.appendChild(oLink);
  13. }
  14. /* addEvent function removed from this listing*/
  15. };
  16. addPrintLink.addEvent(window, 'load', function(){addPrintLink.init('article','Print this page');});

The full script is available in addprintlink.js, and I made a simple demo page where you can compare the obtrusive and unobtrusive ways of creating print links.

I have tested the script in every browser I have access to, and it works as expected everywhere with three exceptions, all related to Apple WebKit. In OmniWeb, Shiira, and Safari 3 beta for Windows, window.print evaluates to true, but nothing happens when window.print() is executed. window.print() being broken is listed as a known issue on the OmniWeb support page, and there is a note about the problem in the Windows version of Safari 3 on Apple's support site, but I can't find anything about it in the Shiira forum. It seems likely that it will eventually be fixed in all three browsers.

Browser bugs aside, the take-home lesson from this article is that any links or other elements that require JavaScript to work properly should also be created with JavaScript. Otherwise you risk confusing and annoying users who are browsing without JavaScript support.

Posted on September 14, 2007 in JavaScript, Usability