Thursday, May 24, 2012

Get query string values in JavaScript


Is there a plugin-less way of retrieving query string values via jQuery (or without)?



If so, how, and if not what plugin do you recommend?


Source: Tips4all

26 comments:

  1. You don't need jQuery for that purpose you can use the pure JavaScript:

    function getParameterByName(name)
    {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(window.location.search);
    if(results == null)
    return "";
    else
    return decodeURIComponent(results[1].replace(/\+/g, " "));
    }

    ReplyDelete
  2. Some of the solutions posted here are inefficient. Repeating the regular expression search every time the script needs to access a parameter is completely unnecessary, one single function to split up the parameters into an associative-array style object is enough. If you're not working with the HTML 5 History API, this is only necessary once per page load. The other suggestions here also fail to decode the URL correctly.

    var urlParams = {};
    (function () {
    var e,
    a = /\+/g, // Regex for replacing addition symbol with a space
    r = /([^&=]+)=?([^&]*)/g,
    d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
    q = window.location.search.substring(1);

    while (e = r.exec(q))
    urlParams[d(e[1])] = d(e[2]);
    })();


    Example querystring:


    ?i=main&mode=front&sid=de8d49b78a85a322c4155015fdce22c4&enc=+Hello%20&empty


    Result:

    urlParams = {
    enc: " Hello ",
    i: "main",
    mode: "front",
    sid: "de8d49b78a85a322c4155015fdce22c4",
    empty: ""
    }

    alert(urlParams["mode"]);
    // -> "front"

    alert("empty" in urlParams);
    // -> true


    This could easily be improved upon to handle array-style query strings too. An example of this is here, but since array-style parameters aren't defined in RFC 3986 I won't pollute this answer with the source code.

    Also, as pointed out in the comments, ; is a legal delimiter for key=value pairs. It would require a more complicated regex to handle ; or &, which I think is unnecessary because it's rare that ; is used and I would say even more unlikely that both would be used. If you need to support ; instead of &, just swap them in the regex.


    If you're using a server-side preprocessing language, you might want to use its native JSON functions to do the heavy lifting for you. For example, in PHP you can write:

    <script>var urlParams = <?php echo json_encode($_GET, JSON_HEX_TAG);?>;</script>


    Much simpler!

    ReplyDelete
  3. Improved version of this answer:

    function getParameterByName(name) {

    var match = RegExp('[?&]' + name + '=([^&]*)')
    .exec(window.location.search);

    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

    }


    For more info on improvement see: http://james.padolsey.com/javascript/bujs-1-getparameterbyname/

    ReplyDelete
  4. Without jQuery

    var qs = (function(a) {
    if (a == "") return {};
    var b = {};
    for (var i = 0; i < a.length; ++i)
    {
    var p=a[i].split('=');
    if (p.length != 2) continue;
    b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
    }
    return b;
    })(window.location.search.substr(1).split('&'));


    With an URL like ?topic=123&name=query+string, the following will return:

    qs["topic"]; // 123
    qs["name"]; // query string
    qs["nothere"]; // undefined (object)




    Google method

    Tearing Google's code I found the method they use: getUrlParameters

    function (b) {
    var c = typeof b === "undefined";
    if (a !== h && c) return a;
    for (var d = {}, b = b || k[B][vb], e = b[p]("?"), f = b[p]("#"), b = (f === -1 ? b[Ya](e + 1) : [b[Ya](e + 1, f - e - 1), "&", b[Ya](f + 1)][K](""))[z]("&"), e = i.dd ? ia : unescape, f = 0, g = b[w]; f < g; ++f) {
    var l = b[f][p]("=");
    if (l !== -1) {
    var q = b[f][I](0, l),
    l = b[f][I](l + 1),
    l = l[Ca](/\+/g, " ");
    try {
    d[q] = e(l)
    } catch (A) {}
    }
    }
    c && (a = d);
    return d
    }


    It is obfuscated, but it is understandable.

    They start to look for parameters on the url from ? and also from the hash #. Then for each parameter they split in the equal sign b[f][p]("=") (which looks like indexOf, they use the position of the char to get the key/value). Having it split they check whether the parameter has a value or not, if it has they store the value o d, if not it just continue.

    In the end the object d is returned, handling escaping and the + sign. This object is just like mine, it has the same behavior.



    My method as a jQuery plugin

    (function($) {
    $.QueryString = (function(a) {
    if (a == "") return {};
    var b = {};
    for (var i = 0; i < a.length; ++i)
    {
    var p=a[i].split('=');
    if (p.length != 2) continue;
    b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
    }
    return b;
    })(window.location.search.substr(1).split('&'))
    })(jQuery);


    Usage

    $.QueryString["param"]




    Performance test (split method against regex method) (jsPref)

    Preparation code: methods declaration

    Split test code

    var qs = window.GetQueryString(query);

    var search = qs["q"];
    var value = qs["value"];
    var undef = qs["undefinedstring"];


    Regex test code

    var search = window.getParameterByName("q");
    var value = window.getParameterByName("value");
    var undef = window.getParameterByName("undefinedstring");


    Testing in Firefox 4.0 x86 on Windows Server 2008 R2 / 7 x64


    Split method: 144,780 ±2.17% fastest
    Regex method: 13,891 ±0.85% | 90% slower

    ReplyDelete
  5. Roshambo on snipplr.com has a really hot and simple script to achieve this described in Get URL Parameters with jQuery | Improved. With his script you also easily get to pull out just the parameters you want.

    Here's the gist:

    $.urlParam = function(name){
    var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if (!results)
    {
    return 0;
    }
    return results[1] || 0;
    }


    Then just get your parameters from the query string.

    So if the URL/query string was xyz.com/index.html?lang=de.

    Just call var langval = $.urlParam('lang');, and you've got it.

    UZBEKJON has a great blog post on this as well, Get URL parameters & values with jQuery.

    ReplyDelete
  6. If you're using jQuery, you can use a library, such as jQuery BBQ: Back Button & Query Library.


    ...jQuery BBQ provides a full .deparam() method, along with both hash state management, and fragment / query string parse and merge utility methods.


    If you want to just use plain JavaScript, you could use...

    var getParamValue = (function() {
    var params,
    resetParams = function() {
    var query = window.location.search,
    regex = /[?&;](.+?)=([^&;]+)/g,
    match;

    params = {};

    if (query) {
    while (match = regex.exec(query)) {
    params[match[1]] = decodeURIComponent(match[2]);
    }
    }
    };

    window.addEventListener
    && window.addEventListener('popstate', function() {
    resetParams();
    });

    resetParams();

    return function(param) {
    return params.hasOwnProperty(param) ? params[param] : null;
    }

    })();​


    Because of the new HTML History API and specifically history.pushState() and history.replaceState(), the URL can change which will invalidate the cache of parameters and their values.

    This version will update its internal cache of parameters each time the history changes.

    ReplyDelete
  7. Just another recommendation. The plugin jQuery-URL-Parser allows to retrieve all parts of URL, including anchor, host, etc.

    Usage is very simple and cool:

    $.url.param("itemID")

    ReplyDelete
  8. Here's my stab at making Andy E's excellent solution into a full fledged jQuery plugin:

    ;(function ($) {
    $.extend({
    getQueryString: function (name) {
    function parseParams() {
    var params = {},
    e,
    a = /\+/g, // Regex for replacing addition symbol with a space
    r = /([^&=]+)=?([^&]*)/g,
    d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
    q = window.location.search.substring(1);

    while (e = r.exec(q))
    params[d(e[1])] = d(e[2]);

    return params;
    }

    if (!this.queryStringParams)
    this.queryStringParams = parseParams();

    return this.queryStringParams[name];
    }
    });
    })(jQuery);


    The syntax is:

    var someVar = $.getQueryString('myParam');


    Best of both worlds!

    ReplyDelete
  9. If you're doing more URL manipulation than simply parsing the querystring, you may find URI.js helpful. It is a library for manipulating URLs - and comes with all the bells and whistles. (Sorry for self-advertising here)

    to convert your querystring into a map:

    var data = URI('?foo=bar&bar=baz&foo=world').query(true);
    data == {
    "foo": ["bar", "world"],
    "bar": "baz"
    }


    (URI.js also "fixes" bad querystrings like ?&foo&&bar=baz& to ?foo&bar=baz)

    ReplyDelete
  10. Roshambo jQuery method wasn't taking care of decode URL

    http://snipplr.com/view/26662/get-url-parameters-with-jquery--improved/

    Just added that capability also while adding in the return statement

    return decodeURIComponent(results[1].replace(/\+/g, " ")) || 0;


    Now you can find the updated gist:

    $.urlParam = function(name){
    var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if (!results) { return 0; }
    return decodeURIComponent(results[1].replace(/\+/g, " ")) || 0;


    }

    ReplyDelete
  11. Code golf:

    var a = location.search&&location.search.substr(1).replace(/\+/gi," ").split("&");
    for (var i in a) {
    var s = a[i].split("=");
    a[i] = a[unescape(s[0])] = unescape(s[1]);
    }


    Display it!

    for (i in a) {
    document.write(i + ":" + a[i] + "<br/>");
    };


    On my Mac: test.htm?i=can&has=cheezburger displays

    0:can
    1:cheezburger
    i:can
    has:cheezburger

    ReplyDelete
  12. This is a function I created a while back and I'm quite happy with. It is not case sensitive - which is handy. Also, if the requested QS doesn't exist, it just returns an empty string.

    I use a compressed version of this. I'm posting uncompressed for the novice types to better explain what's going on.

    I'm sure this could be optimized or done differently to work faster, but it's always worked great for what I need.

    Enjoy.

    function getQSP(sName, sURL) {
    var theItmToRtn = "";
    var theSrchStrg = location.search;
    if (sURL) theSrchStrg = sURL;

    var sOrig = theSrchStrg;

    theSrchStrg = theSrchStrg.toUpperCase();
    sName = sName.toUpperCase();
    theSrchStrg = theSrchStrg.replace("?", "&")
    theSrchStrg = theSrchStrg + "&";
    var theSrchToken = "&" + sName + "=";
    if (theSrchStrg.indexOf(theSrchToken) != -1) {
    var theSrchTokenLth = theSrchToken.length;
    var theSrchTokenLocStart = theSrchStrg.indexOf(theSrchToken) + theSrchTokenLth;
    var theLocOfNextAndSign = theSrchStrg.indexOf("&", theSrchTokenLocStart);
    theItmToRtn = unescape(sOrig.substring(theSrchTokenLocStart, theLocOfNextAndSign));
    }
    return unescape(theItmToRtn);
    }

    ReplyDelete
  13. I like dojo's queryToObject. The function could easily be plucked from the framework if you're on a diet.

    ReplyDelete
  14. I like Ryan Phelan's solution. But I don't see any point of extending jQuery for that? There is no usage of jQuery functionality.

    On other hand I like the built-in function in Google Chrome: window.location.getParameter.

    So why not to use this? Okay, other browsers don't have. So let's create this function if it does not exist:

    if (!window.location.getParameter ) {
    window.location.getParameter = function(key) {
    function parseParams() {
    var params = {},
    e,
    a = /\+/g, // Regex for replacing addition symbol with a space
    r = /([^&=]+)=?([^&]*)/g,
    d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
    q = window.location.search.substring(1);

    while (e = r.exec(q))
    params[d(e[1])] = d(e[2]);

    return params;
    }

    if (!this.queryStringParams)
    this.queryStringParams = parseParams();

    return this.queryStringParams[key];
    };
    }


    This function is more or less from Ryan Phelan, but it is wrapped differently: clear name and no dependencies of other javascript libraries. More about this function on my blog.

    ReplyDelete
  15. function GET() {
    var data = [];
    for(x = 0; x < arguments.length; ++x)
    data.push(location.href.match(new RegExp("/\?".concat(arguments[x],"=","([^\n&]*)")))[1])
    return data;
    }


    example:
    data = GET("id","name","foo");
    query string : ?id=3&name=jet&foo=b
    returns:
    data[0] // 13
    data[1] // jet
    data[2] // b
    or
    alert(GET("id")[0]) // return 3

    ReplyDelete
  16. I would rather use split() instead of Regex for this operation:

    function getUrlParams() {
    var result = {};
    var params = (window.location.search.split('?')[1] || '').split('&');
    for(var param in params) {
    if (params.hasOwnProperty(param)) {
    paramParts = params[param].split('=');
    result[paramParts[0]] = decodeURIComponent(paramParts[1] || "");
    }
    }
    return result;
    }

    ReplyDelete
  17. I use the plugin getUrlParam described in jQuery-Plugin – getUrlParam (version 2).

    ReplyDelete
  18. Nice.

    To get a specific named argument in the query you could also do it the following way:
    JavaScript: Get URL Query Argument

    Remember to url decode the value using the "unescape" method in JavaScript.

    ReplyDelete
  19. Here is my version of query string parsing code on github

    It's "prefixed" with jquery.*, but the parsing function itself don't use jQuery. Its pretty fast but still open for few simple performance optimizations.

    Also it supports list & hash-tables encoding in URL, like:

    arr[]=10&arr[]=20&arr[]=100


    or

    hash[key1]=hello&hash[key2]=moto&a=How%20are%20you

    ReplyDelete
  20. kis:

    function qs(key) {
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
    hash = hashes[i].split('=');
    vars.push(hash[0]);
    vars[hash[0]] = hash[1];
    }
    return vars[key];
    }


    call it from anywhere in the js:

    var result = qs['someKey'];

    ReplyDelete
  21. http://someurl.com?key=value&keynovalue&keyemptyvalue=&&keynovalue=nowhasvalue#somehash



    Regular key/value pair (?param=value)
    Keys w/o value (?param : no equal sign or value)
    Keys w/ empty value (?param= : equal sign, but no value to right of equal sign)
    Repeated Keys (?param=1&param=2)
    Removes Empty Keys (?&& : no key or value)


    Code:


    var queryString = window.location.search || '';
    var keyValPairs = [];
    var params = {};
    queryString = queryString.substr(1);

    if (queryString.length)
    {
    keyValPairs = queryString.split('&');
    for (pairNum in keyValPairs)
    {
    var key = keyValPairs[pairNum].split('=')[0];
    if (!key.length) continue;
    if (typeof params[key] === 'undefined')
    params[key] = [];
    params[key].push(keyValPairs[pairNum].split('=')[1]);
    }
    }



    How to Call:


    params['key']; // returns an array of values (1..n)



    Output:


    key ["value"]
    keyemptyvalue [""]
    keynovalue [undefined, "nowhasvalue"]

    ReplyDelete
  22. Try this:

    String.prototype.getValueByKey = function(k){
    var p = new RegExp('\\b'+k+'\\b','gi');
    return this.search(p) != -1 ? decodeURIComponent(this.substr(this.search(p)+k.length+1).substr(0,this.substr(this.search(p)+k.length+1).search(/(&|;|$)/))) : "";
    };


    Then call it like so:

    if(location.search != "") location.search.getValueByKey("id");


    You can use this for cookies also:

    if(navigator.cookieEnabled) document.cookie.getValueByKey("username");


    This only works for strings that have "key=value[&|;|$]"... will not work on objects/arrays.

    If you don't want to use String.prototype...
    move it to a function and pass the string as an argument

    ReplyDelete
  23. I took this answer and added support for optionally passing the URL in as a parameter; falls back to window.location.search. Obviously this is useful for getting the query string parameters from URLs that are not the current page:

    (function($, undef) {
    $.QueryString = function(url) {
    var pairs, qs = null, index, map = {};
    if(url == undef){
    qs = window.location.search.substr(1);
    }else{
    index = url.indexOf('?');
    if(index == -1) return {};
    qs = url.substring(index+1);
    }
    pairs = qs.split('&');
    if (pairs == "") return {};
    for (var i = 0; i < pairs.length; ++i)
    {
    var p = pairs[i].split('=');
    if(p.length != 2) continue;
    map[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
    }
    return map;
    };
    })(jQuery);

    ReplyDelete
  24. This code will create a object which have two method
    1. isKeyExist: Check if particular parameter exist;
    2. getValue: get value of particular parameter.

    var QSParam = new function() {
    var qsParm = {};
    var query = window.location.search.substring(1);
    var params = query.split('&');
    for (var i = 0; i < params.length; i++) {
    var pos = params[i].indexOf('=');
    if (pos > 0) {
    var key = params[i].substring(0, pos);
    var val = params[i].substring(pos + 1);
    qsParm[key] = val;
    }
    }
    this.isKeyExist = function(query){
    if(qsParm[query]){
    return true;
    }
    else{
    return false;
    }
    };
    this.getValue = function(query){
    if(qsParm[query])
    {
    return qsParm[query];
    }
    throw "URL does not contain query "+ query;
    }
    };

    ReplyDelete
  25. Here's my own take on this. This first function decodes a URL string into an object of name/value pairs:

    url_args_decode = function (url) {
    var args_enc, el, i, nameval, ret;
    ret = {};
    // use the DOM to parse the URL via an 'a' element
    el = document.createElement("a");
    el.href = url;
    // strip off initial ? on search and split
    args_enc = el.search.substring(1).split('&');
    for (i = 0; i < args_enc.length; i++) {
    // convert + into space, split on =, and then decode
    args_enc[i].replace(/\+/g, ' ');
    nameval = args_enc[i].split('=', 2);
    ret[decodeURIComponent(nameval[0])]=decodeURIComponent(nameval[1]);
    }
    return ret;
    };


    And as an added bonus, if you change some of the args, you can use this second function to put the array of args back into the URL string:

    url_args_replace = function (url, args) {
    var args_enc, el, name;
    // use the DOM to parse the URL via an 'a' element
    el = document.createElement("a");
    el.href = url;
    args_enc = [];
    // encode args to go into url
    for (name in args) {
    if (args.hasOwnProperty(name)) {
    name = encodeURIComponent(name);
    args[name] = encodeURIComponent(args[name]);
    args_enc.push(name + '=' + args[name]);
    }
    }
    if (args_enc.length > 0) {
    el.search = '?' + args_enc.join('&');
    } else {
    el.search = '';
    }
    return el.href;
    };

    ReplyDelete
  26. This one works fine

    function getQuerystring(key) {
    var query = window.location.search.substring(1);
    alert(query);
    var vars = query.split("&");
    for (var i = 0; i < vars.length; i++) {
    var pair = vars[i].split("=");
    if (pair[0] == key) {
    return pair[1];
    }
    }
    }


    taken from here

    ReplyDelete