Targeting External Links Intelligently

This is an exclusive guest post by , posted on January 20th, 2009.

In the beginning…

[ Young Planet Earth ] In the time of the dinosaurs, HTML authors controlled the way anchors opened by adding target="_blank" as an attribute on an anchor tag. Then the molten mass of Internet began to cool into the thin crust of Web 2.0, the continents began to separate and there came a great migration of pages from HTML to the shinier, new XHTML. Most authors didn’t know what that meant, but it had an “X” in it, so it must be cool, they thought.

Alas, there came a great despair as the beloved target="_blank" attribute was no longer looked kindly upon by The Great Validator. The new XHTML pages would not wear the Shiny Badge of Validation Love.

Designers, developers and former blink taggers mourned the passing of new windows and slogged on, heads hung low… until March 4th, 2003. On that day, Kevin Yank of SitePoint.com delivered the news that one could use JavaScript to code target="_blank" on all anchors upon which one had set the rel="external" attribute after the pages had loaded. The pages would receive the much sought after blessing of The Great Validator and anchors could open new windows without extensive JavaScripting.

Oh, how the authors rejoiced in the discovery of this new treasure. Then came the Great Usurpers: User Experience Advocates who said, “Thine actions shall bring about the decline of the Great Internet. The choice of _Blank and _Self belongs to the Almighty User.” Once again, a wave of sorrow swept the Internet.

…until today.

The New Internet

Website designers and developers have a great many tools at their disposal these days. Like power tools, these things can help or hurt us. In theory, the idea of opening external links in a new window sounds very sane. If everybody used it this idea intelligently, it would be, well, smart.

In fact, I’m surprised my browser doesn’t allow me to specify what to do with links that take me to a different domain. It seems like a reasonable enough expectation.

Moving along, since there’s already scripts out there which set the target attribute to “_blank” and authors who’ve written the tutorials already, so I’ll just get to the point of this script and why it’s different.

Here’s the list of goals and requirements I used in writing this script:

  • Easy – I didn’t want to have to ever touch it again, even to configure it with defaults. I just wanted to include it on the page and be done with it.
  • Easier – I didn’t want to have to set rel="external" on anything. I figured the script should be smart enough to determine if a link is external or interal by comparing the domain of the site with the href of the anchor.
  • Accessible – The user needed to be able to silence it, and at worse, choose the course of action when an external link was encountered.

I used jQuery as the base library, but obviously it could be easily translated to another library or to library independence.

Stay on target… stay on target…

Having stalled long enough, and with no further ado, 40 lines of “anchor targeted window scripting” bliss (with attached line-by-line description):

(function(){
  var extAnchorTarget = function () {
    var msgtxt = null, usropt = null, askopt = null;
    msgtxt = "Click OK to open this link in a new window "
           + "or cancel to open it in this window.";
    usropt = $(":radio:checked[name=extwinopt]").val() || 0;
    usropt = parseInt(usropt);
    switch (usropt) {
      case 2:
        this.target = "_blank";
      break;
      case 1:
        this.target = "_self";
      break;
      case 0:
      default:
        askopt = confirm(msgtxt);
        this.target = !askopt ? "_self" : "_blank";
      break;
    }
    return true;
  };
  var labelAnchors = function () {
    var winhome = document.domain.split(".").reverse();
        winhome = winhome[1]+"."+winhome[0];
    $("a").each(function(i){
      var lnkhome = this.href.split("/")[2].split(".").reverse();
          lnkhome = lnkhome[1]+"."+lnkhome[0];
      if (!winhome.match(lnkhome)) {
        $(this).addClass("external");
        $(this).click(extAnchorTarget);
      } else {
        $(this).addClass("internal");
      }
    });
  };
  $(function(){
    labelAnchors();
  });
})();

If you’re using jQuery on your site already, just load this script and all of your target="blank"-anchors-opening-in-new-windows dreams will come true.

Ultimately, this script would be integrated with two additional features:

  • Modals – At the moment, this script relies on the browser confirm function which is a bit ugly and klunky. A polished modal window that would appear as needed would make this the real deal.
  • Cookies – Having integrated a lovely modal widget, we should store the user’s preference to prevent our script from bugging them.

You’ll notice that on Line 6, the script is looking for a form value which contains the user options. While it will silently default to asking the user, this would ultimately be the place where we might also check for a cookie value.

The demo (written in shiny XHTML 1.1 Strict) includes a form which works, but which is obviously reset every time the page is loaded. This would be a problem for a website without a cookie solution, though it’s less apparent in the single page demo.

This script now has the potential to fill the requirements outlined above. It performs its own domain to href comparison, so I could throw it right into an application. I don’t have to set additional values on any attributes, though there’s probably some good reason I should be adding rel="external" to off-site links anyway. It contains a built-in mechanism for asking the user, rather than simply forcing the user to open a new window.

Wrapping Up…

So there you have it. Now go forth and please The Great Validator and The Great Usurpers. Much thanks to Kevin Yank of SitePoint.com for his original article and to Jeff Starr of Perishable Press for hosting this one. Also, a huge thank you to all User Experience Experts and Advocates for unwittingly and unfairly playing the role of the villain in my little story. I hope you’ll forgive my having a little fun at your expense and not rush out to buy a Bill Brown voodoo doll.