How JavaScript can get its own File Path

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Arodicus
    New Member
    • May 2007
    • 12

    How JavaScript can get its own File Path

    I'm trying to get the pathname of the .js file that the currently-executing function resides in. This is useful if your .js file loads other assets within (or based on) the directory your .js file is in.


    After being told by several folks it wasn't possible, I actually figured out a way (shown below), so
    1. I'm posting it so others may benefit, and
    2. You can tell me if there are any potential bugs.
    3. You can tell me if there's a better way.


    Include the following snippet in the first line of your .js file:

    Code:
    var thisScript = (function(){
        var ScriptID = "ScriptID" + Math.round(100000*Math.random());
        document.write("<script id='"+ScriptID+"'></script>");
        return document.getElementById(ScriptID).previousSibling.getAttribute("src");
    })()
    
    alert(thisScript);
    and thisScript will contain a string representing the filepath to the currently-executing .js file, ie "JavaScript/test.js".

    Tested in IE 7, Firefox 2, Safari 3

    HOW IT WORKS:
    First off, we generate a random ID. Next, we use document.write to create a bogus <SCRIPT> tag in the DOM (we can't use DOM commands here because the page is still streaming and DOM doesn't fully exist)

    That done, we now look for the bogus tag, knowing that its previous sibling *must* be the currently-executing <SCRIPT> tag. (Amazingly, even though DOM isn't fully written yet, this still works).

    Finally, we just grab the src attribute of the current <SCRIPT>, and we have our answer. Any functions that reference the global thisScript will automatically know their own filepath.

    If you are dealing with multiple JS files, just vary the name of thisScript (thisScript1, thisScript2, etc), or else reference thisScript within a closure function to capture its state at the time it was executed.

    I wrapped the whole thing in a null closure, so the function and all variables it creates garbage-collect the moment it runs, to avoid stepping on any existing code. All that remains is the var you assigned along with its value.
  • mrhoo
    Contributor
    • Jun 2006
    • 428

    #2
    You can use dom methods as soon as the html element is read,
    as long as you do not call anything by name that does not yet exist.

    var scr=document.ge tElementsByTagN ame('script');
    scr=scr[scr.length-1]
    alert(scr.src || scr.text);

    I cannot imagine the need for this- once loaded,
    all the scripts become a single script, within the same window scope.

    Comment

    • Arodicus
      New Member
      • May 2007
      • 12

      #3
      This is extremely useful if you're trying to load assets other than javascript that happen to be in the same directory as the script. This is particularly true if you're trying to get the same group of assets to load across multiple servers, and don't necessarily have control over the who|what|where factors.

      For instance, I have a utility program written as several SWFs which are stored along with the support javascript that loads them and sends them information. The support js loads, and automatically knows where to look for the SWFs (based on its src attribute), rather than being explicitly told.

      This means that installation is now simply "unzip this folder on your server and load the script" rather than "unzip and put the script here, but put the files over there, and now you have to tell the script where the files are" and all that nonsense. Developers only need to know that they need to load the .js file because it's able to locate the SWFs that it needs entirely on it's own. They don't even need to be AWARE there are other assets.

      This has a side of effect of greatly increasing portability - the exact same script can now be used to load the assets, even if loaded on different pages and websites - even crossdomain - without being told where anything it needs happens to be.

      This creates a modular, almost object-oriented approach with the physical folder structure, rather than a more traditional, "sorted-by-filetype" approach where "js files go here and swf go there and jpgs go..".

      The folder containing all the js and other assets is now wholly self contained - it's a module. Assets such as support graphics, swfs, audio etc are now tied to their module, rather than tied to the webpage containing the module.

      Comment

      • Arodicus
        New Member
        • May 2007
        • 12

        #4
        I like your way a little better, since it doesn't create the extra Script and avoids document.write, so I'll test to see how well it works on all major browsers.

        Both approaches suffer a fatal flaw, though; they assume the currently-executing script hasn't already injected another script into the page, which is a dangerous assumption: both methods will pick up the wrong script, which may be sourced differently.

        In that case, it may be necessary to (gag) actually walk the code to verify it's the right code... or put in a liner note saying "hey, call this first".

        Additionally, neither version, I think, is going to work after the document stream has closed, ala Dojo/Prototype, although yours stands a better chance since it's just pure DOM. Ah well... more liner notes... :)

        Comment

        • Arodicus
          New Member
          • May 2007
          • 12

          #5
          [QUOTE=Arodicus]I like your way a little better, since it doesn't create the extra Script and avoids document.write, so I'll test to see how well it works on all major browsers. [QUOTE]

          Slight modification to your code:

          Code:
          var scr=document.getElementsByTagName('script');
          var src=scr[scr.length-1].getAttribute("src");
          alert(src);
          ... which now works great! Thankas for the input, this seems to be much better.

          The use of getAttribute provides consistency across platforms. Under Mozilla browsers, scr.src returns a fully qualified URI, while IE returns a relative URI; getAttribute however always returns the exact attribute that was actually used, which could be significant for some parsing out the container ref as I suggested above.

          Comment

          • tkamin
            New Member
            • Oct 2011
            • 1

            #6
            Code:
            var scr=document.getElementsByTagName('script');
            var src=scr[scr.length-1].getAttribute("src");
            alert(src);
            It seems that this solution might fail if the last script tag pulls an external JS file - like when the last script is a reference to Google Analytics (ga.js).

            Comment

            Working...