Programming and Technology
RSS icon Home icon
  • Dynamic paths in external javascript and stylesheets

    Posted on April 19th, 2010 brandon No comments

    Best practices  dictate that unobtrusive javascript is king these days which means that all javascript should live in external js files instead of cluttering up the html. Simple enough, however, situations arise sometimes where you need to adapt your javascript for dynamic conditions of the application, most notably, the current base directory where your application lives. If your application is small enough you can just hard code paths to images, other scripts, or internal urls however if you are anything like me, you probably shudder at the thought of hard coding any thing. Take this use case into consideration: let’s say we have an external javascript file called myscript.js which houses all of our javascript for handling click events on ajax powered links throughout the site.

    1.  
    2.   jQuery(‘a.update-me’).click(function(){
    3.      jQuery(‘div#ajax-content’).load(‘/thebasepath/page/dosomething’);
    4.   });
    5.  

    Here we are calling a url on the site to populate a div with some content. As you can see I had to hard code the url with a pre-determined basepath. The problem arises in a scenario where the site get’s moved into a different folder, perhaps we are migrating to a different server, or perhaps the site is getting restructured. It’s simple enough to edit this one instance of the url, however, what if there are 15 or 30 other ajax calls each with unique urls? Suddenly it’s a tedious task of doing search and replace.

    What if we could treat external javascript files (or even external stylesheets) like we would treat a template in an MVC application? Wouldn’t this be ideal:

    1.  
    2.   jQuery(‘a.update-me’).click(function(){
    3.      jQuery(‘div#ajax-content’).load(‘%basepath%/page/dosomething’);
    4.   });
    5.  

    Here we indicate that basepath is a variable. I chose percent signs to signal a variable but the choice is arbitrary as long as you use something you can uniquely match on. So how do we make this work? Well let me start by recommending that you read an older post I wrote about bundling assets more efficiently on your site called: Queued, Concatenated, and Gzipped Assets with the Zend Framework. In brief, in that article I wrote about how you can concatenate all of your javascript or css into single requests in order to lower the overhead of making multiple requests to grab page assets. We can extend this functionality to do some automatic search and replace for us since it’s already processing the contents of your scripts when it concatenates them. Here is what my updated js.php file looks like:

    1.  
    2. <?php
    3.  
    4. ob_start(‘ob_gzhandler’);
    5.  
    6. header(‘Content-type: text/javascript; charset: UTF-8′);
    7. header("Cache-Control: must-revalidate");
    8. $offset = 60 * 60 ;
    9. $ExpStr = "Expires: " .
    10. gmdate("D, d M Y H:i:s",
    11. time() + $offset) . " GMT";
    12. header($ExpStr);
    13.  
    14. if (isset($_GET[‘include’])){
    15.   $includes = explode(‘,’, $_GET[‘include’]);
    16.   foreach($includes as $include){
    17. //     readfile("$include.js");
    18.     $contents = file_get_contents(dirname(__FILE__) . "/$include.js");
    19.     $contents = preg_replace(‘/%images%/’, ‘/assets/images’, $contents);
    20.     $contents = preg_replace(‘/%scripts%/’, ‘/assets/scripts’, $contents);
    21.     $contents = preg_replace(‘/%styles%/’, ‘/assets/styles’, $contents);
    22.     echo $contents;
    23.   }
    24. }
    25.  
    26. ?>
    27.  

    Now instances of %images%, %scripts%, and %styles% will be replaced with dynamic live paths automatically. No search and replace and one less headache when it comes time to migrate your site.

    • Share/Bookmark

    Leave a reply

Get Adobe Flash playerPlugin by wpburn.com wordpress themes