Relative to absolute links with JavaScript

I was toying with a completely different thing and specifically a Yahoo service that gives you the ability to use HTML as data and then lets you use xpath to query this data. I came up with a somewhat interesting idea (will post tomorrow, too late now), but all of a sudden I realized I need to convert relative links to absolute ones. I thought it's just a trivial thing (I mean how hard could it be) but then it turns out there are these little edge cases...

Anyway, I came up with something and posting here in case someone else might need it (or even me, for example two years from now. Hmm, will there be URLs in the future, in the distant 2011, or we'll all be just pure non-material consciousness ?)

So, the test page is here

And the actual code (also on github) is as follows:

function toAbs(link, host) {

  var lparts = link.split('/');
  if (/http:|https:|ftp:/.test(lparts[0])) {
    // already abs, return
    return link;
  }

  var i, hparts = host.split('/');
  if (hparts.length > 3) {
    hparts.pop(); // strip trailing thingie, either scriptname or blank 
  }

  if (lparts[0] === '') { // like "/here/dude.png"
    host = hparts[0] + '//' + hparts[2];
    hparts = host.split('/'); // re-split host parts from scheme and domain only
    delete lparts[0];
  }

  for(i = 0; i < lparts.length; i++) {
    if (lparts[i] === '..') {
      // remove the previous dir level, if exists
      if (typeof lparts[i - 1] !== 'undefined') {
        delete lparts[i - 1];
      } else if (hparts.length > 3) { // at least leave scheme and domain
        hparts.pop(); // stip one dir off the host for each /../
      }
      delete lparts[i];
    }
    if(lparts[i] === '.') {
      delete lparts[i];
    }
  }

  // remove deleted
  var newlinkparts = [];
  for (i = 0; i < lparts.length; i++) {
    if (typeof lparts[i] !== 'undefined') {
      newlinkparts[newlinkparts.length] = lparts[i];
    }
  }

  return hparts.join('/') + '/' + newlinkparts.join('/');

}

Update: added a check for ./ in the URLs thanks to QA from Boštjan

This entry was posted on Tuesday, March 17th, 2009 and is filed under JavaScript. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.


Get notification for future posts: follow me on Twitter or subscribe to my RSS feed

3 Responses to “Relative to absolute links with JavaScript”

  1. Boštjan Says:

    What about “./” links (e.g. ./news.html)?

  2. Stoyan Says:

    Thanks, Boštjan, forgot about those, now updated the code, basically just ignoring these.

  3. Nidhi Says:

    Hi Stoyan Stefanov,

    This may not be the correct place for this question but I would like to know if you have any solution for this problem

    I would like to download JavaScript file without blocking on load event in Firefox:

    I am making a dynamic script call to load some extenal JS before window’s onload event. Here is the sample code.

    var temp = document.createElement(‘script’);
    temp.type = ‘text/javascript’;
    temp.async = temp.defer= true;
    temp.src = “http://stevesouders.com/efws/iframe-empty.php?t==”;
    window.setTimeout(function(){document.getElementsByTagName(‘head’)[0].appendChild(temp)},0);

    This code is perfectly working on IE (Window onload event is not waiting for dynamic script resource download). However it’s not working on Firefox. Window onload event is waiting for the dynamic script resource download.

    Are there any workarounds for this issue. You can use http://nidhisekhar.com/samples/async_script_call_settimeout.html link to see the behavior on IE and Firefox. I appreciate your help.

    Thanks

Leave a Reply