Wednesday, September 16, 2009

Get URL parameters & values with jQuery

In this post, I would like to share a little jQuery code snippet that makes getting URL parameters and their values more convenient.

Recently, while working on one of my projects, I needed to read and get parameter values from URL string of the current page that was constructed and sent by PHP script. I came across this short and sweet JavaScript code snippet by Roshambo that does just that.

// Read a page's GET URL variables and return them as an associative array.
function getUrlVars()
{
    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;
}

The function returns an array/object with your URL parameters and their values. For example, consider we have the following URL:

http://www.example.com/?me=myValue&name2=SomeOtherValue

Calling getUrlVars() function would return you the following array:

{
    "me"    : "myValue",
    "name2" : "SomeOtherValue"
}

To get a value of first parameter you would do this:

var first = getUrlVars()["me"];

// To get the second parameter
var second = getUrlVars()["name2"];

To make the script syntax to look more jQuery like syntax I rewrote it as an extension for jQuery:

$.extend({
  getUrlVars: function(){
    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;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  }
});

Now, if you include the above code in your javascript file, you can get URL parameter values in the following way:

// Get object of URL parameters
var allVars = $.getUrlVars();

// Getting URL var by its nam
var byName = $.getUrlVar('name');

That’s it! You might also find the following jQuery related articles on this blogs interesting:

  1. Cross-domain AJAX querying with jQuery
  2. Javascript for() loop vs jQuery .each() performance comparison
  3. Create jQuery custom selectors with parameters
  4. JavaScript / jQuery password generator

