4

Is there an easy way to get the relative url with javascript? Im trying to use window.location.href but it returns the absolute path.

What im trying to do is this: I have two pages; mobile.html and desktop.html. I want to use ONE javascript-file to detect whether the user is on a mobile or desktop (I know, this is not a very good way to do it..) like this:

var is_mobile = //alot of text from http://detectmobilebrowsers.com/
                //that returns true/false, this works fine

if (is_mobile){

    if (window.location.href != "mobile.html"){
        window.location = "mobile.html";
    }
}

else {
    if (window.location.href != "desktop.html"){
        window.location ="desktop.html";
    }
}

So the problem with absolute path is that when testing either mobile/desktop.html they both go into infinite loop pagerefresh..

1

5 Answers 5

6
var page = window.location.pathname.split('/').pop();

if (isMobile && page !== 'mobile.html')
    window.location = 'mobile.html';
else if (!isMobile && page !== 'desktop.html')
    window.location = 'desktop.html';
Sign up to request clarification or add additional context in comments.

2 Comments

awesome! just what I was looking for. But can you explain what .split() and .pop() does? I guess split splits the string where '/', but does it return an array or what? and what does .pop() do here? thanks!
Yep, split returns an array, and .pop() returns the last element of the array. '/foo/bar/mobile.html'.split('/') returns ['foo', 'bar', 'mobile.html']. ['foo', 'bar', 'mobile.html'].pop() returns the string 'mobile.html'. (Try it in Chrome dev tools or Firebug.)
1

Just test if it ends with either HTML file. You could use regular expressions:

if(/desktop\.html$/.test(window.location.href)) {
     // code for desktop
} else if(/mobile\.html$/.test(window.location.href)) {
     // code for mobile
}

Comments

1

Another solution to find out whether the location.href ends with mobile.html or not, without using regular expressions:

if(window.location.href.indexOf("mobile.html") != (window.location.href.length - "mobile.html".length)) {
  ..
}

Comments

0

URL.getRelativeURL

There's a bullet-proof public-domain extension for the standard URL object called getRelativeURL.

This would solve the problem for you:

var loc = new URL(location.href); //get the current location
var dir = new URL(".", loc); //get the current directory
var rel = loc.getRelativeURL(dir); //relative link from dir to loc

if( rel !== "mobile.html" ){ ... }

Try it live. View on Gist.

1 Comment

Just a point of order, you should not extend built-in objects in this way, because (a) it can end up causing conflicts with future additions to the standard library (or other libraries that try doing similar modifications!), and (b) it makes it hard to identify what code is being run, which is a pain for humans and bundlers alike (and in a modules world, importing something like this is purely side-effect, which is very undesirable). This should be implemented as a standalone function.
0

Here is @m93a's answer adapted to work without modifying the URL class, and with typescript types...

/**
 * Returns relative URL from base to target.
 * @param target
 * @param base
 * @param reload `false` to use "#" whenever the path and query of this url and the base are equal,
 *               `true` to use filename or query (forces reload in browsers)
 * @param root   `true` to force root-relative paths (e.g. "/dir/file"),
 *               `false` to force directory-relative paths (e.g. "../file"),
 *               `undefined` to always use the shorter one.
 * @param dotSlash whether or not to include the "./" in relative paths.
 */
export function uriRelativize(target: string | URL, base: string | URL, reload?: boolean, root?: boolean, dotSlash?: boolean): string {
    if (!(target instanceof URL))
        target = new URL(target);
    if (!(base instanceof URL))
        base = new URL(base);

    reload = !!reload;
    dotSlash = !!dotSlash;

    var rel = "";

    if (target.protocol !== base.protocol) {
        return target.href;
    }

    if (target.host !== base.host ||
        target.username !== base.username ||
        target.password !== base.password) {

        rel = "//";

        if (target.username) {
            rel += target.username;
            if (target.password)
                rel += ":" + target.password;
            rel += "@";
        }

        rel += target.host;
        rel += target.pathname;
        rel += target.search;
        rel += target.hash;

        return rel;

    }

    if (target.pathname !== base.pathname) {

        if (root) {
            rel = target.pathname;
        } else {

            var thisPath = target.pathname.split("/");
            var basePath = base.pathname.split("/");
            var tl = thisPath.length;
            var bl = basePath.length;

            for (var i = 1, l = Math.min(tl, bl) - 1; i < l; i++) {
                if (thisPath[i] !== basePath[i]) {
                    break;
                }
            }

            for (var cd = bl - 1; cd > i; cd--) {

                if (!rel && dotSlash) {
                    rel += "./";
                }

                rel += "../";
            }

            if (dotSlash && !rel)
                rel += "./";

            for (l = tl; i < l; i++) {
                rel += thisPath[i];
                if (i !== l - 1) {
                    rel += "/";
                }
            }

            if (root !== false && rel.length > target.pathname.length) {
                rel = target.pathname;
            }

            if (!rel && basePath[basePath.length - 1]) {
                rel = "./";
            }

        }
    }

    if (rel || target.search !== base.search) {
        rel += target.search;
        rel += target.hash;
    }

    if (!rel) {
        if (reload) {
            rel = target.search || "?";
            rel += target.hash;
        } else {
            rel = target.hash || "#";
        }
    }
    return rel;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.