Skip to content

Instantly share code, notes, and snippets.

@lionel-rowe
Last active April 30, 2019 12:34
Show Gist options
  • Save lionel-rowe/abdf3a128e0c22a8f5123e9bb4007891 to your computer and use it in GitHub Desktop.
Save lionel-rowe/abdf3a128e0c22a8f5123e9bb4007891 to your computer and use it in GitHub Desktop.
QueryParams - super-simple query string parser with comma-delimited arrays
const QueryParams = {};
QueryParams.options = {
usePlusSigns: false, // per RFC 1866 application/x-www-form-urlencoded; otherwise use "%20" for space
keyMustReturnArray: key => key.endsWith('_arr') // for URI-decoded keys that return `true` for this function, coerce the value to an array even if it contains no commas
};
const decode = str => {
if (QueryParams.options.usePlusSigns) {
str = str.replace(/\+/g, '%20');
}
return decodeURIComponent(str);
};
const encode = str => {
str = encodeURIComponent(str);
if (QueryParams.options.usePlusSigns) {
str = str.replace(/%20/g, '+');
}
return str;
};
QueryParams.parse = queryString => {
const obj = {};
const m = queryString.match(/\?(.+)/);
if (!m) return obj;
const data = m[1];
data.split('&')
.forEach(kv => {
const [_key, val] = kv.split('=');
const key = decode(_key);
if (typeof val === 'undefined') {
obj[key] = null;
} else if (QueryParams.options.keyMustReturnArray(key) || val.includes(',')) {
const arr = val ? val.split(',') : [];
obj[key] = arr.map(el => decode(el));
} else {
obj[key] = decode(val);
}
});
return obj;
};
QueryParams.serialize = obj => {
let queryString = '?';
Object.keys(obj).forEach((key, idx) => {
const val = obj[key];
if (typeof val === 'undefined') return;
if (idx !== 0) queryString += '&';
queryString += encode(key);
if (val === null) return;
queryString += '=';
if (val instanceof Array) {
queryString += val.map(el => encode(el)).join(',');
} else {
queryString += encode(val);
}
});
return queryString === '?' ? '' : queryString;
};
QueryParams.get = () => QueryParams.parse(window.location.search);
QueryParams.set = (obj, usePushState=true) => {
const f = usePushState ? 'pushState' : 'replaceState';
window.history[f](
{},
'',
[
window.location.origin,
window.location.pathname,
QueryParams.serialize(obj),
window.location.hash
].join('')
);
};
QueryParams.update = (obj, usePushState=true) => {
const updates = QueryParams.get();
Object.keys(obj).forEach(key => {
updates[key] = obj[key];
});
QueryParams.set(updates, usePushState);
};
QueryParams.clear = (usePushState=true) => {
QueryParams.set({}, usePushState);
}
export default QueryParams;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment