Thursday, June 11, 2009

Find & select all external links with jQuery

Selecting all external links and amending them in some way is probably one of the most used jQuery tutorials. By selecting all anchor links on the page and for example adding a CSS class with only one jQuery line shows how jQuery is simple and powerful. Also if you are progressively enhancing your website this is one of the trick you might use.

Actually, I had to select all external links and add an image that indicates it the other day. So, I created a custom jQuery selector called :external that makes finding external links easier for you. (Read “Custom jQuery Selectors” post to learn how to create your own custom selectors)

External links custom jQuery selector code:

// Creating custom :external selector
$.expr[':'].external = function(obj){
    return !obj.href.match(/^mailto\:/)
            && (obj.hostname != location.hostname);
};

// Add 'external' CSS class to all external links
$('a:external').addClass('external');

You can see this code in action here.

You may use the code above to:

  • Add CSS class to all external links
  • Dynamically add an image after the link to indicate that it is an external link
  • Bind a click event to track what links where clicked
  • etc.

Update: The return part was update to take into the account the mailto links as suggested in comments by Phillipp and Karl below.

8 comments:

  1. I just want to say your posts and tutorials are all very useful and practical. Its great, and I enjoy checking them out weekly~

    Thank you~

    -Soh

    ReplyDelete
  2. Nice one. You might want to account for "mailto" links as well. Your selector will match those, when it probably shouldn't. Just change the second line to this:

    return (obj.hostname && obj.hostname != location.hostname);

    ReplyDelete
  3. You may want to change the line

    return (obj.hostname != location.hostname);

    to something like

    return obj.hostname && (obj.hostname != location.hostname);

    in order to not select any mailto: links for example.

    ReplyDelete
  4. Ok, maybe that was a bit too dirty. In IE6 obj.hostname for mailto links actually returns the part after the @. So we'd better have something like:

    return !obj.href.match(/^mailto\:/) && (obj.hostname != location.hostname)

    ReplyDelete
  5. @Karl, @Phillipp, Thanks for pointing that out.

    Updated the post...

    ReplyDelete
  6. You might also want to include something like this:

    (jQuery(obj).attr('href') !== undefined)

    This way links to anchors on the same page will not get selected.

    ReplyDelete
  7. Thanks for sharing this useful script.

    Do you have any piece of code which uses jquery to let me

    1) assign rel="nofollow" to all external links
    2) open in new window
    3) have a small icon indicating external link

    ReplyDelete
  8. for this job you don't need jQuery at all. try to use CSS instead:
    a[href^="http"] {
    background: url(path/to/external/icon.png) no-repeat;
    padding-left: 10px;
    }

    ReplyDelete