J'utilise actuellement la fonction suivante pour "convertir" une URL relative en URL absolue:
function qualifyURL(url) {
var a = document.createElement('a');
a.href = url;
return a.href;
}
Cela fonctionne assez bien dans la plupart des navigateurs, mais IE6 insiste pour renvoyer toujours l'URL relative! Il en va de même si j'utilise getAttribute ('href').
La seule façon dont j'ai pu obtenir une URL qualifiée à partir d'IE6 est de créer un élément img et d'interroger son attribut 'src' - le problème avec cela est qu'il génère une requête serveur; quelque chose que je veux éviter.
Ma question est donc la suivante: existe-t-il un moyen d'obtenir une URL complète dans IE6 à partir d'une URL relative (sans demande de serveur)?
Avant de recommander une correction rapide de regex/chaîne, je vous assure que ce n'est pas si simple. Éléments de base + URL relatives à double période + une tonne d'autres variables potentielles en font vraiment l'enfer!
Il doit y avoir un moyen de le faire sans avoir à créer un mammouth d'une solution regex'y ??
Comme c'est étrange! IE le comprend cependant lorsque vous utilisez innerHTML au lieu des méthodes 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;
}
Un peu moche, mais plus concis que Doing It Yourself.
Tant que le navigateur implémente correctement la balise <base>, les navigateurs ont tendance à:
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;
}
Voici un jsfiddle où vous pouvez l'expérimenter: http://jsfiddle.net/ecmanaut/RHdnZ/
Vous pouvez le faire fonctionner sur IE6 en clonant simplement l'élément:
function qualifyURL(url) {
var a = document.createElement('a');
a.href = url;
return a.cloneNode(false).href;
}
(Testé en utilisant IETester sur les modes IE6 et IE5.5)
J'ai trouvé sur ce blog une autre méthode qui ressemble vraiment à la solution @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;
}
Je l'ai trouvé un peu plus élégant, pas un gros problème.
RI.js semble résoudre le problème:
URI("../foobar.html").absoluteTo("http://example.org/hello/world.html").toString()
Voir aussi http://medialize.github.io/URI.js/docs.html#absoluteto
Pas testeed avec IE6, mais peut-être utile pour ceux qui recherchent le problème général.
En fait, je voulais une approche qui n'ait pas nécessité de modifier le document d'origine (même pas temporairement) mais qui utilisait toujours l'analyse syntaxique des URL du navigateur, etc. De plus, je voulais pouvoir fournir ma propre base (comme la réponse d'ecmanaught). C'est assez simple, mais utilise createHTMLDocument (pourrait être remplacé par createDocument pour être un peu plus compatible éventuellement):
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;
}
Cette solution fonctionne dans tous les navigateurs.
/**
* 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
Cependant, il ne prend pas en charge les URL relatives contenant "..", comme "../file.png".
Voici la fonction que j'utilise pour résoudre les URL relatives de base:
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(/^\.\//, '');
}
Testez-le sur jsfiddle: https://jsfiddle.net/n11rg255/
Il fonctionne à la fois dans le navigateur et dans node.js ou d'autres environnements.
J'ai trouvé ce billet de blog qui suggère d'utiliser un élément d'image au lieu d'une ancre:
http://james.padolsey.com/javascript/getting-a-fully-qualified-url/
Cela fonctionne pour développer une URL de manière fiable, même dans IE6. Mais le problème est que les navigateurs que j'ai testés téléchargeront immédiatement la ressource lors de la définition de l'attribut src image - même si vous définissez src sur null sur la ligne suivante.
Je vais plutôt essayer la solution de bobince.
Si url
ne commence pas par '/'
Prenez l'url de la page actuelle, coupez tout ce qui est passé le dernier '/'; puis ajoutez l'url relative.
Sinon si url
commence par '/'
Prenez l'url de la page actuelle et coupez tout à droite du single '/'; puis ajoutez l'url.
Sinon si url
commence par # ou?
Prenez l'url de la page actuelle et ajoutez simplement url
J'espère que ça marche pour toi