Obecnie używam następującej funkcji, aby „przekonwertować” względny adres URL na bezwzględny:
function qualifyURL(url) {
var a = document.createElement('a');
a.href = url;
return a.href;
}
Działa to całkiem dobrze w większości przeglądarek, ale IE6 nadal nalega na zwracanie względnego adresu URL! Robi to samo, jeśli używam getAttribute („href”).
Jedynym sposobem, w jaki mogłem uzyskać kwalifikowany adres URL z IE6, jest utworzenie elementu img i wysłanie zapytania o jego atrybut „src” - problem polega na tym, że generuje on żądanie serwera; coś, czego chcę uniknąć.
Moje pytanie brzmi: czy istnieje sposób na uzyskanie w pełni kwalifikowanego adresu URL w IE6 z adresu względnego (bez żądania serwera)?
Zanim polecisz szybką naprawę wyrażeń regularnych / ciągów, zapewniam, że nie jest to takie proste. Elementy bazowe + względne adresy URL z podwójnymi okresami + mnóstwo innych potencjalnych zmiennych to naprawdę piekło!
Musi istnieć sposób, aby to zrobić bez konieczności tworzenia gigantycznego rozwiązania regex'y?
Odpowiedzi:
Jak dziwnie! IE rozumie to jednak, kiedy używasz innerHTML zamiast metod 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; }
Trochę brzydkie, ale bardziej zwięzłe niż Zrób to sam.
źródło
O ile przeglądarka prawidłowo implementuje tag <base>, które przeglądarki zazwyczaj:
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; }
Oto jsfiddle, w którym możesz poeksperymentować: http://jsfiddle.net/ecmanaut/RHdnZ/
źródło
base_url
parametru, więc staje się onundefined
i jest do niego przypisywany"undefined"
. Zamiast tego należy przekazać pusty ciąg. Lub, jeśli chcesz, aby drugi parametr był opcjonalny, użyjour_base.href = base_url || ""
zamiastour_base.href = base_url
…Możesz sprawić, by działało w IE6, po prostu sklonując element:
function qualifyURL(url) { var a = document.createElement('a'); a.href = url; return a.cloneNode(false).href; }
(Testowane przy użyciu IETester w trybach IE6 i IE5.5)
źródło
Znalazłem na tym blogu inną metodę, która naprawdę wygląda jak rozwiązanie @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; }
Wydało mi się to trochę bardziej eleganckie, nic wielkiego.
źródło
Wydaje się, że URI.js rozwiązuje problem:
URI("../foobar.html").absoluteTo("http://example.org/hello/world.html").toString()
Zobacz także http://medialize.github.io/URI.js/docs.html#absoluteto
Nie testowane z IE6, ale może być pomocne dla innych szukających informacji o ogólnym problemie.
źródło
npm install URIjs
, a nie inna biblioteka o podobnej nazwieurijs
github.com/medialize/URI.js#using-urijsWłaściwie chciałem podejścia do tego, które nie wymagałoby modyfikowania oryginalnego dokumentu (nawet nie tymczasowo), ale nadal korzystałem z wbudowanego analizowania adresów URL przeglądarki i tym podobnych. Chciałem też móc zapewnić własną bazę (na przykład odpowiedź ecmanaught). Jest to raczej proste, ale używa createHTMLDocument (może być zastąpione przez createDocument, aby być nieco bardziej kompatybilnym):
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/
źródło
document.implementation.createHTMLDocument
$("#loadedHere").createElement("a").url="foo"
skutkowało pustym adresem URL, więc musiałem uciec się do stworzenia osobnego dokumentu.To rozwiązanie działa we wszystkich przeglądarkach.
/** * 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
Jednak nie obsługuje względnych adresów URL zawierających „..”, np. „../File.png”.
źródło
/img/profile.php?url=https://google.com/logo.svg
.Oto funkcja, której używam do rozwiązywania podstawowych względnych adresów 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(/^\.\//, ''); }
Przetestuj na jsfiddle: https://jsfiddle.net/n11rg255/
Działa zarówno w przeglądarce, jak iw node.js lub w innych środowiskach.
źródło
Znalazłem ten post na blogu, który sugeruje użycie elementu obrazu zamiast kotwicy:
http://james.padolsey.com/javascript/getting-a-fully-qualified-url/
Działa to w celu niezawodnego rozwinięcia adresu URL, nawet w IE6. Problem polega jednak na tym, że testowane przeze mnie przeglądarki natychmiast pobierają zasób po ustawieniu atrybutu src obrazu - nawet jeśli ustawisz src na null w następnym wierszu.
Zamiast tego spróbuję zastosować rozwiązanie Bobince'a.
źródło
Gdyby
url
nie zaczyna się od „/”Weź adres URL bieżącej strony, odetnij wszystko poza ostatnim „/”; następnie dołącz względny adres URL.
W przeciwnym razie, jeśli
url
zaczyna się od „/”Weź adres URL bieżącej strony i odetnij wszystko na prawo od pojedynczego znaku „/”; następnie dołącz adres URL.
W przeciwnym razie, jeśli
url
zaczyna się od # lub?Wybierz adres URL bieżącej strony i po prostu dołącz
url
Mam nadzieję, że to działa dla Ciebie
źródło
Jeśli działa w przeglądarce, to działa dla mnie ...
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; }
źródło