web-dev-qa-db-ja.com

相対URLから絶対URLを取得します。 (IE6の問題)

現在、次の関数を使用して、相対URLを絶対URLに「変換」しています。

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

これはほとんどのブラウザで非常にうまく機能しますが、IE6は相対URLを返すことに固執しています! getAttribute( 'href')を使用する場合も同じです。

IE6から修飾URLを取得できた唯一の方法は、img要素を作成し、 'src'属性をクエリすることです。これに関する問題は、サーバーリクエストを生成することです。避けたいもの。

だから私の質問は次のとおりです。IE6で相対URLから完全修飾URLを取得する方法はありますか(サーバーリクエストなし)。


簡単な正規表現/文字列修正を推奨する前に、それほど単純ではないことを保証します。基本要素+ダブルピリオドの相対URL +他の潜在的な変数のトンは本当にそれを地獄にします!

Regex'yソリューションの巨大なものを作成することなくそれを行う方法がなければなりませんか?

79
James

おかしいですね! IEは、DOMメソッドの代わりにinnerHTMLを使用すると理解できます。

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;
}

少しいですが、Doing It Yourselfよりも簡潔です。

47
bobince

ブラウザが<base>タグを正しく実装している限り、どのブラウザがそうする傾向があります:

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;
}

これを試すことができるjsfiddleを次に示します。 http://jsfiddle.net/ecmanaut/RHdnZ/

27
ecmanaut

要素を複製するだけでIE6で動作させることができます:

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

(IE6およびIE5.5モードでIETesterを使用してテスト済み)

16
Oriol

これで見つけました ブログ @bobinceソリューションのように見える別の方法。

function canonicalize(url) {
    var div = document.createElement('div');
    div.innerHTML = "<a></a>";
    div.firstChild.href = url; // Ensures that the href is properly escaped
    div.innerHTML = div.innerHTML; // Run the current innerHTML back through the parser
    return div.firstChild.href;
}

それほどエレガントではなく、大したことではないことがわかりました。

10

RI.js は問題を解決するようです:

URI("../foobar.html").absoluteTo("http://example.org/hello/world.html").toString()

http://medialize.github.io/URI.js/docs.html#absoluteto も参照してください

IE6ではテストされていませんが、一般的な問題を検索している他のユーザーにとっては役立つかもしれません。

7
koppor

私は実際に、元のドキュメントを(一時的であっても)変更する必要がなく、ブラウザの組み込みURL解析などを使用するアプローチを望んでいました。また、(ecmanaughtの答えのように)自分のベースを提供できるようにしたかった。かなり簡単ですが、createHTMLDocumentを使用します(おそらく、互換性を高めるためにcreateDocumentに置き換えることができます)。

function absolutize(base, url) {
    d = document.implementation.createHTMLDocument();
    b = d.createElement('base');
    d.head.appendChild(b);
    a = d.createElement('a');
    d.body.appendChild(a);
    b.href = base;
    a.href = url;
    return a.href;
}

http://jsfiddle.net/5u6j403k/

7
Chris Hopman

このソリューションは、すべてのブラウザーで機能します。

/**
 * 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

ただし、「../ file.png」のような「..」を含む相対URLはサポートしていません。

5
Feross

これは、基本的な相対URLを解決するために使用する関数です。

function resolveRelative(path, base) {
    // Absolute URL
    if (path.match(/^[a-z]*:\/\//)) {
      return path;
    }
    // Protocol relative URL
    if (path.indexOf("//") === 0) {
      return base.replace(/\/\/.*/, path)
    }
    // Upper directory
    if (path.indexOf("../") === 0) {
        return resolveRelative(path.slice(3), base.replace(/\/[^\/]*$/, ''));
    }
    // Relative to the root
    if (path.indexOf('/') === 0) {
        var match = base.match(/(\w*:\/\/)?[^\/]*\//) || [base];
        return match[0] + path.slice(1);
    }
    //relative to the current directory
    return base.replace(/\/[^\/]*$/, "") + '/' + path.replace(/^\.\//, '');
}

Jsfiddleでテストします: https://jsfiddle.net/n11rg255/

ブラウザとnode.jsまたは他の環境の両方で機能します。

3
lovasoa

アンカーの代わりに画像要素を使用することを提案するこのブログ投稿を見つけました:

http://james.padolsey.com/javascript/getting-a-fully-qualified-url/

これは、IE6でもURLを確実に展開するために機能します。しかし問題は、次の行でsrcをnullに設定しても、イメージのsrc属性を設定すると、テストしたブラウザーがすぐにリソースをダウンロードすることです。

代わりに、bobinceのソリューションを試してみます。

2
Jesse Hallett

urlが '/'で始まらない場合

現在のページのURLを取得し、最後の「/」以降のすべてを切り取ります。次に、相対URLを追加します。

urlが '/'で始まる場合はそれ以外

現在のページのURLを取得し、単一の「/」の右側のすべてを切り取ります。次に、URLを追加します。

urlが#または?で始まる場合はそれ以外

現在のページのURLを取得し、単にurlを追加します


それがあなたのために働くことを願っています

0
geowa4