Convert relative path to absolute using JavaScript

后端 未结 11 1546
误落风尘
误落风尘 2020-11-28 05:15

There\'s a function, which gives me urls like:

./some.css
./extra/some.css
../../lib/slider/slider.css

It\'s always a relative path.

<
相关标签:
11条回答
  • 2020-11-28 05:29
    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;
    }
    

    This works on IE6 too, unlike some other solutions (see Getting an absolute URL from a relative one. (IE6 issue))

    0 讨论(0)
  • 2020-11-28 05:30

    I had to add a fix to the accepted solution because we can have slashes after # in our angularjs navigation.

    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("/");
    }
    
    0 讨论(0)
  • 2020-11-28 05:31

    I found a very simple solution to do this while still supporting IE 10 (IE doesn't support the URL-API) by using the History API (IE 10 or higher). This solution works without any string manipulation.

    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() won't trigger browser navigation, but will still modify document.location and supports relative aswell as absolute paths.

    The one drawback of this solution is that if you are already using the History-API and have set a custom state with a title, the current state's title is lost.

    0 讨论(0)
  • 2020-11-28 05:37

    The proposed and accepted solution does not support server relative URLs and does not work on absolute URLs. If my relative is /sites/folder1 it won't work for example.

    Here is another function that supports full, server relative or relative URLs as well as ../ for one level up. It is not perfect but covers a lot of options. Use this when your base URL is not the current page URL, otherwise there are better 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;
    }
    

    Hope this helps. It was really frustrating not to have this basic utility available in JavaScript.

    0 讨论(0)
  • 2020-11-28 05:38

    This from MDN is unbreakable!

    /*\
    |*|
    |*|  :: 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);
    }
    

    Sample usage:

    /* 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
    
    0 讨论(0)
提交回复
热议问题