29
Sep
07

Media URL on javascript files

Using the MEDIA_URL setting in a template context variable is a very practical way to have the media files being served from a location defined in the settings file. James Bennett explains here how to define and use this context variable.

But, for example, if I need to have media urls in my javascript files, which are static files, I don't have access to this variable. Take this very simple example. I have a image placeholder in the markup.

<h1>Test 01</h1>
<img id="placeholder" src="">

And the image url is set with javascript.

function set_image() {
    var placeholder = document.getElementById("placeholder");
    placeholder.setAttribute("src","http://localhost:8000/static/django.gif");
}
window.onload = set_image

In this case the full url is hardcoded which, of course is not what I want. Like for the other media files I want to use the above url during development and in deployment switch to the media server url. Something like:

http://media.someserver.com/django.gif

I discuss bellow the approaches I have been trying.

Always use the media server urls in the javascript

Just always using the media server url in the javascript files. It's simple and works fine if I don't need to change the static resources. But changing the static files during development becomes a problem. And developing offline it's also a problem. So it's not a good solution.

Global javascript variable with the media url

This means having the following code in the base template.

<script src="{{ media_url }}test.js" type="text/javascript"></script>
<script language="javascript">var MEDIA_URL = "{{ MEDIA_URL }}";</script>

and in the javascript

function set_image() {
    var placeholder = document.getElementById("placeholder");
    placeholder.setAttribute("src", MEDIA_URL + "django.gif");
}

This approach works, and I consider it more practical than the previous one, but to have a global variable and extra markup is not very clean.

Media url stored in a meta tag

As a variant of the previous approach, instead of creating a global javascript variable I set a meta tag with the location of the media_url.

<meta name="media_url" id="media_url" content="{{ MEDIA_URL }}" />

Then in the javascript file extract the value from the DOM.

document.getElementById("media_url").getAttribute("content");

Again it's not a very clean solution.

Take the media url from the CSS url

This last one is based on convention. I always have the CSS files in the root of my media folder. If the urls for my CSS files are like:

http://media.someserver.com/style.css

then my media url is

http://media.someserver.com/

So in this case the idea is to always fetch the media url from the CSS file url (and so the document must always have a CSS file). The javascript function for such task:

function get_media_url() {
    var css_url = document.styleSheets[0].href;
    var last_slash = css_url.lastIndexOf('/');
    return css_url.substr(0,last_slash+1);
}

Although being based on convention this last one is the one I am more keen on using.

But to be honest, one of the reasons to write this post was to try to find some best practice for this topic. And maybe (hopefully) someone from the community can show some better practice.




9 Responses to “Media URL on javascript files”


  1. 1 September 29, 2007 at 11:44 am by Dan Larkin

    For all my django projects that that need MEDIA_URL in javascript files I just put <script type="text/javascript">var MEDIA_URL = "{{MEDIA_URL}}";</script> above all my other <script> definitions. Works like a charm and it's definitely the simplest of all the options you listed.

  2. 2 September 29, 2007 at 11:48 am by apollo13

    I use this method in my files: <script language="javascript">var MEDIA_URL = "{{ media_url }}";</script>
    I don't like the css approach, as my css files life in a css sub folder.
    To keep your apps portable I also would use the global-js var.

  3. 3 September 29, 2007 at 12:50 pm by slink

    For defining function get_media_url(), Pedro, you may use the Lazy Function Definition Pattern described by Peter [1]. So avoiding so many function calls, a better solution could be this:

    var media_url = function() {
    var css_url = document.styleSheets[0].href;
    var last_slash = css_url.lastIndexOf('/');
    return css_url.substr(0,last_slash+1);
    }();

    [1] http://peter.michaux.ca/article/3556

  4. 4 September 29, 2007 at 07:48 pm by James Bennett

    It's worth noting that a context processor for MEDIA_URL -- django.core.context_processors.media -- was added to Django a little while back and is now in the defualt set of context processors.

  5. 5 October 05, 2007 at 07:52 pm by Pedro Lima

    Thanks for the feedback. The global js variable seems to be the simple way to do it. And I also agree that simple is good.

  6. 6 December 05, 2007 at 06:45 am by Ben Walton

    Do you have a solution for getting the MEDIA_URL in a css file? For say a background-image ?

    Thanks,
    Ben

  7. 7 December 05, 2007 at 08:05 am by Pedro Lima

    Hi Ben,

    I never faced that need since I keep my CSS together with the media files. So for background images I just put the path relative to the CSS file (for example "background: url(img/myfile.png)" ). Doesn't that work for you?

  8. 8 November 23, 2010 at 12:46 pm by Abhas

    I was trying to follow the solution provided i.e. var MEDIA_URL={{MEDIA_URL}};

    However I have noticed that if I try to include src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" in the script tags,then i get MEDIA_URL as undefined inspite of the above mentioned declaration.any help would be greatly appreciated.

  9. 9 May 11, 2011 at 09:44 pm by jbaby

    i dont get it i need to link stuff for my glogster project which you probably dont no wat that is so go to google and type

Leave a Reply