Improving Link Display for Print

by Aaron Gustafson

49 Reader Comments

Back to the Article
  1. That is really cool, you just gave your webpage a bibliography, the gap between web and print has been bridged.
    Copy & paste the code below to embed this comment.
  2. Thank you for your hard work, this script will certainly make it easier for users to archive sites.
    Copy & paste the code below to embed this comment.
  3. I did something similar over a year ago (wrote to A List Apart back then to recommend it as an article - twice - but got no response). It really is a highly useful technique, and this is a great overview of it. My solution added a couple of extra things - firstly I had an ‘exclude’ list - of classes and id’s - any links inside them got ignored (this allowed people to print my blog articles, but not have navigation links shown up). I also created a screen-view with the print style sheet so you didn’t need to use print preview (I just used some simple javascript to extract the print style sheet and rerender the page with it). I never did do a proper writeup, and now someone’s beaten me to it :-)
    Copy & paste the code below to embed this comment.
  4. The techniques on ALA never cease to amaze me with their ingenuity and this one is no exception. This article has educated me twofold - firstly, by showing me that you can actually display links in a print stylesheet (something I was never aware of) and secondly by showing that you can, with a bit of simple and logical scripting, format the links into a readable footnoted format. Excellent stuff.
    Copy & paste the code below to embed this comment.
  5. Great article.  Kudos to everyone at ALA :D In Sam Newman’s post (3) he mentions providing a screen-view of the print style - something like ‘view printable version’.  I have always wondered if we should or should not be providing this functionality to users.  What does everyone think? Why would users need to view the printed style?  To check that we are not going to waste all the colours on their printer? :P ... Is knowledge of printed styles so fleeting in web users that they need to see for sure they are printing a stripped-down ready-for-print version? Love to hear what people think about this.  Maybe there is already an article on it over at useit.com
    Copy & paste the code below to embed this comment.
  6. Its weird because 3 days ago I posted an article on how to show links when you print an article from the web. “You can read the article here”:http://petrangr.blogspot.com/2005/09/link-display-for-print.html
    Of course it is not that advanced as the A List’s. Really good article.
    Copy & paste the code below to embed this comment.
  7. Thank you! Thank you! Thank you! This lovely little snippet of JavaScript is definitley one I will use repeatedly! I thought the article was very well written. As for Alex’s question (5) I think a print preview would be a good option just simply because of the varying paper sizes and margins in spme printers. I have in the oast had to modify my margins prior to printing to allow me to get everything in the articles without really breaking up the flow and outline. If you offer the visitor a print preview they can see what it will look like at their default printer settings so that they can make any adjustments needed. Again though I can see this script having a very long and useful life in the archive of useful JavaScripts I have been puttin together. Thanks again for all your hard work!
    Copy & paste the code below to embed this comment.
  8. I must say I really love this idea. The original method (going to print) was pretty clever, but it did render quite… ugly :) This is beautiful though! Well done!
    Copy & paste the code below to embed this comment.
  9. Really simple technique, but such a brilliant idea! congratulations! I agree with Sam about implementing an exclude list, and I suggest that not only menu links should be excluded but even all the internal links, I think only externals and files (PDF, DOC etc.) links should be printed… For example in a presentation page on a commercial site often happens that a link to a page already in the menu is recalled into the text body: “And don’t forget to visit our customers area to find out offers & discounts”. Why should you report this link? To reach main areas of the site you just need the main domain. This technique is awesome if used as “Bibliography” and link/cite your sources, but pay attention not to link “everything”. Bye
    Copy & paste the code below to embed this comment.
  10. Well assuming you’re using relative links for everything on the site, why not just check if the href commences with ‘http’ ? This is a cool technique, but i’m not 100% convinced. I mean if someone really wanted to check out a link, then to go to the original article and select it is only one extra page load + a mouse click. If they wanted to check out more than one then they would probably do that anyway to save typing.
    Copy & paste the code below to embed this comment.
  11. Hi! A great article. But wouldn’t
    window.onload = function() {
      footnoteLinks(‘container’,‘container’);
    }
    make all previous onload-added functions be erased? I would have suggested Scott Andrew’s addEvent function, but I recently read about some flaws of that method at http://www.quirksmode.org/blog/archives/2005/08/addevent_consid.html - have a look at http://www.quirksmode.org/blog/archives/2005/09/addevent_recodi.html for some alternate ways instead. On the “Print Preview” matter… I wonder if that wouldn’t be “lying to the visitor” in a way: maybe she has made some customisations in the browser that makes the prints different; for example told the browser to exclude background pictures, colors or whatever on print-out. Would a “Print Preview” be able to adapt to that?
    Copy & paste the code below to embed this comment.
  12. _ “...told the browser to exclude background pictures, colors or whatever on print-out. Would a “Print Preview”? be able to adapt to that?“_ The typical modern browser comes with a Print Preview that does most of what you say. Why duplicate that? I would like to see the article’s effect working _on the screen version_ though. It’s just to good to hide! However, I’m not digging the superscripted numbers. What happens if they follow text that is already superscripted? Ie: the squared part at the end of Einstein’s famous formula. I’ve seen print use square brackets around numbers after important words, so I would prefer that. Eg: Visit Meyerweb.com[1] The problem there lies in that the HTML list at the end uses numbers and periods, which doesn’t match the above format. Perhaps generated content could come to the rescue?
    Copy & paste the code below to embed this comment.
  13. A List Apart changed my example! It should have had square brackets around the 1 after the link. (Well it looked OK on preview…)
    Copy & paste the code below to embed this comment.
  14. Chris: “Why duplicate that?” Yep, that was exactly my point. I’m sorry if my language skills didn’t allow me to make that clear. :)
    Copy & paste the code below to embed this comment.
  15. This is seriously great. But what if your document already has footnotes? Maybe an alternate numbering system, such as the links as a,b,c and your regular footnotes as 1,2,3?  Or perhaps a more complex solution that will automatically renumber your existing footnotes and correctly intersperse the links?
    Copy & paste the code below to embed this comment.
  16. (to Pär Axelsson): you can call as many functions one after another, as you want, if you do it this way:
    window.onload = function() {
    functionOne();
    functionTwo();
    functionThree();
    }
    make sure, there is no “onload” call from the “body” tag, though.
    Copy & paste the code below to embed this comment.
  17. Ilya: Yes, but that wouldn’t be very modular. What if I include two different scripts, each with their own set of functions that should be “onloaded” (or onclicked, or whatever). A working cross-browser addEvent()-function would be great to have, why I’m waiting for the “recoding competition” at http://www.quirksmode.org/blog/archives/2005/09/addevent_recodi.html to be finished… Btw how do I include a link in the comments?
    Copy & paste the code below to embed this comment.
  18. We did this on our site about 8 months ago and have found it to be very useful. In addition to not having footnotes for navigation links, we also added some code to check if the text of the link was the url itself. If the url was already displayed, then there’s no need to have a footnote. Minor bug: When you cut and paste from a page using this script, the footnotes carry over, even though they didn’t show up on the screen version of the page. Haven’t figured out a workaround for this (if there is one). Any thoughts?
    Copy & paste the code below to embed this comment.
  19. The following code can be used to replace the duplicate-checking part of the code and avoid the use of a couple of the jsUtilities functions, including inArray, which I imagine isn’t nearly as efficient for large lists as associative arras are. Plus you can avoid that confusing bit with the === operator. if (myArr[thisLink]) { // if a duplicate
            // get the corresponding number from
            // the array of used links
            note_txt = document.createTextNode(myArr[thisLink]);
          } else { // if not a duplicate
            var li   = document.createElement(‘li’);
            var li_txt = document.createTextNode(thisLink);
            li.appendChild(li_txt);
            ol.appendChild(li);
            myArr[thisLink] = num;
            note_txt = document.createTextNode(num);
            num++;
          }
    Copy & paste the code below to embed this comment.
  20. Nice to see a truly useful article at ALA for a change (i.e. not so cutting edge that we can apply it in our day-to-day work). I’d love to see a follow up that incorporates some of the great suggestions that have been made in the comments.
    Copy & paste the code below to embed this comment.
  21. Perhaps I should have explicitly stated so in the article, but I *do not* recommend using the simple onload function I used in the sample files to run the script. I *do* recommend using some method of onload handling (of which there are numerous methods available).
    Copy & paste the code below to embed this comment.
  22. While I was looking over the library, I noticed that the regular expression used to remove a class doesn’t take into account that the class name passed in might be part of another class name. For example, if an element has the classes “mycar car”, and you want to remove the car class, it would result in the classes being named “my car” instead of just “mycar”. The fix that I can see would be to change \\s? to \\b in the regular expression.
    Copy & paste the code below to embed this comment.
  23. This seems to be cool to me, but I am very tired and all that code, while neccessary, currently makes my brainy meats hurt.  I understand what it does, and I understand the commented psuedo code near the top of the article, but the code itself melted into an impossible to understand goop right before my eyes.  My problem, not yours. I say all this to cover my butt in case this question is totally stupid due to my current limited understanding of the code.  What if you want to index links from multiple site areas in this way?  For example, maybe there’s an article, a primary navigation menu with links within the current site, and a seccondary menu with external links to related articles.  You want to exclude the nav section but include the other two.  Or what about ways to exlude certain areas?  What if the ID containing the article or whatever you want to be indexed contains other children that you don’t want to be indexed, ads or some such? I know the scripts could be edited (by someone more compitent or at least less sleep deprived than myself) to allow for these sorts of special cases.  But how extensible is the script as currently written? I know these are special cases well beyond the scope you had in mind for this article, which I freely admit is great and don’t mean to knit pick. And this quasi real time comment preview widget is super cool.  Someone should write an article about that.
    Copy & paste the code below to embed this comment.
  24. There is a very cool Greasemonkey user script that will do something similar for any page.
    It’s called “Annotate Links”:http://www.xs4all.nl/~jlpoutre/BoT/Javascript/AnnotateLinks/
    Copy & paste the code below to embed this comment.
  25. I really hate being the troll, but the jsUtilities library you reference is pretty dangerous stuff. You’ve extended _Object_ which will effectively break anyone who tries to use _for…in_ in their code. <ot>Also, it seems strange that you have all your functions written to use _apply_. Why make things harder than you have to?</ot> How ‘bout making the unobtrusive JavaScript a bit more unobtrusive?
    Copy & paste the code below to embed this comment.
  26. The reason I didn’t simply filter out relative links (which for many sites would be good enough) is because I had a very good idea about what it was people we’re interested in - the body of the article. Back then I was a bit more disorganised (crufty URLs - ugh!) and would frequently use a fixture of relative and absolute URLs. I think I’ve fixed most of them up now, but even so some of my navigation elements use absolute links (for example my del.icio.us links). I can’t remember the exact reason why I showed a print view in a new window rather than relying on print preview, but think it came down to be being frustrated by how slow some of the print previews in various browsers were. I also intensly dislike a print link automatically printing something without being able to see it, and hadn’t worked out how to trigger a print preview. As I already had all the cross-browser DOM walking sorted, finding any print stylesheets and adding screen was a breeze.
    Copy & paste the code below to embed this comment.
  27. I dug out the code snippet I used to make my print stylesheets visible. It’s kind of taken out of context - my print reloaded the page using a query string requesting the print view, which in turn changed the stylesheet link: /*
    * Makes all ‘print’ stylesheets ‘screen’ stylesheets as well so you can see how it will print…
    * TODO: match on ‘print’ assumes a single media type - need to support a list of media types (with indexof?)
    */
    function showPrintStylesheets() {
      var links = document.getElementsByTagName(‘link’);   for (i = 0; i < links.length; i++) {
        var link = links;
        var media = link.getAttribute(‘media’);     if ((media) && (media == ‘print’) ) {
        link.setAttribute(‘media’,media + ‘, screen’);
        link[removed].replaceChild(link,link);
        }
      }
    } I suppose I really should get around to writing this up too…
    Copy & paste the code below to embed this comment.
  28. bq. Why would users need to view the printed style? To check that we are not going to waste all the colours on their printer? :P ... Is knowledge of printed styles so fleeting in web users that they need to see for sure they are printing a stripped-down ready-for-print version? Given the number of websites that haven’t got the hang of print stylesheets, and allow sidebars, ad banners and columns wider than a page to be printed, is it any wonder that users are reluctant to just press ‘Print’? I’ve had a print.css on my website for a long time, but I still get the occasional user suggest that I add a Print-friendly format for each page so that they don’t have to print the blue background - they obviously haven’t found the Print Preview button (and yes, most of them are using IE6 - if they only had v5 I could sympathise). Those users may be a minority. It may be that most people (i) trust me not to waste their colour ink, (ii) don’t care if I waste their colour ink, or (iii) have found the Preview button. I don’t know, and I don’t know how to find out…
    Copy & paste the code below to embed this comment.
  29. I just wanted to let everyone know that I will be incorporating a lot of the great ideas/improvements suggested here into the latest revisions of my jsUtilities library and the footnoteLinks script itself (giving credit where it is due, of course). It will probably be a few days before I can get it all together and put it up on “my site”:http://www.easy-designs.net but I wanted to let you all know that your ideas are great and are not being ignored. If you made a suggestion and would like credit, please email me (aaron [at] easy [dash] designs [dot] net) your name and website (if it isn’t complete here in the discussion) and if your fix makes it in, I will add your info to the comments. A few quick responses:
    * To answer “Derek’s concern”:http://www.alistapart.com/comments/improvingprint?page=3#23 about excluding certain sections, currently that is not supported, but a @class@ of “ignore” on any element will effectively exclude it. Also, the script already has the ability to perform its duties on a uniquely identified section of your choosing and (based on my experience) I have not found a need for more. I keep my most important content (which is where I’d want the links pulled from) in a @div@ with an @id@ of “content.” * As for “David’s concern”:http://www.alistapart.com/comments/improvingprint?page=3#25 about my redefining of @Object@, I will certainly look into the issue and see if there are remedies (I don’t often use @for…in@ loops in JavaScript). Also, my use of @apply@ was somewhat annoying, I know, but was necessary to accomodate Internet Explorer, which does not currently allow extension of @Element@, @Array@, etc. which was my preference. I have requested that this be remedied in the forthcoming version 7, but we’ll see if that actually happens.
    Copy & paste the code below to embed this comment.
  30. I’m probably more sleep deprived now than I was while writing my original message.  I appologize in advance for any incoherance on my part. As long as there’s an effective way to exclude an area, such as class=“ignore”, I can’t really think of any situation that can’t be handled.  It may not be the most efficient possible way, especially if you end up having to exlude 3 elements in order to include 2 children of some parent element, but it’d work.  And I freeley admit any situation like this would be pretty rare.  So that answers my original concerns quite nicely. Also, the link to your site that’s attached to your name is missing the : in http:// so something somewhere is being helpful and adding http:// in front of it, which kills the link.
    Copy & paste the code below to embed this comment.
  31. Great idea, great article. I just implemented the idea in my gaming fansite and printed pages look better than ever. I was using Eric’s idea previously but there were often too many links near each other, and the result was quit scary. But now it all looks great, thank you again :)
    I went a very little step further and replaced:
    document.createTextNode(‘Links’);
    with document.createTextNode(‘Link index - ‘+self.location); and added a page-break-before: always; to the styles of the “Links” container.
    The final result: the links now come in the last printed page (the user might not want to print it out) and the title says what page the links are from so that the page doesn’t get lost.
    Copy & paste the code below to embed this comment.
  32. Is there a way to ignore all links inside blocks such as wrapping paragraphs and divs? I don’t have any javascript skills… Thank for your artice! I’m already using it.
    Copy & paste the code below to embed this comment.
  33. Should be easily done with CSS ID and/or classes :-)
    Copy & paste the code below to embed this comment.
  34. Interesting but there is one little flaw. Currently the script appends a class of @noted@ to the @html@ element (gasp !). Class is not a valid attribute for @html@ in any of the official DTD (see the “html 401 rec”:http://www.w3.org/TR/html401/struct/global.html#edef-HTML for a starter). In practice, this is not so important, all current modern browsers actually support it (that is, recognize the @html.noted@ selector). But still, it would be better to append said class to the @body@ element.
    Copy & paste the code below to embed this comment.
  35. If I apply this to a page that doesn’t have any links (and as I’m including the footnoteLinks.js file in my header, I can’t *not* include it), I get an empty section with the heading “Links” at the bottom.  How can I prevent the “Links” section from appearing?  Now, the page I’m creating does have links, but they’re all marked with “ignore” because they’re footnote superscripts that point to named anchors within the page.
    Copy & paste the code below to embed this comment.
  36. This is just awesome. I’m going to have to implement this myself. It’s so simple, but so damn effective. Thanks heaps.
    Copy & paste the code below to embed this comment.
  37. I would like to say that this is a great idea. I have expanded on this script greatly. Essentially, my changes included the dropping of the jsUtilities package (it altered Object, which from my understanding is VERY unsafe). Part of this was achieved by simply making the modifications that Brian Hardy suggested in his post and part from my own version of addClass. I expanded upon the ability to ignore certain sections. Now you can label an element to be ignored and its descendants will also be ignored. Also, I strip off “mailto:“‘s, and ignore any code that has an href of simply “#” (usually used as a handler for JavaScript) and links to JavaScript code (href=”[removed]...”). Another change is that the h2 and the ol elements are only attached if there are any links found on the page. Finally, the code also ignore links where the text of a link is the link itself. You can see an example of my code by doing a print preview against: http://www.cps.brockport.edu/~cpsclub/ (note that the e-mail address isn’t printed). The code is in compact form similar to the code in the article. A more readable version can be seen at http://www.cps.brockport.edu/~cpsclub/template/footnoteLinksExpanded.js
    Copy & paste the code below to embed this comment.
  38. I was wondering if anyone else had run into this problem.  In IE6, if you have a linked image (e.g. ...), I get two superscripts and footnotes - one for the <a> tag and one for the <img> tag.  The first footnote has the URL of the <a> tag, and the second has the URL in the src attribute of the <img> tag. Why does this happen?  Any ideas on how to fix it? You can try this out for yourself by just adding a linked image to the final HTML from the article:
    http://www.alistapart.com/d/improvingprint/files/final.html
    Copy & paste the code below to embed this comment.
  39. Yes, this is a problem. Mozilla will also double the superscripts, but it won’t add a supercript for the image. I’ll look into it and see if I can fix this.
    Copy & paste the code below to embed this comment.
  40. Ansel: I modified my version heavily from the authors code. Mine no longer has this problem. I solved it by walking the DOM with a recursive function, rather than just grabbing every single element. If anyone knows anything about Memory leaks, can you please review the expanded version of the code. I’m not well versed in this (I have been reading all of the recent QuirksBlog entries on this subject) and not sure if I’ve worked around them. I think so….
    Copy & paste the code below to embed this comment.
  41. Brian, thanks for taking a look at it.  However, the links in your previous comment (#37) don’t work (403 Forbidden).  Is that page not accessible outside your university?
    Copy & paste the code below to embed this comment.
  42. I discovered the correct link:
    http://www.cps.brockport.edu/~cpsclub/template/footnoteLinksExpanded.js (The links posted in comment #37 are missing the tilde before “cpsclub”.)
    Copy & paste the code below to embed this comment.
  43. Sorry about that. Glad it worked for you (I assume it works or you’d have complained when posting).
    Copy & paste the code below to embed this comment.
  44. I was just checking through the comments again to see how the discussion has progressed and it looks like you all have been very busy kicking the tires and finding bugs. I love all of the energy around this script and am very happy this has made so many of you smile. In the coming weeks I will be looking over the enhancements you all have put together and will look to roll them into a revised version I have planned. Thanks again for all of your feedback!
    Copy & paste the code below to embed this comment.
  45. This is so great! I use it on my own website, if you want to check. I only changed one thing: when there is no link at all, I find it disturbing to have a “links” title with no content, so I have just added a test for num > 1 before actually adding the content. HTH
    Copy & paste the code below to embed this comment.
  46. Another possibility would be to check the _myArr_ array to see if it is empty before appending the <h2> and <ol>: if (myArr.length > 0) {
      // append the heading and ordered list to the target
      target.appendChild(h2);
      target.appendChild(ol);
    }
    Just another way of preventing “Links” from showing up in case there are no links on the page or you have all of them in the _ignore_ class.
    Copy & paste the code below to embed this comment.
  47. I’ve just implemented this on my own site (www.fueladvance.com) and it rocks! Try printing our homepage…
    Copy & paste the code below to embed this comment.
  48. @Brian LePore: I’ve seen you’ve made a lot of alterations, but how do you implement them? Do you have some description? What I was missing in the original script was not having the ability to skip elements (e.g. a menu). Even if it is set to display:none it will not print but the links are added to the list anyway. This could be solved bij adding ignore to an element (which is not possible right now) or by ignoring all elements that are not dispayed all together.
    The class ignore did not seem to work bij the way but that is probably my bad implementation. Another thing is that IE treats images as a link too. But the technique is great and offers a great result for the end user.
    Copy & paste the code below to embed this comment.
  49. Hi, The author’s technique is pretty slick.  However, it wasn’t *quite* was I was searching for—hopefully someone here knows the answer.  Is there a way to have a larger document that has lots of anchor links print just the page number they’ll appear on?  So if you’re printing something that looks like this: Additional Considerations ...it would appear in a print version as: Additional Considerations (p. 17) This ability would really help for a document I’m currently working on. Thanks,
    Kev
    Copy & paste the code below to embed this comment.