jQuery Printed Footer Links

Monday, March 8. 2010

I was randomly perusing the web and stumbled across an older interesting List Apart article (September 19, 2005 to be exact). In it, the author used JavaScript to create a list of all links found on the page, and then create a footer with a footnote-like list. I was using simple CSS to display the URL of the hyperlink in print display media, but that doesn't work in some browsers (IE), and worse off it can really mess up the visual order of the page.

Inspired by the article's intentions, I decided to use some jQuery to whip up a similar solution and I took the opportunity to use jQuery 1.4's new syntax for object creation (so this is 1.4 code only - see comments for a 1.3.x solution). Differences? I exclude hyperlinks set to the hash symbol (#) which shouldn't be found anyway (graceful degredation people!), "mailto" links, and I don't find link element's citations (blockquote "cite" property). I also believe his script would grab image information, but I'm not entirely sure, mine only searches hyperlinks. I also opted not to exclude listings of duplicate hyperlink values. If it's found twice, it lists it in the footer twice. Less JS processing, and more clear to the visitor (in my opinion).

Expected Issues: It requires JavaScript (and the jQuery library included on your page). If JavaScript is enabled but CSS is disabled, the hidden content will be visible to the user.

On to the code!

First thing's first, we should find the links in our code that we'd like to target. For my situation, I have a content class defined on my page for all content, and the column that contains the actual body is called ".col2_right" (yes, I know, ignore the fact of the poor naming scheme). So, in jQuery, we're going to target all hyperlinks found in the col2_right and content classes, but we don't want to include links to hashes or mailto links. I've also removed listing to nofollow links, but that is my choice (probably not a good one, but I digress).


We'll also need some sort of container to keep these found links wrapped in. I chose to use a fieldset and legend, you could just as easily create a DIV and a H2 or other tags for your own purposes. I also want to create an ordered list to match the found hyperlinks.

Here comes the real center, meaty goodness of the script: looping through our list of found hyperlinks, creating a little notification text next to the hyperlink's text, and add the hyperlink URL itself to the footnote section in the ordered list as a list item.

We use jQuery's each() method to loop through the items in the array, grab the link's URL so that we can do some testing on it, and modify it's value for inclusion in to the footnotes. Some links may be relative URLs, but that doesn't mean much to someone who doesn't know what a relative URL is. In fact, it would probably confuse me too at first. I happen to know that my domain forces www for the subdomain so I've added that in, fix that up as you like. I then create a span tag to hold the associated footnote number (the ListApart article used a superscript tag, I found regular text is more easily readable), add a class to it so it's only visible when printed, and create my list item element with the URL from our link, and place those elements in to the document in the appropriate places with the appendTo jQuery function.

Last but not least, we append our entire footnote to the end of our content body section. The full code is below.


Note the added "if" statement to check the length of the links variable. If it is empty, we did not find any links and don't want to create any extra markup when printing the page.

Oh, and the CSS: ".print_only { display:none; }" This should be placed in your normal style sheet, and leave it out from your print style sheet. If you don't have a print style sheet, extend it a bit: @media print { .print_only { display:none; } }

Note: Thanks to Stiles to provide some fixes and compatibility changes for jQuery 1.3.x.

Trackbacks


Trackback specific URI for this entry
    No Trackbacks

Comments


    #1 Stiles on 03/24/10 at 07:44 AM [Reply]
    Thanks for the jQuery version of the ALA script, it's exactly what I was looking for! However, I had to make some mods for it to work with jQuery 1.3.2:

    First, lines like

    CODE:
    var footnotesWrapper = $('', {css: {clear: 'both'}}).addClass('print_only');


    I had to change to

    CODE:
    var footnotesWrapper = $('', {}).addClass('print_only').css({clear:'both'});


    Also, the original selector to find the links on the page would pick up anchors which did not have an href defined (there was no href="" inside the a tag). Then later in the code, when you check the first character of the href (linkValue.substring(0,1) === '/') javascript throws an error because href is undefined. To fix this, I changed

    CODE:
    var links = $('.col2_right.content a:not([href^=#],[href^=mailto],[rel=nofollow])');


    to

    CODE:
    var links = $('.col2_right.content a[href]:not([href^=#],[href^=mailto],[rel=nofollow])');


    After these minor changes, it's working great! Thanks again.
    #1.1 Brendon Kozlowski on 03/24/10 at 08:35 AM [Reply]
    Dangit, I forgot to mention that I wanted to attempt to use the new ability of jQuery 1.4 to create the objects; so of course this wouldn't work in 1.3.x - sorry about that, and thank you for mentioning it.

    Ironically, I made the exact same change to someone else's script 2 days before (a[href]) and didn't put it in this code, I have no idea why. I'll be updating the code for the anchor without an href property, as well as mentioning this works for jQuery 1.4+. Thank you for your comment!

    I've also updated the full code block and added in an "if" statement. You've probably already done this, but thought I would bring it up.
    #2 Brian on 12/19/10 at 10:43 AM [Reply]
    What you've written seems beautifully simple and easy to understand but I'm having difficulties making it work. Am I right in my understanding that:

    1. I have a print stylesheet that puts the href after any links (i.e., a:link:after{etc..}) -- I've been using this for a while successfully.
    2. I load the jquery library from an external file.
    3. I take the "full code" (last snippet) from above and either reference it externally or put it inline in my page -- and I alter it so that the container we're searching is correctly named.

    I've done all this but nothing. What am I missing?
    #2.1 Brendon Kozlowski on 12/20/10 at 07:51 AM [Reply]
    You're certainly able to keep #1, but it's not necessary - the whole point of this script is so that the links themselves are not listed directly in the body of the page (and for very long links, it can make your page look severely odd), but instead place that information in a footer. You're more than welcome to leave it in the body of the page though if you'd like. :)

    2 & 3: Yes and yes.

    It's hard to say without seeing a live example of it not working. Do you have a location with it online and live that I could see?

    ...also, remove the "www" in the "http://www" + document.location.host line...that was an oversight of mine, and I've edited the code as such.
    #2.1.1 Brian on 12/20/10 at 08:54 AM [Reply]
    Thanks Brendon, as an example, you can see it failing here:
    [url=http://www.chabun.com/blog/post/2009/04/05/Using-wget-to-keep-your-website-alive.aspx]http://www.chabun.com/blog/...[/a]

    The scripts are just before the closing form tag, one to jquery, and then inline script with your code.

    thanks for looking at this.
    #2.1.2 Brian on 12/20/10 at 03:23 PM [Reply]
    Hi again Brendon,
    I don't know what's wrong on that page that I sent you. The css validates, I'm validating the html now. Then I'm going to try simplifying the blog theme I modified. I had grabbed it from someone and just changed a couple colours. However, your solution worked for me in a simple page doing as I described in my first post:
    http://www.chabun.com/blog/themes/chabun/test.html

    So, I'll muddle along and figure it out (unless you really have time to look at my page ... which is far more than I expect).

    Thanks for your help.
    #2.1.2.1 Brendon Kozlowski on 12/20/10 at 09:14 PM [Reply]
    Hey Brian. I'm heading for bed, but I did take a quick look at it to see where the problem is coming from. The JavaScript seems to be running just fine. The issue is in the CSS.

    That is the problem; I haven't yet looked through to find exactly what the problem is, but a quick solution would be to forcibly show the footnote area, and the referencing numbers (in your current version of the code, the SUP tags).

    In the print style sheet:
    .print_only { display:inline; }
    fieldset.print_only { display:block; }

    That should (hopefully) fix the visibility issues you're having; though I doubt it's the best solution; and there may be others wandering around.

    In your example, you'd probably also want to disallow links that contain "javascript:[...]" from being rendered in the footnote area. :)
    #2.1.2.2 Brendon Kozlowski on 12/20/10 at 09:24 PM [Reply]
    It looks like you figured it out and was working on it while I was looking it over. :) Looks good!

    (...and you did it without my overbearing CSS band-aid fix.)

Add Comment

E-Mail addresses will not be displayed and will only be used for E-Mail notifications.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

BBCode format allowed