Created
October 2, 2012 21:46
-
-
Save davesque/3823519 to your computer and use it in GitHub Desktop.
Parse and manipulate query args in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*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