Получение абсолютного URL-адреса от относительного. (Проблема IE6)
В настоящее время я использую следующую функцию для "конвертации" относительного URL в абсолютный:
function qualifyURL(url) {
var a = document.createElement('a');
a.href = url;
return a.href;
}
Это работает очень хорошо в большинстве браузеров, но IE6 настаивает на возврате относительного URL-адреса еще! Он делает то же самое, если я использую getAttribute ('href').
Единственный способ получить URL-адрес из IE6 - создать элемент img и запросить атрибут 'src' - проблема заключается в том, что он генерирует запрос сервера; чего я хочу избежать.
Итак, мой вопрос: есть ли способ получить полный URL-адрес в IE6 из относительного (без запроса сервера)?
Прежде чем рекомендовать быстрое исправление регулярных выражений/строк, я заверяю вас, что это не так просто. Базовые элементы + двойные относительные относительные URL + тонна других потенциальных переменных действительно делают это ад!
Должен быть способ сделать это, не создавая мамонта решения регулярного выражения
Ответы
Ответ 1
Как странно! Однако IE это понимает, когда вы используете innerHTML вместо методов DOM.
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;
}
Немного уродливый, но более краткий, чем Doing It Yourself.
Ответ 2
Пока браузер реализует <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/
Ответ 3
Вы можете заставить его работать с IE6, просто клонируя элемент:
function qualifyURL(url) {
var a = document.createElement('a');
a.href = url;
return a.cloneNode(false).href;
}
(Протестировано с использованием IETester в режимах IE6 и IE5.5)
Ответ 4
Я нашел в этом 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;
}
Я нашел его немного более элегантным, а не большим.
Ответ 5
URI.js, похоже, решает проблему:
URI("../foobar.html").absoluteTo("http://example.org/hello/world.html").toString()
См. также http://medialize.github.io/URI.js/docs.html#absoluteto
Не тестируется с IE6, но может быть полезно для других, которые ищут общую проблему.
Ответ 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/
Ответ 7
Это решение работает во всех браузерах.
/**
* Given a filename for a static resource, returns the resource 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
Это функция, которую я использую для определения основных относительных 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 или в других средах.
Ответ 9
Я нашел этот пост в блоге, который предлагает использовать элемент изображения вместо якоря:
http://james.padolsey.com/javascript/getting-a-fully-qualified-url/
Это работает над надежным расширением URL-адреса даже в IE6. Но проблема в том, что браузеры, которые я тестировал, будут немедленно загружать ресурс при установке атрибута src изображения, даже если вы установите для src значение null на следующей строке.
Я собираюсь дать решение bobince вместо этого.
Ответ 10
Если url
не начинается с '/'
Возьмите текущий URL страницы, отрубите все, что прошло мимо последнего '/'; затем добавьте относительный URL.
Иначе, если url
начинается с '/'
Возьмите текущий URL-адрес страницы и отрубите все справа от сингла '/'; затем добавьте URL-адрес.
В противном случае, если url
начинается С# или?
Возьмите текущий URL-адрес страницы и просто добавьте url
Надеюсь, что это сработает для вас.
Ответ 11
Если он работает в браузере, для меня это работает.
function resolveURL(url, base){
if(/^https?:/.test(url))return url; // url is absolute
// let 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 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;
}