External Link Indicator for SharePoint Pages Using JavaScript

Many so-called Web 2.0 sites show a little icon for any links which send you out of their purview to another site.  This is a nice thing to do within SharePoint as well.  You can easily make this happen without users needing to take any action by adding some JavaScript into your master page.

I got the basics for this from a post entitled Useful Links with JavaScript by Toby Somerville over at SitePoint.  Also check out his http://ikonize.com/ site for examples.  Thanks to Toby for the approach and the parseURL and the qualifyHREF functions.

What the JavaScript below does is look for all of the links within the main content pane of SharePoint pages (the table with the id=”MSO_ContentTable”) and add the ExternalLink CSS class to them if they lead outside the current server context.  I wanted to limit things to the main content pane for several reasons. First, there may be links in other parts of the page that we just don’t want to make look different (e.g., the footer), and secondly, in MOSS the My Site link at the top of the page takes you to a different Web App, and I didn’t want to show the external link icon there.  Obviously, you can adapt the JavaScript based on what you’d like to do.  I built this for use with a master page in MOSS that is based on default.master with minimal customization.

First, put the JavaScript below into a file somewhere in your Site Collection (I always create a Document Library called JavaScript in the root site of the Site Collection) and then add a script line into the <HEAD> section of your master page:

<script language="javascript" type="text/javascript" src="/JavaScript/ExternalLinks.js"></script>

Then call the StyleExternalLinks() function in the onload event of the <BODY>:

<BODY scroll="yes" onload="javascript:if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();StyleExternalLinks();">

In my custom CSS, I’ve added a new class called ExternalLink, defined as follows:

a.ExternalLink {
  background-image:url('/SiteCollectionImages/ExternalLink.jpg');
  background-repeat:no-repeat;
  background-position:right top;
  padding-right:15px;
}

You could pretty easily expand the JavaScript below to highlight other link types as well, but my focus was on external links:

// Sets a class to all external links
function StyleExternalLinks() {
    thisHost = parseURL(qualifyHREF(document.location.href)).hostname;
    tables = document.getElementsByTagName(“TABLE”);

    for (i = 0; i < tables.length; i++) {         // Only apply external link icon for links in the main pane         if (tables[i].id == "MSO_ContentTable") {          anchors = tables[i].getElementsByTagName("A");             for (a = 0; a < anchors.length; a++) {                 thisLinkHost = parseURL(qualifyHREF(anchors[a].href)).hostname;                 if (thisLinkHost != thisHost) {                     anchors[a].className += "ExternalLink";                 }             }             // Since this is the main pane, we're done             return;         }     } }     //parse a URL to form an object of properties     function parseURL(url){         var loc = {             'href': url         };         var parts = url.replace('//', '/').split('/');         loc.protocol = parts[0];         loc.host = parts[1];         parts[1] = parts[1].split(':');         loc.hostname = parts[1][0];         loc.port = parts[1].length > 1 ? parts[1][1] : ”;
        parts.splice(0, 2);
        loc.pathname = ‘/’ + parts.join(‘/’);
        loc.pathname = loc.pathname.split(‘#’);
        loc.hash = loc.pathname.length > 1 ? ‘#’ + loc.pathname[1] : ”;
        loc.pathname = loc.pathname[0];
        loc.pathname = loc.pathname.split(‘?’);
        loc.search = loc.pathname.length > 1 ? ‘?’ + loc.pathname[1] : ”;
        loc.pathname = loc.pathname[0];
        var dotty = loc.pathname.split(‘.’);
        if (dotty.length > 1) {
            loc.extension = dotty[(dotty.length – 1)];
        }
        else {
            loc.extension = ”;
        }
        return loc;
    }
    //qualify an HREF to form a complete URI
    function qualifyHREF(href, context){
        var here = document.location.href;
        var bases = document.getElementsByTagName(‘base’);
        if (bases.length > 0) {
            var basehref = bases[0].getAttribute(‘href’);
            if (basehref && basehref != ”) {
                here = basehref;
            }
        }
        if (typeof context == ‘string’ && context != ”) {
            here = context;
        }
        var parts = here.replace(‘//’, ‘/’).split(‘/’);
        var loc = {
            ‘protocol’: parts[0],
            ‘host’: parts[1]
        }
        parts.splice(0, 2);
        loc.pathname = ‘/’ + parts.join(‘/’);
        var uri = loc.protocol + ‘//’ + loc.host;
        if (/^(\.\/)([^\/]?)/.test(href)) {
            href = href.replace(/^(\.\/)([^\/]?)/, ‘$2’);
        }
        if (/^([a-z]+)\:\/\//.test(href)) {
            uri = href;
        }
        else
            if (href.substr(0, 1) == ‘/’) {
                uri += href;
            }
            else
                if (/^((\.\.\/)+)([^\/].*$)/.test(href)) {
                    var lastpath = href.match(/^((\.\.\/)+)([^\/].*$)/);
                    lastpath = lastpath[lastpath.length – 1];
                    var references = href.split(‘../’).length – 1;
                    var parts = loc.pathname.split(‘/’);
                    parts = parts.splice(0, parts.length – 1);
                    for (var i = 0; i < references; i++) {                         parts = parts.splice(0, parts.length - 1);                     }                     var path = '';                     for (i = 0; i < parts.length; i++) {                         if (parts[i] != '') {                             path += '/' + parts[i];                         }                     }                     path += '/';                     path += lastpath;                     uri += path;                 }                 else {                     path = '';                     parts = loc.pathname.split('/');                     parts = parts.splice(0, parts.length - 1);                     for (var i = 0; i < parts.length; i++) {                         if (parts[i] != '') {                             path += '/' + parts[i];                         }                     }                     path += '/';                     uri += path + href;                 }         return uri;     }[/sourcecode]