我目前正在使用以下函数将相对网址“转换”为绝对网址:
function qualifyURL(url) {
var a = document.createElement('a');
a.href = url;
return a.href;
}
这在大多数浏览器中运行良好,但IE6坚持仍然返回相对URL!如果我使用getAttribute('href'),它也会这样做。
我能够从IE6中获取合格的URL的唯一方法是创建一个img元素并查询它的'src'属性 - 这个问题是它生成一个服务器请求;我想避免的事情。
所以我的问题是:有没有办法从IE6中获取完全限定的URL(没有服务器请求)?
在您推荐快速正则表达式/字符串修复之前,我向您保证并非如此简单。基本元素+双周期相对网址+一吨其他潜在变量真的让它变得地狱!
必须有办法做到这一点,而不必创建一个正则表达式的解决方案?
答案 0 :(得分:47)
function escapeHTML(s) {
return s.split('&').join('&').split('<').join('<').split('"').join('"');
}
function qualifyURL(url) {
var el= document.createElement('div');
el.innerHTML= '<a href="'+escapeHTML(url)+'">x</a>';
return el.firstChild.href;
}
有点难看,但比自己动手更简洁。
答案 1 :(得分:27)
只要浏览器实现&lt; base&gt;标记正确,哪些浏览器倾向于:
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/
答案 2 :(得分:15)
你可以在IE6上使用它来克隆元素:
function qualifyURL(url) {
var a = document.createElement('a');
a.href = url;
return a.cloneNode(false).href;
}
(在IE6和IE5.5模式下使用IETester测试)
答案 3 :(得分:10)
我在这个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;
}
我发现它更优雅,没什么大不了的。
答案 4 :(得分:7)
URI.js似乎解决了这个问题:
URI("../foobar.html").absoluteTo("http://example.org/hello/world.html").toString()
另见http://medialize.github.io/URI.js/docs.html#absoluteto
没有使用IE6进行测试,但对于搜索一般问题的其他人可能会有帮助。
答案 5 :(得分:7)
我实际上想要一种方法,不需要修改原始文档(甚至不是暂时的),但仍然使用浏览器的内置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;
}
答案 6 :(得分: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
但是,它不支持带有“..”的相对网址,例如“../ file.png”。
答案 7 :(得分:3)
这是我用来解析基本相对网址的功能:
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或其他环境。
答案 8 :(得分:2)
我发现这篇博文建议使用图片元素而不是锚点:
http://james.padolsey.com/javascript/getting-a-fully-qualified-url/
即使在IE6中也可以可靠地扩展URL。但问题是我测试的浏览器会在设置图像src属性时立即下载资源 - 即使你在下一行将src设置为null。
我将把bobince的解决方案改为。
答案 9 :(得分:0)
如果url
未以'/'
获取当前页面的网址,切断最后一个'/'后的所有内容;然后追加相对网址。
如果url
以'/'
获取当前页面的网址并删除单个'/'右侧的所有内容;然后附上网址。
如果url
以#或?
获取当前页面的网址,只需添加url
希望它适合你
答案 10 :(得分:-1)
如果它在浏览器中运行,这种方式对我有用..
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;
}