var clickHandler = function() {
    /**
     *  Attach an event handler to an event, crossbrowser
     *  @param  HtmlDomElement  element
     *  @param  string          event to listen to
     *  @param  function        function to execute
     */
    var addEvent = function(element, name, func)
    {
        // this might be a browser or could be IE
        if (window.addEventListener || document.addEventListener) element.addEventListener(name, func, true);
        else if (window.attachEvent) element.attachEvent('on'+name, func);
    }

    /**
     *  Initialize the click registration system
     */
    var initialize = function()
    {
        // Get all aTags
        var aTags = document.getElementsByTagName("a");

        // regex to test for valid hyperlink
        var protocol = new RegExp('^https?:\\/\\/');

        // get the length
        var length = aTags.length;
        
        // and attach a handler to each of them
        for (var i = 0; i < length; i++) 
        {
            // Get the tag
            var tag = aTags.item(i);
            
            // does this tag have a valid hyperlink
            if (!tag.href || tag.href.length == 0) continue;

            // is it a http:// or https:// link
            if (!protocol.test(tag.href)) continue;
            
            // everything is fine register the event
            addEvent(tag, 'mouseout', restoreHref);
            addEvent(tag, 'mousedown', registerClick);
        }
    }

    /**
     *  Check if a link is a local anchor
     *  @param  string  the url to check
     *  @return boolean is the url local
     */
    var isLocalAnchor = function(url)
    {
        // location of anchor sign in string
        var anchor;

        // locate the anchor sign in the url
        if ((anchor = url.indexOf('#')) == -1) return false;

        // strip the anchor part
        url = url.substring(0, anchor);

        if ((anchor = window.location.href.indexOf('#')) == -1) return url = window.location.href;
        else return url = window.location.href.substring(0, anchor);
    }

    /**
     *  Register a click on a hyperlink
     *  @param  HtmlEvent   event object
     */
    var registerClick = function(event)
    {
        // get the target
        var linkElement = typeof event.currentTarget == 'object' ? event.currentTarget : event.srcElement;

        // Get the body tag for later comparison
        var body = document.getElementsByTagName('body').item(0);
        
        // Make sure we have the right element
        while (linkElement.nodeName.toLowerCase() != 'a')
        {
            // get the parent node
            linkElement = linkElement.parentNode;
            
            // is this the body, then return
            if (linkElement === body) return;
        }
        
        // if the target is local, don't mess with it
        if (isLocalAnchor(linkElement.href)) return;

        // prevent default action from being executed
        if (typeof event.preventDefault == 'function') event.preventDefault();
        else event.returnValue = false;

        // get the link identifier and original url
        var linkID = encodeURIComponent(linkElement.rev ? linkElement.rev : linkElement.href);
        var original = encodeURIComponent(linkElement.href);
        
        // construct the url
        var url = '?registerClick='+linkID+'&document='+documentIdentifier+'&url='+original;
        
        // store the original href
        linkElement.oldHref = linkElement.href;
        
        // set the new href
        linkElement.href = url;
    }
    
    /**
     *  Restore the original href of a hyperlink
     *  @param  HtmlEvent   event object
     */
    var restoreHref = function(event)
    {
        // get the target
        var linkElement = typeof event.currentTarget == 'object' ? event.currentTarget : event.srcElement;
        
        // Get the body tag for later comparison
        var body = document.getElementsByTagName('body').item(0);
        
        // Make sure we have the right element
        while (linkElement.nodeName.toLowerCase() != 'a')
        {
            // get the parent node
            linkElement = linkElement.parentNode;
            
            // is this the body, then return
            if (linkElement === body) return;
        }
        
        // check if the oldhref exists
        if (typeof linkElement.oldHref == 'undefined') return;
        
        // reset the oldhref
        linkElement.href = linkElement.oldHref;
    }

    /**
     * Initialize the clickHandler
     */
    initialize();
}();

