What is my script src URL?
Asked Answered
M

6

37

Is there a simple and reliable way to determine the URL of the currently-executing JavaScript file (inside a web page)?

My only thought on this is to scan the DOM for all the script src attributes to find how the current file was referenced and then figure out the absolute URL by applying it to document.location. Anyone have other ideas, is there some super-easy method I completely overlooked?

UPDATE: Script elements accessed via the DOM already have a src property which contains the full URL. I don't know how ubiquitous/standard that is, but alternatively you can use getAttribute("src") which will return whatever raw attribute value is in the [X]HTML.

Madel answered 12/6, 2009 at 0:39 Comment(3)
possible duplicate of How might I get the script filename from within that script?Johannessen
Thanks to ie11 there doesn't seem to be a water tight approach. See this site for some comparisons fractallambda.com/2014/11/15/…Tericaterina
For Exact Answer: #2977151Abirritate
C
41

Put this in the js file that needs to know it's own url.

Fully Qualified (eg http://www.example.com/js/main.js):

var scriptSource = (function(scripts) {
    var scripts = document.getElementsByTagName('script'),
        script = scripts[scripts.length - 1];

    if (script.getAttribute.length !== undefined) {
        return script.src
    }

    return script.getAttribute('src', -1)
}());

Or As it appears in source (eg /js/main.js):

var scriptSource = (function() {
    var scripts = document.getElementsByTagName('script'),
        script = scripts[scripts.length - 1];

    if (script.getAttribute.length !== undefined) {
        return script.getAttribute('src')
    }

    return script.getAttribute('src', 2)
}());

See http://www.glennjones.net/Post/809/getAttributehrefbug.htm for explanation of the getAttribute parameter being used (it's an IE bug).

Convulsive answered 12/6, 2009 at 1:40 Comment(8)
For the fully qualified one can't you just use script.src? Why are you using script.getAttribute('src', -1)???Rhineland
Great answer. One caveat - it the script is lazy loaded (injected into the DOM by another script), it won't be the last script in the DOM, so this exact snippet won't work.Wexford
Will certainly not work with <script src="..." async> tags, (the html5 form of lazy loading) and even without those, it's not working at all on FF12, so I suppose recent browsers are starting to deliberately break that.Chicken
Not "should break", but "are breaking"; I saw that happen. Pages look faster if javascripts load asynchronously by default. It could break functionality, yes, but in most cases it probably doesn't. And those race conditions can and are identified and handled while loading by most recent js engines. @MarcoDemaioChicken
@Crescent Fresh: FYI your solution does not work in IE8 anymore because IE8 properly supports script.src as FF and other browsers, but your code would return script.getAttribute('src', -1) also for IE8, and IE8 would NOT return the fully qualified src as IE6 and IE7 did.Rhineland
I have come across a case where this algorithm doesn't work reliably. Other script tags that are set to async can run between your script being requested and run. These scripts can add other scripts to the DOM which appear after yours. When your script run the last script on the page is no longer yours and the wrong src is returned.Intercellular
@Karl: whoa ya absolutely, so much has changed in browserland in the last 4 years since this answer, a hack like this is bound to be stale! Please modify as you see fit, so many of my answers I don't have time to revisit.Convulsive
Note this approach is not guaranteed to work even without async. See #14410482Tericaterina
I
39

For recent browsers, you can use document.currentScript to get this information.

var mySource = document.currentScript.src;

The upside is that it's more reliable for scripts that are loaded asynchronously. The downside is that it's not, as best I know, universally supported. It should work on Chrome >= 29, FireFox >= 4, Opera >= 16. Like many useful things, it doesn't seem to work in IE.

When I need to get a script path, I check to see if document.currentScript is defined, and, if not, use the method described in the accepted answer.

if (document.currentScript) {
    mySource = document.currentScript.src;
} else {
    // code omitted for brevity
}

https://developer.mozilla.org/en-US/docs/Web/API/document.currentScript

Inessential answered 28/4, 2014 at 17:50 Comment(3)
caniuse.com doesn't monitor this feature yet. You can help with an upvote here: github.com/Fyrd/caniuse/issues/1099.Bisitun
@Bisitun it worked! caniuse.com/#search=currentscriptKeel
When will this be available in Chrome? It's not available in 87 yet...?Notary
R
6

As it appears in source (e.g. /js/main.js), this is cross-browser:

var scriptSource = (function() 
{ 
    var scripts = document.getElementsByTagName('script'), 
        script = scripts[scripts.length - 1]; 

    //No need to perform the same test we do for the Fully Qualified
    return script.getAttribute('src', 2); //this works in all browser even in FF/Chrome/Safari
}()); 

Fully Qualified (e.g. http://www.example.com/js/main.js):

After some tests it seems hard to get the fully qualified one in a cross-browser way. The solution suggested by Crescent Fresh does not work in IE8 to get the fully qualified, even if it works in IE7

Rhineland answered 5/10, 2010 at 15:24 Comment(0)
D
5

This method work with defer, async and lazy loading Since you know the filename of your script, and if it will be unique

/* see  
 * https://mcmap.net/q/95184/-what-is-my-script-src-url/984656#984656
 * http://www.glennjones.net/Post/809/getAttributehrefbug.htm
 * 
 * iterate all script to find script with right filename
 * this work with async and defer (but your script MUST have a unique filemane)
 * mozilla support document.currentScript and we use it, if is set
 *
 * this will not work with local script loaded by jQuery.getScript(),
 * since there is no script tag added into the dom. the script is only evaluated in global space.
 * http://api.jquery.com/jQuery.getScript/
 *  
 * to fix this odd, you can add a reference in meta ( meta[name=srcipt][content=url] )
 * when you load the script
 */
var scriptFilename = 'jquery.plugins.template.js'; // don't forget to set the filename 
var scriptUrl = (function() {
    if (document.currentScript) { // support defer & async (mozilla only)
        return document.currentScript.src;
    } else {
        var ls,s;
        var getSrc = function (ls, attr) {
            var i, l = ls.length, nf, s;
            for (i = 0; i < l; i++) {
                s = null;
                if (ls[i].getAttribute.length !== undefined) { 
                    s = ls[i].getAttribute(attr, 2);                    
                }               
                if (!s) continue; // tag with no src
                nf = s;
                nf = nf.split('?')[0].split('/').pop(); // get script filename
                if (nf === scriptFilename) {
                    return s;
                }
            }
        };          
        ls = document.getElementsByTagName('script');
        s = getSrc(ls, 'src');
        if ( !s ) { // search reference of script loaded by jQuery.getScript() in meta[name=srcipt][content=url]
            ls = document.getElementsByTagName('meta');             
            s = getSrc(ls, 'content');
        }           
        if ( s ) return s;
    }
    return '';
})();

var scriptPath =  scriptUrl.substring(0, scriptUrl.lastIndexOf('/'))+"/";

a jquery plugin template with it: https://github.com/mkdgs/mkdgs-snippet/blob/master/javascript/jquery.plugins.template.js

note: this will not work with local script loaded by jQuery.getScript(), since there is no script tag added into the dom. the script is only evaluated in global space. http://api.jquery.com/jQuery.getScript/

to fix it you can do something like:

function loadScript(url,callback) {     

    if ( $('[src="'+url+'"]').length ) return true; // is already loaded    

    // make a reference of the loaded script
    if ( $('meta[content="'+url+'"]', $("head")).length ) return true; // is already loaded 
    var meta = document.createElement('meta');
    meta.content = url;
    meta.name = 'script';
    $("head").append(meta);

    return $.ajax({
          cache: true,
          url: u,
          dataType: 'script',
          async: false,
          success : function (script) {                     
                try { 
                    if ( typeof callback == 'function' ) callback();    
                } catch (error) { 
                    //console.log(error);
                }
          }
     });
}
Deckle answered 9/5, 2013 at 9:33 Comment(2)
Interesting use of document.currentScript here. Sadly, the browser support information is not tey available on caniuse.com. You can help by upvoting the opened issue: github.com/Fyrd/caniuse/issues/1099.Bisitun
I've voted for it but caniuse.com is not the only information source. developer.mozilla.org/en-US/docs/Web/API/Document/currentScriptDeckle
K
0

If this is a strictly client solution, yours sounds pretty good.

If you are writing code on the server, you could probably just populate a div/hidden field/(insert your fave HTML element here) with the fully resolved URL to the script, and pick that up with your javascript on the clientside.

Krystenkrystin answered 12/6, 2009 at 0:45 Comment(2)
server side, he could just serve the js trough asp/php/jsp/cgi and output the url in javascript from there.Chicken
@Chicken -- I'm currently enjoying the idea of a "JS trough", however it's served ;)Muscadel
R
0

You may want to have a look at https://addons.mozilla.org/en-US/firefox/addon/10345 if you're interested in learning which functions (and thus which file) are executing on a page you don't control.

If you're interested in figuring out which of your scripts is executing, then there are a number of ways. With Firebug you could console.log() the information. Even just putting alert statements in your code (while annoying) can help debug in a low-tech way. You could also raise errors and catch them, then process using properties of the error (see: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error)

However, why would this be important? If the script is causing errors already then it's easy enough to determine where the error is occurring. If it's not about errors at all, then what's the advantage in knowing which file it comes from?

Ro answered 12/6, 2009 at 0:48 Comment(2)
In my current project the JavaScript resource files are fixed to a specific sub-directory. Figuring out the script's absolute URL can tell me what the local base directory is so I can strip it off to come up with the document "key" (as known to the server-side). It'll be used for generating forms, async requests, etc. and not for debugging.Madel
in that case, what you proposed above is the only solution really available.Ro

© 2022 - 2024 — McMap. All rights reserved.