Skip to content

Instantly share code, notes, and snippets.

@davesque
Created October 2, 2012 21:46
Show Gist options
  • Save davesque/3823519 to your computer and use it in GitHub Desktop.
Save davesque/3823519 to your computer and use it in GitHub Desktop.
Parse and manipulate query args in JavaScript
/*global _:true */
/**
* Args builds an object with a property for each query argument in the query
* portion of a url. Properties on the object can then be modified and an
* updated url with query string can be produced from the Args instance.
*/
function Args(url) {
var self = this;
//|
//| Get url query parameters and set object properties
//|
var urlFragments = url.split("?");
var queryString = ( urlFragments.length > 1 ) ? urlFragments[1] : "";
var queryFragments = queryString.split("&");
// Get key value pairs
_.each(queryFragments, function(queryFragment) {
var argFragments = queryFragment.split("=");
var argName = decodeURIComponent(argFragments[0]);
var argValue = ( argFragments.length > 1 ) ? decodeURIComponent(argFragments[1]) : undefined;
self[argName] = argValue;
});
//|
//| Private properties, getters, and setters
//|
// Path of url (without query string)
var path = urlFragments[0];
// In case a specific order for parameters is needed, it is stored here.
// Contains an array that looks like: ["prop_name1", "prop_name2", etc.]
var order;
this.getPath = function() { return path; };
this.getOrder = function() { return order; };
this.setOrder = function(o) { order = o; };
}
Args.propertyToString = function(name, value) {
if ( _.isFunction(value) )
return undefined;
else if ( value === undefined )
return encodeURIComponent(name);
else
return encodeURIComponent(name) + "=" + encodeURIComponent(value);
};
/**
* Converts an Args object into a string with the original url path and all
* get parameters encoded as a query string. Must be set directly on the
* prototype because IE doesn't like overriding Object methods via
* Underscore.extend().
*/
Args.prototype.toString = function() {
return this.getPath() + "?" + this.getQueryString();
};
_.extend(Args.prototype, {
/**
* Converts query data in an Args object into a query string.
*/
getQueryString: function() {
var self = this;
var order = this.getOrder();
// Build query fragments (["name1=value1", "name2", undefined, etc.])
var queryFragments;
if ( order !== undefined ) {
var orderedProperties = _.map(order, function(propName) {
if ( _.has(self, propName) ) {
return {
name: propName,
value: self[propName]
};
}
// Return undefined if property does not exist so it can be filtered
return undefined;
});
// Filter out undefined values
orderedProperties = _.compact(orderedProperties);
queryFragments = _.map(orderedProperties, function(prop) {
return Args.propertyToString(prop.name, prop.value);
});
} else {
queryFragments = _.map(this, Args.propertyToString);
}
queryFragments = _.reject(queryFragments, function(i) {
return (i === undefined);
});
return queryFragments.join("&");
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment