debuggable

 
Contact Us
 

Relative urls in JavaScript

Posted on 14/9/08 by Felix Geisendörfer

Hey folks,

this is post #25 of my 30 day challenge.

One of the issues I always face when writing JavaScript is the relative path problem. Unless you specify an absolute path for lets say an ajax request, your urls will resolve relative to the current url.

This is a really annoying issue, especially since we are all used to CakePHP fixing it for us when using Router::url. So how could we create our own url() function in JavaSccript that will solve this problem for us?

Well the solution is simple. All we need to do is to store the information on the base url somewhere in the html. Since we are lucky, the html specification already knows an element for this called <base>.

So when we open up our app/views/layouts.ctp file, all we need to put into the <head> section is the following:

<base href="<?php echo Router::url('/'); ?>" />

Now we need a little JavaScript function we can use with this:

$.url = function(url) {
  return $('base').attr('href')+url.substr(1);
}

Now whenever we want to make an ajax call, we can simply do:

$('#foo').get($.url('/posts/index));

Of course another way of achieving the same result is to require your site to run within its own domain (virtual host). However, I like building apps that can also run from within a sub folder as it makes them more portable and its easier for other people to set the site up and get involved in the project.

Alright, looking forward to alternative approaches & feedback.

-- Felix Geisendörfer aka the_undefined

 
&nsbp;

You can skip to the end and add a comment.

NOSLOW  said on Sep 14, 2008:

Why not just set a global js variable named 'base' (within your own namespace, of course) and forget the dependency on a js library to access that value? Works for me ;)

Thomas Sittig  said on Sep 14, 2008:

sure, the global variable-solution works well. but i would agree with the way of felix. why? because with it, as a developer, i don't have to ask myself over and over again, how i named this global variable. in fact, i know excatly where i find the information i'm looking for. and i know, this information is in a place, where it belongs to.

NOSLOW  said on Sep 14, 2008:

@Thomas: With Felix's approach, you still have to remember your own convention of the custom function $.url. If you must, you could write a similar getter function to achieve the same results -- without the dependency of jquery.

If you setup a global namespace for each project with conventions for naming your project's variables, I don't see this as an issue at all. Felix just likes to show off his "Rock Star" jquery abilities sometimes :P. It certainly makes a more interesting blog read!

Felix Geisendörfer said on Sep 14, 2008:

NOSLOW: I'll try whatever necessary to make you use jQuery ; ).

Walekr Hamilton said on Sep 14, 2008:

I would much rather just echo out a variable available in the head of the layout as javascript than make everything within the app depend on a tag. (I've gotten myself into trouble with .)

Pixelastic  said on Sep 14, 2008:

There are side effects of using an autoclosed base tag on IE6, I tried to post some code explaining the problem and the workaround but your spam filter blocked me, I posted it to your contact page instead.

Anyway, I prefere a meta (name="Identifier-URL") for this purpose, having spent too much time debugging IE6.

James Calfee  said on Oct 06, 2009:

This avoids the server-side code. You can use the current URL to get your base location:

var basedir = document.location.href;
basedir = basedir.substring(0, basedir.lastIndexOf('/')) + '/';

Then convert your relative path into a the full path:

basedir + 'myfile.json'

This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.