aknosis.com

webdev && sysadmin quips, tips, articles + more

Using jQuery to Rewrite Relative Urls to Absolute Urls - [Revisited]

| Comments

After scanning my site stats and realizing that an old post about how to rewrite all the relative urls on a page with jQuery was one of my most visited, I decided to review the code and noticed it could be improved. My knowledge of JavaScript and jQuery has improved immensely since that previous post and this revisit is an attempt to improve upon it.

Problem: Need to change all the relative urls on a page and replace with an absolute url.

Different from my other post I’m going to separate the concerns of this problem: 1 being selecting only the links that are relative and not inline or mailto: links; 2 modifying the href.

Selecting the links on a page

The jQuery standard $(‘a’) will only solve half our problem because we only want links that are relative. There are several different methods we can use with jQuery to get exactly what you need, however first take into context what your page actually looks like. You may be able to save some time if your page has relatively few links, on the other hand if you have a page with hundreds of links you will need to chose your selectors wisely. To make the best and most informed decision, I suggest you test your various use cases @ http://jsperf.com/.

Here are three that I came up with:

jQuery Selectors
1
2
3
$('a').not('[href^="http"],[href^="https"],[href^="mailto:"],[href^="#"]');
$('a:not([href^="http:"],[href^="https:"],[href^="mailto:"],[href^="#"])');
$('a:not([href*="://"],[href^="mailto:"],[href^="#"])');

I’m going to use the first one just because it is a little bit more succinct. Now that we have all of the relative links on the page we need modify the href for each one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$(function(){
//Use jQuerys .each() method to iterate over each link
        $('a').not('[href^="http"],[href^="https"],[href^="mailto:"],[href^="#"]').each(function() {
//Use .attr() to modify the href, when you provide a callback function
//the arguments passed are the attribute index and its value
            $(this).attr('href', function(index, value) {
//This fix solves the problem when you aren't at the root level of a site
// e.g. if you are at site.com/page1/ and the link href is "do/something"
// we need to make sure the absolute url becomes newsite.com/page1/do/something
// if we just prepended the new domain we would actually get newsite.comdo/something
// which obviously wouldn't work
                if (value.substr(0,1) !== "/") {
                    value = window.location.pathname + value;
                }
//When you return from the callback function for .attr() it will set the attribute
//to this new value.
//We don't use a trailing slash on mynewurl.com because it will already exist if
//the href starts with a / or it will be part of window.location.pathname
                return "http://mynewurl.com" + value;
        });
    });
});

Live example below, hover over the links to see the urls before, click the button and check them again, all of the relative links will become absolute with the new domain.

Thanks for reading my post, I hope it was helpful.

Comments