50 comments:

  1. Shouldn't you cache the decoded vars?

    ReplyDelete
  2. I don't really see the point of making this a jquery plugin in this case, since it doesn't take jQuery or DOM elements and doesnt return them either.

    Nonetheless, This is by far the cleanest implementation of this utility I have seen.

    Also, jQuery will let you go back the other way too:

    $.param({
    me: "myValue",
    name2: "someOtherValue"
    });

    returns "me=myValue&name2=someOtherValue"

    This is really nice for caching the results of jQuery plugins that take objects as parameters. Usually, if you try to say cache[obj] = foo obj.toString will be called and you will be left with "[object Object]", which is not too helpful, but $.param() handles everything cleanly and quickly. So, now cache[$.param(obj)] = foo works out perfectly.

    ReplyDelete
  3. Just one line is enough inside getUrlVars():
    return window.location.href.slice(window.location.href.indexOf('?')).split(/[&?]{1}[\w\d]+=/);

    Take care

    ReplyDelete
  4. That's pretty sweet. I'm in the need for just this bit of code. Thanks! :)

    Shane

    ReplyDelete
  5. I was going to reply to this post with a regex solution, which I think is much more elegant. However, someone has obviously beat me to it:
    http://ejohn.org/blog/search-and-dont-replace/

    ReplyDelete
  6. Er, I posted too soon. The page I linked to wasn't solving this exact problem. Here's the solution that solves this problem:

    function getUrlParameters() {
    var map = {};
    var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
    map[key] = value;
    });
    return map;
    }

    ReplyDelete
  7. you are confusing location.search and location.hash

    here is an example i built for a framework that extracts both search and hash

    var Params = {
    /*
    Get
    -------------------------------
    walk through window.location.search and window.location.hash
    generate object (result) from iteration
    */
    Get:function()
    {
    result = {};
    request = {
    search:window.location.search.slice(1, window.location.search.length),
    hash:window.location.hash.slice(1, window.location.hash.length)
    }

    // check
    for(type in request)
    {
    if(request[type] != "")
    {
    var x = request[type].split("&");
    for(i in x)
    {
    var y = x[i].split("=");
    var prop = y[0];
    var value = y[1];
    result[prop] = value;
    }
    }
    }
    return result;
    }
    }

    where result will be an object as such
    result = {
    search:{
    prop:value,...
    },
    hash:{
    prop:value,...
    },
    }

    ps: love your articles
    addons.32teeth@gmail.com

    ReplyDelete
  8. I know this is completely unrelated but based on your understanding of jquery, please indulge me an see if you can help me...

    I have this code
    jQuery(document).ready(function() {

    $('a').click(function() {
    ...

    I have a lot of a (=link) tags generated dynamically after an Ajax call that I tug inside a div tag but for the life of me they do not get selected based on the event above...can you help me out? thanks!

    ReplyDelete
  9. Looks great!! But how to call an extension in jquery ?

    Thanks Alex

    ReplyDelete
  10. This is a great bit of code, thanks a lot. I added the code in a separate js file and works well.

    ReplyDelete
  11. Would be nice to add decodeURI before slice url

    ReplyDelete
  12. Excellent article.

    But after reading the following
    http://asimilia.wordpress.com/2008/12/17/jquery-extend-confusion/

    I have little bit confusion... which one is correct in our example?

    ReplyDelete
  13. Hi, Thanks for the post.

    What if the query parameter is an object. When I try to access that object it's giving me an error. please help, thanks.


    var first = getUrlVars()["query"];

    alert("property ==="+first.name);

    ReplyDelete
  14. What jquery version library does this work with?

    thanks all

    Getting some "unexpected token in attribute selector" error message.

    I basically created a blank html and linked to the latest jQuery library and added the above code to a "script" block

    ReplyDelete
  15. you could simply use this:

    var rUrl = $(document).getUrlParam("ReturnUrl");

    OR

    var rUrl = $().getUrlParam("ReturnUrl");

    http://somesite.com?ReturnUrl=%2fStore%2fProducts%2fAdd

    Original posting:
    http://www.techiegyan.com/2009/04/01/read-url-parameter-in-javascript-jquery-plugin/

    ReplyDelete
  16. thanks for saving my brain from extraction.. NICE POST

    ReplyDelete
  17. What about the hash? Currently, the above code will add the hash onto the last query parameter.

    ReplyDelete
  18. Whoops... I think I lied, sorry...

    ReplyDelete
  19. excellent code...
    after a long search i found this solution good

    ReplyDelete
  20. but what if the URL has a hash at the moment?

    if there is a location hash, this script doesnt work right...

    ReplyDelete
  21. Thanks. Probably want to modify the hashing part to something like:

    var url = decordeURI(window.location.href.replace(/&/g, "&"));
    var hashes = url.indexOf("?") + 1).split("&");

    There's probably an even better regex way.

    ReplyDelete
  22. This is incredibly useful to my team. We are using it to simulate pages in prototyping without the benefit of a database, so being able to manipulate pages and content within based on this is wonderful. Thanks so much!

    ReplyDelete
  23. Note that the URL can also have anchors- e.g.:
    http://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html#comments

    Perhaps use something like:
    vars[hash[0]] = hash[1].replace(/#/g, '');

    ReplyDelete
  24. Would someone be nice enough to tell me step by step how to pull the URL parameter and place it as a string inside of a form text box? Sorry if this is a newbie question, but I think it would help a lot of people implement this idea.

    ReplyDelete
  25. Hey dude. Thank you so much, you rocks!

    ReplyDelete
  26. When there are multiple url parameters i am seeing getUrlVars()["me"]; is returning 'myValue,' instead of 'myValue'

    Anybody is seeing this kind of issue?

    ReplyDelete
  27. Dunno if it will help anyone out, but I've extended it a little bit to handle arrays passed through the URL (eg: http://website.com/?myarray[]=test1&myarray[]=test2&myarray[]=test3 )

    $.extend({
    getURLVariables : function() {
    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('=');
    var key = hash[0].split('[]')[0];
    if(!vars[key]) {
    vars.push(key);
    vars[key] = [];
    }
    vars[key].push(hash[1]);
    }
    return vars;
    },
    getURLVariable : function(name) {
    var val;
    var query = $.getURLVariables()[name];
    if(query){
    if(query.length == 1) {
    val = query[0];
    } else {
    val = query;
    }
    }
    return val;
    }
    });

    ReplyDelete
  28. if you have page anker in your page, and parse your url including an anker, the anker will become part of last element

    ex http://mypage/somepage.html?a=2345#kurt

    So before parsing the url you should remove everying after and including the #

    ReplyDelete
  29. it will be great if you write a article about jQuery security while getting parameters from the url... i have some work in jquery, but i don't feel they are highly secure...

    ReplyDelete
  30. Years too late, but you should do a check to see if the var exists before returning a value (to avoid a javascript error):

    getUrlVar: function(name){
    if($.getUrlVars()[name]){
    return $.getUrlVars()[name];
    }else{return null;}
    }

    ReplyDelete
  31. yoink!

    just added it to my plugin (added decodeURIComponent to returned value), thanks :-)

    ReplyDelete
  32. Thanx a lot for your help. Saves me a lot of time! :)

    ReplyDelete
  33. Here's a variation of the function to extract a single value: https://gist.github.com/1771618

    ReplyDelete
  34. Oops, that last version had issues when there were no params. Here's a better version:

    function getUrlVars() {
    var params = {}, d = function (s) { return s ? decodeURIComponent(s.replace(/\+/, " ")) : null; }
    if(window.location.search) $.each(window.location.search.substring(1).split('&'), function(i, v) {
    var pair = v.split('=');
    params[d(pair[0])] = d(pair[1]);
    });
    return params;
    }

    ReplyDelete
  35. can this code be used on a commercial website

    ReplyDelete
  36. Awesome post. Works like a charm. Thanks!

    ReplyDelete
  37. Why not make it more useful and PASS it the url, so you can parse hrefs from links too?

    function getUrlVars(url)
    {
    var vars = [], hash;
    var hashes = url.slice(url.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;
    }

    If you want it for page then call it with
    var myGetArray = getUrlVars(window.location.href);

    ReplyDelete
  38. this will not work for arrays returned through get, which have the following syntax:

    ?a[action]=5&a[method]=b

    The obvious object that should be returned is:
    {
    "a": {
    "action": 5,
    "method": "b"
    }
    }

    and not:
    {
    "a[action]": 5,
    "a[method]": "b"
    }

    ReplyDelete
  39. Works well. Thanks

    ReplyDelete
  40. Regarding the regex solution, here's a simple variant that expands the function to include keys that don't have values defined. For example in "page.html?mobile&page=1", the "mobile" key has no value. Just add a question mark (?) after the second equals (=) sign in the regex string. It will yield the object {mobile:"",page:1}, whereas without the ? mark the mobile key won't even make it into the object. This is useful if you just need to detect the existence of a key in the URI, and not necessarily the value.

    Here's a copy of the full function with the ? mark added after the second equal sign in the regular expression.

    function getUrlParameters() {
    var map={};
    var parts=window.location.href.replace(/[?&]+([^=&]+)=?([^&]*)/gi,function(m,key,value){
    map[key]=value;
    });
    return map;
    }

    ReplyDelete
  41. I have made some modifications to fix encoding problem :
    vars[v[0]] = decodeURI(v[1]);

    Result is :

    (function ($) {
    /**
    * returns object with url variables
    * hash parameters take precedence over search
    * parameters
    * @return {Object}
    */
    $.getUrlVars = function () {
    var loc = document.location,
    search = loc.search.replace('?', '').split('&'),
    hash = loc.hash.replace('#', '').split('&'),
    i, l, v, vars = {};

    for (i = 0, l = search.length; i < l; i++) {
    v = search[i].split('=');
    vars[v[0]] = decodeURI(v[1]);
    }

    for (i = 0, l = hash.length; i < l; i++) {
    v = hash[i].split('=');
    vars[v[0]] = decodeURI(v[1]);
    }

    return vars;
    }

    /**
    * returns a single value from the getUrlVars hash
    * @param {String} i The hash index
    * @return {String}
    */
    $.getUrlVar = function (i) {
    return $.getUrlVars()[i];
    }
    }(jQuery));

    ReplyDelete
  42. this doesn't work for a single variable. i.e. there is no & to split on..

    ReplyDelete
  43. Best example I have seen - thumbs up!

    ReplyDelete
  44. This doesn't work for URL's with a hash section. For example:

    http://www.whatever.com/?id=38389#Registration

    In the id field, the value would be 38389#Registration which is incorrect.

    You should use window.location.search instead of window.location.href.slice(window.location.href.indexOf('?') + 1)

    ReplyDelete
  45. I have two variables "coachid" & "screenname"

    ?coachid=186123&screenname=Hank247Fitness

    Not sure exactly how to implement this into the following code:

    function cleanse( txt ) {
    txt = txt.replace( /\s/g, '' );
    txt = txt.replace( /[^A-Za-z0-9.]/g, '' );
    return txt;
    }

    function update_links() {
    var sn = cleanse( $('#screenname').val() );
    var ci = cleanse( $('#coachid').val() );


    $('.linkformat').each( function( lfind, lf ) {
    var lf_id = lf.id.match( /lf_(.*)$/ );
    lf_id = lf_id[1];

    var fmt = $(lf).text();

    fmt = fmt.replace(/\{\{screenname\}\}/gi, sn );
    fmt = fmt.replace(/\{\{coachid\}\}/gi, ci );


    var linkresult = $('#lr_'+lf_id);

    if ( linkresult.get(0).nodeName == 'A' ) {
    $('#lr_'+lf_id).attr( 'href', fmt );
    $('#lr_'+lf_id).text( fmt );
    } else {
    $('#lr_'+lf_id).text( fmt );
    }
    } );
    }

    $(function() {
    $('.coach-image').click( function( e ) {
    e.preventDefault();
    $('#coachid').val( $(this).attr('coachid') );
    $('#screenname').val( $(this).attr('screenname') );

    update_links();
    } );
    $('.watchable').keyup( function() { update_links(); } );
    $('.watchable').blur( function() { update_links(); } );
    $('#getname').click(function() {
    $.ajax({
    type: "POST",
    url: "getname.php",
    data: "id=" + escape($('#coachid').val()),
    success: function(data) {
    if ( data.name != null ) {
    $('#screenname').val(data.name);
    } else if ( data.error != null ) {
    alert("There was an error accessing the server: " + data.error);
    }
    },
    error: function() {
    alert("The getname backend function is not present or could not be invoked properly.");
    }
    });
    });
    update_links();
    });

    ReplyDelete
  46. Hi,

    What if i have a "=" in my value?
    let's say http://www.example.com?var1=val1&var2=val2=val3

    note that, var2 should be "val2=val3"
    but in this case, i only got "val2"

    Thank you.

    ReplyDelete