31

I am adding my Javsacript file in pages with different query strings in the script path like this:

Page1:

<script type="text/javascript" src="file.js?abc=123"></script>

Page2:

<script type="text/javascript" src="file.js?abc=456"></script>

Page3:

<script type="text/javascript" src="file.js?abc=789"></script>

In my Javascript file, how can I get the value of the "abc" param? I tried using window.location for this, but that does not work.

In case it helps, below is a function I use to find the value of a query string param:

function getQuerystring(key, defaultValue) {
    if (defaultValue == null) defaultValue = "";
    key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
    var qs = regex.exec(window.location.href);
    if (qs == null)
        return defaultValue;
    else
        return qs[1];
}
Oded
  • 489,969
  • 99
  • 883
  • 1,009
TruMan1
  • 33,665
  • 59
  • 184
  • 335
  • possible duplicate of [How might I get the script filename from within that script?](http://stackoverflow.com/questions/710957/how-might-i-get-the-script-filename-from-within-that-script) – Bergi Jul 17 '13 at 15:42

5 Answers5

33

This is possible. See Passing JavaScript arguments via the src attribute. The punchline is that since scripts in HTML (not XHTML) are executed as loaded, this will allow a script to find itself as it is always the last script in the page when it’s triggered–

var scripts = document.getElementsByTagName('script');
var index = scripts.length - 1;
var myScript = scripts[index];
// myScript now contains our script object
var queryString = myScript.src.replace(/^[^\?]+\??/,'');

Then you just apply the query string parsing.

Ashley
  • 4,307
  • 2
  • 19
  • 28
  • 15
    *"...since scripts in HTML (not XHTML) are executed as loaded..."* Note that the [`defer` and `async`](http://www.w3.org/TR/html5/scripting-1.html#attr-script-defer) attributes modify that behavior, so if you're using them, this may not work: Your script may not be the last in the series at that point. Relying on that would give me the shivers anyway, so I'd probably use the filename and filter on `src` (granted that introduces a restriction that the file can't be renamed). – T.J. Crowder Feb 15 '12 at 14:08
  • 1
    Filtering on src might be tricky if you referenced the same script multiple times with different params. – bendytree Apr 11 '13 at 17:42
  • 10
    You could use `document.currentScript` which is the actual script tag which is running the actual code. – MichelMattos Sep 15 '15 at 11:52
  • 1
    @MichelMattos Yes, currentScript is cool! ...unless you need to support IE :-( – targumon May 12 '19 at 08:38
19

First, the technical answer: if you assign your script tag an ID, you can then grab its src and then parse out the query string.

<script id="whatever" type="text/javascript" src="file.js?abc=123"></script>

 

var path = document.getElementById('whatever').src;
// ...

With that answered, I'd like to voice my concern — this reeks of poor design decisions. Why are you including your script this way (with a querystring)? If you're trying to optimize your site (by having one large script that can be cached for subsequent pages), this approch is actually counter-productive because browsers will make a fresh request for the script file on each page due to the differing query string. The correct approach is to have one large shared file and then a small page-specific file on each page.

josh3736
  • 139,160
  • 33
  • 216
  • 263
  • 3
    Josh3736 - one reason (and this is the reason I ended up here via a Google search ) is to handle a widget that is being used elsewhere. For example, I'm doing – Raymond Camden Apr 02 '13 at 22:07
  • 2
    I like this answer. But if using a method like this one, I might do something like this instead: – Tyler Biscoe Feb 16 '15 at 02:03
  • 2
    @Tyler, that's probably how I'd do it today. Notice that this answer was written 4+ years ago, before HTML 5 `data` attributes were widely supported. – josh3736 Feb 16 '15 at 02:32
  • Another reason might be for versioning. When you want a script to be reloaded when a new version has been deployed. Then you might want access to the version number within the script itself. – Daniel C May 10 '16 at 11:26
  • Why didn't i thought of that :D – tbhaxor Jan 16 '21 at 06:07
  • This is also required when you are creating your own plugin objects. So I want to package and distribute my own script that say requires an access key to be passed to the code. – Vinnie Amir Jun 14 '22 at 07:42
5

You can use the URL api and document.currentScript to retreive this`

const url = new URL(document.currentScript.getAttribute('src'));
const scriptParams = Object.fromEntries(url.searchParams)
console.log(scriptParams);
Wallace Vizerra
  • 3,382
  • 2
  • 28
  • 29
4

Since there is no more significant use of Internet Explorer. You can use document.currentScript and new URL, which return a string with the tag <script> in question.

const search            = new URL(document.currentScript.src).search.substring(1)
const stringPreparation = decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"')
const qs                = JSON.parse('{"' + stringPreparation + '"}')

You can reduce this code to one line, but it is not recommended, let minifier scripts do that.

insign
  • 5,353
  • 1
  • 38
  • 35
0

I have a quick and easy solution for extracting the query string from a js file using jQuery to grab the script tag source attribute and simply using two separate functions for parsing the JS file path and query string. Obviously, jQuery is required.

$(document).ready(function() {

    var p = parseURL($('script[src*="thisfile.js"]').attr('src'));

    console.log(p);

});

// Parse a URL into its parts
function parseURL(url)
{
    var p = document.createElement('a');

    p.href = url;

    var obj = {
        'protocol' : p.protocol,
        'hostname' : p.hostname,
        'port' : p.port,
        'pathname' : p.pathname,
        'search' : p.search,
        'query' : p.search.substring(1),
        'args' : parseStr(p.search.substring(1)),
        'hash' : p.hash,
        'host' : p.host
    };

    return obj;
}

// Parse a query string
function parseStr(string)
{
    var args = string.split('&');
    var argsParsed = {};

    for (i = 0; i < args.length; i++)
    {
        var arg = decodeURIComponent(args[i]);

        if (arg.indexOf('=') == -1)
        {
            argsParsed[arg.trim()] = true;
        }
        else
        {
            var kvp = arg.split('=');
            argsParsed[kvp[0].trim()] = kvp[1].trim();
        }
    }

    return argsParsed;
}
Tanoro
  • 871
  • 2
  • 10
  • 30
  • Are you sure that's the easiest way to do it ? And you need to hardcode the file name additionally. – gregn3 Jun 12 '19 at 13:20
  • Ashley's answer above is probably simpler than mine. My snippet was merely one I had at the ready when I posted this. And you don't need to hardcode the file. You need only tailor the jQuery selector on line 3 to suit your specific needs. In this case, my needs were for specific file as was requested in the original post above. – Tanoro Jun 13 '19 at 14:27