The website that I am working on has a
tag point to a different URL than the one that the website has. What I would like to do is get around the
First, if you're not using base
yet or are but can switch away from using it, please read:
Which will give you many good reasons to think twice. Moral of the story: It's usually a bad idea to use base
. There are good reasons, and it is useful; I have used it to great delight many times when working with designers to have local copies of the markup that I can work with but still maintain connections back into the site's assets. But for production sites, it's too clever by half.
Also, this answer was originally written for a different question that was an exact duplicate, so I'm posting this here, although there's an answer that's very similar to it already.
Do you have control over the markup or can you use a selector to get only the elements you want to effect? You could:
HTML (Note the class truelink
.)
<ol>
<li>
<a href="#link1" class="truelink">True Link1</a>
</li>
<li>
<a href="#link2" class="truelink">True Link2</a>
</li>
<li>
<a href="#link3" class="truelink">True Link3</a>
</li>
</ol>
Javascript
window.addEventListener('load', function links(){
var base = document.getElementsByTagName('base')[0],
links = document.getElementsByClassName('truelink'),
l = links.length,
uri = 'http://www.host.tld/path?query=test';
console.log('Base:', base, ', True Links:', links);
console.log('Modifying links in five seconds...');
setTimeout(function go(){
console.log('Modifying links now...');
while (l--){
links[l].href = links[l].href.replace(base.href, uri);
}
console.log('Base: ', base, 'True Links: ', links);
}, 5000);
});
http://jsfiddle.net/M5Hdk/
Keep in mind that this technique demonstrates using document.getElementsByClassName, which is not supported by IE until version 9. If you have to support lower versions than IE9, see Jeremy J Starcher's answer for a less "efficient" but better supported method. There's also document.querySelectorAll
, which is supported by IE8 and above and all other major browsers. If you only need to support IE8, I would suggest using this to select your links over the method Jeremy demonstrates.
I also delay the change for five seconds so you can see it work. Obviously, this won't be necessary for you (most likely).
The only thing I'm not sure about right now is whether or not my .replace()
will always find the base.href
to replace in all browsers, so it may be better to detect the presence of a relative url before doing a replace, so you can do whatever else appropriately. For some related background on this possible "issue", see my question that deals with how browsers handle href
attributes differently in the DOM:
Method for selecting elements in Sizzle using fully-qualified URLs
Also, this will perhaps work most seamlessly if it falls in an inline script
tag right after the content, or at the end of body
tag, in which case you will want to remove the window.addEventListener
part and replace with a self-executing function.
Their are other options, all are probably a little more problematic:
base
tag altogether. If you do this, though, you'll first want to check if you need to manually insert the base.href
content into the links, otherwise I'm sure things can break or become brittle.a
links you want to use your true link and manipulate it that way onclick
, just don't forget to return false
at the end of the click handler function, so the browser doesn't follow the link. This is probably the most seamless method, but is probably not best for all situations.Be sure to test with real world markup. base
is a mildly quirky tool, so manhandling it may lead to unusual side effects. You were warned.
I am working on the assumption that your real case is more complex than your example. If it isn't, then review the other answers, which may be more appropriate for what you need to do.
What this will do is...
window
load event a function that will...DOM
that is an A
tag, and...A
tags and check if the element has an enhance
class, and if so...href
at the #
to get the current a
element's hash
value, which we will...Combine it with the following:
'//' + location.host + location.pathname;
Giving us the current page's URL without a hash
or query string. If you want the query string (what's after the ?
in a URL), add location.search
:
'//' + location.host + location.pathname + location.search;
Note, the //
part is protocol relative, so it will use whatever the base href
's protocol is, e.g., http
or https
. You may want to specify that, however.
Markup
Note the class
attribute, which we will use to identify which a
tags to manipulate.
<ol>
<li>
<a href="#link1">Link 1</a> -
No enhance class, should be subject to <strong>BASE HREF</strong>:
<strong class="p">» http://example.com#link1</strong>
</li>
<li>
<a href="#link2" class="enhance">Link 2</a> -
Has enhance class, should be:
<strong class="p">» http://fiddle.jshell.net/_display/#link2</strong>
</li>
<li>
<a href="#link3" class="enhance">Link 3</a> -
Has enhance class, should be:
<strong class="p">» http://fiddle.jshell.net/_display/#link3</strong>
</li>
<li>
<a href="#link3" class="enhance">Link 4</a> -
Has enhance class, should be:
<strong class="p">» http://fiddle.jshell.net/_display/#link4</strong>
</li>
</ol>
Javascript
//--
// window.onload is not preferred, window.addEventListener
// should be used. Except that only IE9 supports it, and
// IE8 and lower do not support it, and uses window.attachEvent
// instead, which you can test for.
//
// I'm using window.onload here simply as a shortcut method and
// for clarity. This can also go in a script tag at the bottom
// of the body tag, in which case you can remove window.onload
// and use a self-calling anonymous function like:
//
// (function updateLinks(){... all the same as below ...})();
//
// This will ensure you are out of the global variable scope.
//--
window.onload = function updateLinks() {
//--
// Modern browsers can use document.getElementsByClassName
// or you can use a shiv script to add it to browsers that
// don't. I'll do it the "manual" way here, and this works
// cross-browser. The downside is that it will interate
// through every A tag on the page, looking for the "small"
// few that have the el.className we're looking for here.
//--
var els = document.getElementsByTagName("a"),
l = els.length,
trueURL = '//' + location.host + pathname,
i, el, hash;
for (i = 0; i < l; i++) {
el = els[i];
if (el.className.indexOf("enhance") != -1) {
hash = el.href.split('#');
el.href = trueURL + "#" + hash[1];
}
}
};
http://jsfiddle.net/userdude/unnH8/
Mouseover the links to see the current setting. As always, thoroughly test with real markup in multiple browsers.
I would have done it this way
HTML
<ol>
<li>
<a class="build">Link1</a>
</li>
<li>
<a class="build">Link2</a>
</li>
<li>
<a class="build">Link2</a>
</li>
</ol>
Javascript/Jquery
$(function(){
var trueURL = window.location.href;
var i = 1;
$('a.build').each(function(){
$(this).attr('href', trueURL + '#link' + i);
i = i+1;
});
});
Example of working code Here
If you are serious about trueURL = window.location.href
then you are working WAY too hard.
Just make the link #link1
- it automatically will be relative to the current href.
If that was just an example, you may be interested in the:
<BASE href="...">
tag. This will let you change the relative href for all links in the page at once.
And you can do it with javascript by getting each <A...>
DOM element and modifying the href
property.