Javascript Deparam - decode querystring

Opposite of $.param. Sparked by SO discussion: http://stackoverflow.com/questions/2090551/parse-query-string-in-javascript

by drzaus

HTML

<pre id="output"></pre>

JavaScript

deparam = (function(d,x,params,p,i,j) {
return function (qs) {
    // start bucket; can't cheat by setting it in scope declaration or it overwrites
    params = {};
    // remove preceding non-querystring, correct spaces, and split
    qs = qs.substring(qs.indexOf('?')+1).replace(x,' ').split('&');
    // march and parse
    for (i = qs.length; i > 0;) {
    	p = qs[--i];
      // allow equals in value
      j = p.indexOf('=');
      // what if no val?
      if(j === -1) params[d(p)] = undefined;
      else params[d(p.substring(0,j))] = d(p.substring(j+1));
    }

    return params;
};//--  fn  deparam
})(decodeURIComponent, /\+/g);


var tests = {};
tests["simple params"] = "ID=2&first=1&second=b";
tests["full url"] = "http://blah.com/?third=c&fourth=d&fifth=e";
tests['just ?'] = '?animal=bear&fruit=apple&building=Empire State Building&spaces=these+are+pluses';
tests['with equals'] = 'foo=bar&baz=qux&equals=with=extra=equals&grault=garply';
tests['no value'] = 'foo=bar&baz=&qux=quux';
tests['value omit'] = 'foo=bar&baz&qux=quux';

var $output = document.getElementById('output');
function output(msg) {
  msg = Array.prototype.slice.call(arguments, 0).join("\n");
  if($output) $output.innerHTML += "\n" + msg + "\n";
  else console.log(msg);
}
var results = {}; // save results, so we can confirm we're not incorrectly referencing
each(tests, function(msg, test) {
  var q = deparam(test);
  results[msg] = q;
  output(msg, test, JSON.stringify(q), jQuery.param(q));
  output('-------------------');
});

output('=== confirming results non-overwrite ===');
each(results, function(msg, result) {
    output(msg, JSON.stringify(result));
    output('-------------------');
});

// no jquery necessary, duh
function each(obj, cb) {
	Object.keys(obj).forEach(function(k) {
		cb(k, obj[k]);
	})
}
function param(obj) {
	if(typeof(obj) === "string") return obj;
	if(Array.isArray(obj)) return obj.join('&');
	
	return param(Object.keys(obj).map(function(k) {
		return...