2009-01-22 91 views
74

我目前使用下面的函數來「轉換」相對URL,以絕對的:從相關網址獲取絕對網址。 (IE6的問題)

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 +一噸其他潛在變量真的讓它變得糟糕!

必須有辦法做到這一點,而不必創建一個regex'y解決方案的龐然大物?

+8

甜蜜的黑客!不關心IE6。節省了我的時間。你搖滾。 – 2012-02-14 16:03:46

+1

您可以使用[js-uri](http://code.google.com/p/js-uri/)將相對URI解析爲絕對URI。 – Gumbo 2009-01-22 21:58:12

+0

謝謝Gumbo,我想這是必須要做的。我會喜歡更簡潔的解決方案,但無論如何感謝你,我從來不知道這個js-uri課程存在! – James 2009-01-23 08:15:53

回答

0

如果url不以「/」

以當前頁面的URL,砍掉一切都會過去的最後一個「/」開始;然後追加相關的網址。

不然,如果url開始「/」

以當前頁面的URL,一切都砍下來的單「/」的權利;然後附加URL。

否則,如果url以#或?開頭,

以當前頁面的網址,只需追加url


希望它爲你工作

+2

您忘記了URL可以以「//」開頭,這使得它們與方案相關。 //foo.com/bar/ – 2010-03-07 06:19:54

+1

你也忘了虛線的相對../../語法(這個省略是否重要取決於輸出是什麼) – hallvors 2012-12-05 11:14:20

46

真奇怪!然而,當你使用innerHTML而不是DOM方法時,IE會理解它。

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

有點醜,但比做自己更簡潔。

+1

這種方法對我來說很好用!感謝您發佈它! – zachleat 2009-10-19 20:09:46

2

我發現,建議使用的圖像元素,而不是一個錨的這篇博客文章:這一工程能夠可靠地擴展URL

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

,甚至在IE6。但問題是我測試過的瀏覽器會立即下載資源設置圖像的src屬性 - 即使您在下一行將src設置爲null。

我打算讓bobince的解決方案代之。

27

只要瀏覽器>標籤正確地實現了<基地,瀏覽器傾向於:

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/

0

如果在瀏覽器中運行,這種作品適合我...

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

此解決方案適用於所有瀏覽器。

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

但是,它不支持帶「..」的相對URL,比如「../file.png」。

8

我發現在這個blog另一種看起來像@ 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; 
} 

我發現它更優雅一點,沒什麼大不了的。

12

你可以把它在IE6只是克隆的單元工作:

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

(對IE6和IE5.5模式使用IETester測試)

3

這是我用來解決基本功能相對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或其他環境中運行。

6

我其實想要一個不需要修改原始文件(甚至暫時)但仍然使用瀏覽器的內置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/