qualifyHREF

6th January 2009

This script takes a relative path, such as the href attribute of a link, and converts it into a fully-qualified URL. The conversion is based by default on the address of the current page, but it can also work with a context defined by a <base> element, or the location of another resource, such as the document in an <iframe>.

The script comes in particularly useful for normalizing the difference in href and src values between Internet Explorer and other browsers, as discussed in a blog post I wrote for SitePoint, Dealing with unqualified HREF values

Get the script

Download the zipfile [1K] and unzip it into your site directory, then you can either include the script on your page as it is:

<script type="text/javascript" src="qualifyhref.js"></script>

or copy the code into another script, and work with it from there:

//QH1.0 :: qualifyHREF by brothercake - http://www.brothercake.com/

//qualify an HREF to form a complete URI
function qualifyHREF(href, context)
{
    //get the current document location href
    var here = document.location.href;

    //look for a base element to use instead
    var bases = document.getElementsByTagName('base');
    if(bases.length > 0)
    {
        var basehref = bases[0].getAttribute('href');
        if(basehref && basehref != '')
        {
            here = basehref;
        }
    }

    //if the context argument is present and non-empty string, use that instead
    if(typeof context == 'string' && context != '')
    {
        here = context;
    }

    //extract the protocol, host and path
    //and create a location object with the data
    var parts = here.replace('//', '/').split('/');
    var loc = {
        'protocol' : parts[0],
        'host' : parts[1]
        }
    parts.splice(0, 2);
    loc.pathname = '/' + parts.join('/');

    //build a base URI from the protocol plus host (which includes port if applicable)
    var uri = loc.protocol + '//' + loc.host;

    //if the input path is relative-from-here
    //just delete the ./ token to make it relative
    if(/^(\.\/)([^\/]?)/.test(href))
    {
        href = href.replace(/^(\.\/)([^\/]?)/, '$2');
    }

    //if the input href is already qualified, copy it unchanged
    if(/^([a-z]+)\:\/\//.test(href))
    {
        uri = href;
    }

    //or if the input href begins with a leading slash, then it's base relative
    //so just add the input href to the base URI
    else if(href.substr(0, 1) == '/')
    {
        uri += href;
    }

    //or if it's an up-reference we need to compute the path
    else if(/^((\.\.\/)+)([^\/].*$)/.test(href))
    {
        //get the last part of the path, minus up-references
        var lastpath = href.match(/^((\.\.\/)+)([^\/].*$)/);
        lastpath = lastpath[lastpath.length - 1];

        //count the number of up-references
        var references = href.split('../').length - 1;

        //get the path parts and delete the last one (this page or directory)
        var parts = loc.pathname.split('/');
        parts = parts.splice(0, parts.length - 1);

        //for each of the up-references, delete the last part of the path
        for(var i=0; i<references; i++)
        {
            parts = parts.splice(0, parts.length - 1);
        }

        //now rebuild the path
        var path = '';
        for(i=0; i<parts.length; i++)
        {
            if(parts[i] != '')
            {
                path += '/' + parts[i];
            }
        }
        path += '/';

        //and add the last part of the path
        path += lastpath;

        //then add the path and input href to the base URI
        uri += path;
    }

    //otherwise it's a relative path,
    else
    {
        //calculate the path to this directory
        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 += '/';

        //then add the path and input href to the base URI
        uri += path + href;
    }

    //return the final uri
    return uri;
}

Once it's in your codebase you can call it as required, storing the value it returns for further use, for example:

var src = '/images/pants.png';

var uri = qualifyHREF(src);

alert(uri);        //would alert "http://www.brothercake.com/images/pants.png"

In that example, the location of this page is used as the context for creating a qualified URL. However we could also pass in an explicit context, such as the location of an <iframe> document:

var uri = qualifyHREF(src, document.frames['myIframe'].location.href);

Get the script

BSD License → Terms of use

Categories...

Components

Website gadgets

Bits of site functionality:

Usability widgets

Local network apps

Web-applications for your home or office network:

Game and novelties

Our internal search engine is currently offline, undergoing some configuration changes in preparation for a major site overhaul. In the meantime, you can still search this site using Google Custom Search.


In this area

Main areas


[brothercake] a round peg in a square hole, that still fits