Getting an absolute URL from a relative one. (IE6

2019-01-03 22:54发布

I'm currently using the following function to 'convert' a relative URL to an absolute one:

function qualifyURL(url) {
    var a = document.createElement('a');
    a.href = url;
    return a.href;
}

This works quite well in most browsers but IE6 insists on returning the relative URL still! It does the same if I use getAttribute('href').

The only way I've been able to get a qualified URL out of IE6 is to create an img element and query it's 'src' attribute - the problem with this is that it generates a server request; something I want to avoid.

So my question is: Is there any way to get a fully qualified URL in IE6 from a relative one (without a server request)?


Before you recommend a quick regex/string fix I assure you it's not that simple. Base elements + double period relative urls + a tonne of other potential variables really make it hell!

There must be a way to do it without having to create a mammoth of a regex'y solution??

11条回答
Lonely孤独者°
2楼-- · 2019-01-03 23:28

This solution works in all browsers.

/**
 * Given a filename for a static resource, returns the resource's absolute
 * URL. Supports file paths with or without origin/protocol.
 */
function toAbsoluteURL (url) {
  // Handle absolute URLs (with protocol-relative prefix)
  // Example: //domain.com/file.png
  if (url.search(/^\/\//) != -1) {
    return window.location.protocol + url
  }

  // Handle absolute URLs (with explicit origin)
  // Example: http://domain.com/file.png
  if (url.search(/:\/\//) != -1) {
    return url
  }

  // Handle absolute URLs (without explicit origin)
  // Example: /file.png
  if (url.search(/^\//) != -1) {
    return window.location.origin + url
  }

  // Handle relative URLs
  // Example: file.png
  var base = window.location.href.match(/(.*\/)/)[0]
  return base + url

However, it doesn't support relative URLs with ".." in them, like "../file.png".

查看更多
萌系小妹纸
3楼-- · 2019-01-03 23:31

If url does not begin with '/'

Take the current page's url, chop off everything past the last '/'; then append the relative url.

Else if url begins with '/'

Take the current page's url and chop off everything to the right of the single '/'; then append the url.

Else if url starts with # or ?

Take the current page's url and simply append url


Hope it works for you

查看更多
等我变得足够好
4楼-- · 2019-01-03 23:31

If it runs in the browser, this sort of works for me..

  function resolveURL(url, base){
    if(/^https?:/.test(url))return url; // url is absolute
    // let's try a simple hack..
    var basea=document.createElement('a'), urla=document.createElement('a');
    basea.href=base, urla.href=url;
    urla.protocol=basea.protocol;// "inherit" the base's protocol and hostname
    if(!/^\/\//.test(url))urla.hostname=basea.hostname; //..hostname only if url is not protocol-relative  though
    if( /^\//.test(url) )return urla.href; // url starts with /, we're done
    var urlparts=url.split(/\//); // create arrays for the url and base directory paths
    var baseparts=basea.pathname.split(/\//); 
    if( ! /\/$/.test(base) )baseparts.pop(); // if base has a file name after last /, pop it off
    while( urlparts[0]=='..' ){baseparts.pop();urlparts.shift();} // remove .. parts from url and corresponding directory levels from base
    urla.pathname=baseparts.join('/')+'/'+urlparts.join('/');
    return urla.href;
  }
查看更多
等我变得足够好
5楼-- · 2019-01-03 23:34

As long as the browser implements the <base> tag correctly, which browsers tend to:

function resolve(url, base_url) {
  var doc      = document
    , old_base = doc.getElementsByTagName('base')[0]
    , old_href = old_base && old_base.href
    , doc_head = doc.head || doc.getElementsByTagName('head')[0]
    , our_base = old_base || doc_head.appendChild(doc.createElement('base'))
    , resolver = doc.createElement('a')
    , resolved_url
    ;
  our_base.href = base_url || '';
  resolver.href = url;
  resolved_url  = resolver.href; // browser magic at work here

  if (old_base) old_base.href = old_href;
  else doc_head.removeChild(our_base);
  return resolved_url;
}

Here's a jsfiddle where you can experiment with it: http://jsfiddle.net/ecmanaut/RHdnZ/

查看更多
Rolldiameter
6楼-- · 2019-01-03 23:38

You can make it work on IE6 just cloning the element:

function qualifyURL(url) {
    var a = document.createElement('a');
    a.href = url;
    return a.cloneNode(false).href;
}

(Tested using IETester on IE6 and IE5.5 modes)

查看更多
叛逆
7楼-- · 2019-01-03 23:41

How strange! IE does, however, understand it when you use innerHTML instead of DOM methods.

function escapeHTML(s) {
    return s.split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;');
}
function qualifyURL(url) {
    var el= document.createElement('div');
    el.innerHTML= '<a href="'+escapeHTML(url)+'">x</a>';
    return el.firstChild.href;
}

A bit ugly, but more concise than Doing It Yourself.

查看更多
登录 后发表回答