Il y a une fonction qui me donne des URL comme:
./some.css
./extra/some.css
../../lib/slider/slider.css
C'est toujours un chemin relatif.
Imaginons que nous connaissions le chemin actuel de la page, comme http://site.com/stats/2012/
, ne sachant pas comment convertir ces chemins relatifs en chemins réels.
Nous devrions obtenir quelque chose comme:
./some.css => http://site.com/stats/2012/some.css
./extra/some.css => http://site.com/stats/2012/extra/some.css
../../lib/slider/slider.css => http://site.com/lib/slider/slider.css
Pas de jQuery, seulement du javascript à la vanille.
Cela devrait le faire:
function absolute(base, relative) {
var stack = base.split("/"),
parts = relative.split("/");
stack.pop(); // remove current file name (or empty string)
// (omit if "base" is the current folder without trailing slash)
for (var i=0; i<parts.length; i++) {
if (parts[i] == ".")
continue;
if (parts[i] == "..")
stack.pop();
else
stack.Push(parts[i]);
}
return stack.join("/");
}
Javascript le fera pour vous. Pas besoin de créer une fonction. pas besoin de définir le nom de base.
var link = document.createElement("a");
link.href = "../../lib/slider/slider.css";
alert(link.protocol+"//"+link.Host+link.pathname+link.search+link.hash);
//output will be "http://www.yoursite.com/lib/slider/slider.css"
Si vous avez besoin d’une fonction, encapsulez-la comme une fonction avec 3 lignes de code.
var absolutePath = function(href) {
var link = document.createElement("a");
link.href = href;
return (link.protocol+"//"+link.Host+link.pathname+link.search+link.hash);
}
---- MIS À JOUR ---
Version plus simple seulement si vous avez besoin du chemin absolu
var absolutePath = function(href) {
var link = document.createElement("a");
link.href = href;
return link.href;
}
La manière la plus simple, efficace et correcte de le faire consiste simplement à utiliser URL api.
new URL("http://www.stackoverflow.com?q=hello").href;
//=> http://www.stackoverflow.com/?q=hello"
new URL("mypath","http://www.stackoverflow.com").href;
//=> "http://www.stackoverflow.com/mypath"
new URL("../mypath","http://www.stackoverflow.com/search").href
//=> "http://www.stackoverflow.com/mypath"
new URL("../mypath", window.location.href).href
//=> "https://stackoverflow.com/questions/mypath"
En termes de performances, cette solution est comparable à la manipulation de chaînes et deux fois plus rapide que la création de la balise a
.
Ceci de MDN est incassable!
/*\
|*|
|*| :: translate relative paths to absolute paths ::
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|*|
|*| The following code is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
\*/
function relPathToAbs (sRelPath) {
var nUpLn, sDir = "", sPath = location.pathname.replace(/[^\/]*$/, sRelPath.replace(/(\/|^)(?:\.?\/+)+/g, "$1"));
for (var nEnd, nStart = 0; nEnd = sPath.indexOf("/../", nStart), nEnd > -1; nStart = nEnd + nUpLn) {
nUpLn = /^\/(?:\.\.\/)*/.exec(sPath.slice(nEnd))[0].length;
sDir = (sDir + sPath.substring(nStart, nEnd)).replace(new RegExp("(?:\\\/+[^\\\/]*){0," + ((nUpLn - 1) / 3) + "}$"), "/");
}
return sDir + sPath.substr(nStart);
}
Exemple d'utilisation:
/* Let us be in /en-US/docs/Web/API/document.cookie */
alert(location.pathname);
// displays: /en-US/docs/Web/API/document.cookie
alert(relPathToAbs("./"));
// displays: /en-US/docs/Web/API/
alert(relPathToAbs("../Guide/API/DOM/Storage"));
// displays: /en-US/docs/Web/Guide/API/DOM/Storage
alert(relPathToAbs("../../Firefox"));
// displays: /en-US/docs/Firefox
alert(relPathToAbs("../Guide/././API/../../../Firefox"));
// displays: /en-US/docs/Firefox
Si vous souhaitez effectuer une conversion relative en absolu pour un lien d'une page Web personnalisée dans votre navigateur (pas pour la page qui exécute votre script), vous pouvez utiliser une version plus améliorée de la fonction proposée par @Bergi:
var resolveURL=function resolve(url, base){
if('string'!==typeof url || !url){
return null; // wrong or empty url
}
else if(url.match(/^[a-z]+\:\/\//i)){
return url; // url is absolute already
}
else if(url.match(/^\/\//)){
return 'http:'+url; // url is absolute already
}
else if(url.match(/^[a-z]+\:/i)){
return url; // data URI, mailto:, tel:, etc.
}
else if('string'!==typeof base){
var a=document.createElement('a');
a.href=url; // try to resolve url without base
if(!a.pathname){
return null; // url not valid
}
return 'http://'+url;
}
else{
base=resolve(base); // check base
if(base===null){
return null; // wrong base
}
}
var a=document.createElement('a');
a.href=base;
if(url[0]==='/'){
base=[]; // rooted path
}
else{
base=a.pathname.split('/'); // relative path
base.pop();
}
url=url.split('/');
for(var i=0; i<url.length; ++i){
if(url[i]==='.'){ // current directory
continue;
}
if(url[i]==='..'){ // parent directory
if('undefined'===typeof base.pop() || base.length===0){
return null; // wrong url accessing non-existing parent directories
}
}
else{ // child directory
base.Push(url[i]);
}
}
return a.protocol+'//'+a.hostname+base.join('/');
}
Il retournera null
si quelque chose ne va pas.
Usage:
resolveURL('./some.css', 'http://example.com/stats/2012/');
// returns http://example.com/stats/2012/some.css
resolveURL('extra/some.css', 'http://example.com/stats/2012/');
// returns http://example.com/stats/2012/extra/some.css
resolveURL('../../lib/slider/slider.css', 'http://example.com/stats/2012/');
// returns http://example.com/lib/slider/slider.css
resolveURL('/rootFolder/some.css', 'https://example.com/stats/2012/');
// returns https://example.com/rootFolder/some.css
resolveURL('localhost');
// returns http://localhost
resolveURL('../non_existing_file', 'example.com')
// returns null
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;
}
Cela fonctionne aussi sur IE6, contrairement à d’autres solutions (voir Obtenir une URL absolue à partir d’une adresse relative. (Problème avec IE6) )
La solution href ne fonctionne que lorsque le document est chargé (au moins dans IE11). Cela a fonctionné pour moi:
link = link || document.createElement("a");
link.href = window.location.href + "/../" + href;
return link.href;
La solution proposée et acceptée ne prend pas en charge les URL relatives du serveur et ne fonctionne pas sur les URL absolues . Si mon parent est/sites/folder1, cela ne fonctionnera pas par exemple.
Voici une autre fonction qui prend en charge les URL complètes, relatives ou relatives du serveur, ainsi que ../ pour un niveau supérieur. Ce n'est pas parfait, mais couvre de nombreuses options ..__ Utilisez cette option lorsque votre URL de base n'est pas l'URL de la page actuelle, sinon il existe de meilleures alternatives.
function relativeToAbsolute(base, relative) {
//make sure base ends with /
if (base[base.length - 1] != '/')
base += '/';
//base: https://server/relative/subfolder/
//url: https://server
let url = base.substr(0, base.indexOf('/', base.indexOf('//') + 2));
//baseServerRelative: /relative/subfolder/
let baseServerRelative = base.substr(base.indexOf('/', base.indexOf('//') + 2));
if (relative.indexOf('/') === 0)//relative is server relative
url += relative;
else if (relative.indexOf("://") > 0)//relative is a full url, ignore base.
url = relative;
else {
while (relative.indexOf('../') === 0) {
//remove ../ from relative
relative = relative.substring(3);
//remove one part from baseServerRelative. /relative/subfolder/ -> /relative/
if (baseServerRelative !== '/') {
let lastPartIndex = baseServerRelative.lastIndexOf('/', baseServerRelative.length - 2);
baseServerRelative = baseServerRelative.substring(0, lastPartIndex + 1);
}
}
url += baseServerRelative + relative;//relative is a relative to base.
}
return url;
}
J'espère que cela t'aides. C'était vraiment frustrant de ne pas avoir cet utilitaire de base disponible en JavaScript.
J'ai trouvé une solution très simple pour le faire tout en prenant en charge IE 10 (IE ne prend pas en charge l'URL-API) en utilisant History API (IE 10 ou une version supérieure). Cette solution fonctionne sans aucune manipulation de chaîne.
function resolveUrl(relativePath) {
var originalUrl = document.location.href;
history.replaceState(history.state, '', relativePath);
var resolvedUrl = document.location.href;
history.replaceState(history.state, '', originalUrl);
return resolvedUrl;
}
history.replaceState()
ne déclenchera pas la navigation dans le navigateur, mais modifiera toujours document.location
et supportera les chemins relatifs ainsi que les chemins absolus.
L'inconvénient de cette solution est que si vous utilisez déjà l'historique-API et avez défini un état personnalisé avec un titre, le titre de l'état actuel est perdu.
Cela fonctionnera. mais seulement lorsque vous ouvrez une page avec son nom de fichier. cela ne fonctionnera pas bien quand vous ouvrez un lien comme celui-ci stackoverflow.com/page
. cela fonctionnera avec stackoverflow.com/page/index.php
function reltoabs(link){
let absLink = location.href.split("/");
let relLink = link;
let slashesNum = link.match(/[.]{2}\//g) ? link.match(/[.]{2}\//g).length : 0;
for(let i = 0; i < slashesNum + 1; i++){
relLink = relLink.replace("../", "");
absLink.pop();
}
absLink = absLink.join("/");
absLink += "/" + relLink;
return absLink;
}
J'ai dû ajouter un correctif à la solution acceptée car nous pouvons avoir des barres obliques après # dans notre navigation angularjs.
function getAbsoluteUrl(base, relative) {
// remove everything after #
var hashPosition = base.indexOf('#');
if (hashPosition > 0){
base = base.slice(0, hashPosition);
}
// the rest of the function is taken from http://stackoverflow.com/a/14780463
// http://stackoverflow.com/a/25833886 - this doesn't work in cordova
// http://stackoverflow.com/a/14781678 - this doesn't work in cordova
var stack = base.split("/"),
parts = relative.split("/");
stack.pop(); // remove current file name (or empty string)
// (omit if "base" is the current folder without trailing slash)
for (var i=0; i<parts.length; i++) {
if (parts[i] == ".")
continue;
if (parts[i] == "..")
stack.pop();
else
stack.Push(parts[i]);
}
return stack.join("/");
}