-
-
Save pirate/9298155edda679510723 to your computer and use it in GitHub Desktop.
function getUrlParams(search) { | |
const hashes = search.slice(search.indexOf('?') + 1).split('&') | |
const params = {} | |
hashes.map(hash => { | |
const [key, val] = hash.split('=') | |
params[key] = decodeURIComponent(val) | |
}) | |
return params | |
} | |
console.log(getUrlParams(window.location.search)) |
A little more concise, maybe harder to interpret:
function getUrlParams(search) {
let hashes = search.slice(search.indexOf('?') + 1).split('&')
return hashes.reduce((params, hash) => {
let [key, val] = hash.split('=')
return Object.assign(params, {[key]: decodeURIComponent(val)})
}, {})
}
console.log(getUrlParams(window.location.search))
As I find myself searching this way too often and always ending up on this gist:
Dear future self, here's the native way to get URL params:
new URLSearchParams(document.location.search).get("foobar")
Also: Please remember the milk
Thanks @berstend! Note that you can also iterate all params with for...of
syntax: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
@berstend. I logged in just to say thanks...
I was trying to do a super duper mega blaster generic function to split this out. You've provided a much better (and cleaner) way :)
The only problem if you need to support IE 11
new URL()
or new URLSearchParams()
does not work :(
perfect thanks!
modified it slightly to use reduce instead of map to be immutable ;)
const getUrlParams = (search = ``) => {
const hashes = search.slice(search.indexOf(`?`) + 1).split(`&`)
return hashes.reduce((acc, hash) => {
const [key, val] = hash.split(`=`)
return {
...acc,
val: decodeURIComponent(val)
}
}, {})
}
console.log(getUrlParams(window.location.search))
[...new URLSearchParams(document.location.search).entries()].reduce((q, [k, v]) => Object.assign(q, {[k]: v}), {})
I think that it uses every ES6 convention...no wait I need a promise in there somewhere.
@CanRau the returned object should have the computed property of [key].
const getUrlParams2 = (search = '') => {
const hashes = search.slice(search.indexOf('?') + 1).split('&');
return hashes.reduce((acc, hash) => {
// eslint-disable-next-line
const [key, val] = hash.split('=');
return {
...acc,
[key]: decodeURIComponent(val)
};
}, {});
};
Note: the above functions all trim any characters including & following the first equal sign in a query value.
Eg ?q=test=abc
will be returned as test
by the above functions.
Obligatory own version of the above ;)
const decodeURLParams = search => {
const hashes = search.slice(search.indexOf("?") + 1).split("&");
return hashes.reduce((params, hash) => {
const split = hash.indexOf("=");
const key = hash.slice(0, split);
const val = hash.slice(split + 1);
return Object.assign(params, { [key]: decodeURIComponent(val) });
}, {});
};
Improving the @tbillington answer, when only have the key, the key loses the last letter and the value, instead of empty, is assigned with the key.
Eg ?debug&name=John&last-name
will be returned: {debu: "debug", name: "John", last-nam: "last-name"}
instead of: {debug: null, name: "John", last-name: null}
The code:
const decodeURLParams = search => {
const hashes = search.slice(search.indexOf("?") + 1).split("&");
return hashes.reduce((params, hash) => {
const split = hash.indexOf("=");
if (split < 0) {
return Object.assign(params, {
[hash]: null
});
}
const key = hash.slice(0, split);
const val = hash.slice(split + 1);
return Object.assign(params, { [key]: decodeURIComponent(val) });
}, {});
};
What about hash ? http://foo.com/#?a=1 What about hash ? http://foo.com/#/?a=1 What about hash ? http://foo.com/?b=2#?a=1
@cancerbergoSgx
How about cheating and treating as a search string?
// URL hash http://foo.com/?c=2#?a=1&b=works
new URLSearchParams(document.location.hash.replace('#','?')).get('b')
// returns 'works'
// Chrome Version 78.0.3904.87 (Official Build) (64-bit)
You would still need to parse document.location.search
and merge the two objects if you wanted a unified search plus hash parameters data structure.
What about hash ? http://foo.com/#?a=1 What about hash ? http://foo.com/#/?a=1 What about hash ? http://foo.com/?b=2#?a=1
How to handle the value with equal(=) sign? like:
keyA=value1&keyB=hff92hfgg=&keyC=value3
That's not a valid value @zerocoolElite, it needs to be URL-encoded (=
becomes %3D
when URL-encoded).
That's not a valid value @zerocoolElite, it needs to be URL-encoded (
=
becomes%3D
when URL-encoded).
Then the search string should be encoded first before passing to getUrlParams()?
I've tested all the functions above by https://runkit.com/embed/n18yhf9u2nqc and the conclusion is that url-parse and URLSearchParams is the rightest and most expected ones against the standard url - Node.js built-in module. Even the query-string module is not work as expected.
const search = '?abc=foo&def=[asf]&xyz==5&flag&&double&q=test1=test2&keyB=hff92hfgg=';
console.log((search));
const url = require('url')
console.log('0. url - the Node.js built-in module √');
console.log(url.parse(search, true).query);
console.log('1. queryString ×');
console.log(queryString.parse(search));
const parse = require('url-parse')
console.log('2. url-parse √');
console.log(parse(search, true).query);
console.log('3. URLSearchParams √');
console.log([...new URLSearchParams(search).entries()].reduce((q, [k, v]) => Object.assign(q, {[k]: v}), {}))
result:
?abc=foo&def=[asf]&xyz==5&flag&&double&q=test1=test2&keyB=hff92hfgg=
0. url - the Node.js built-in module √
Object {abc: "foo", def: "[asf]", double: "", flag: "", keyB: "hff92hfgg=", q: "test1=test2", xyz: "=5"}
1. queryString ×
Object {: null, abc: "foo", def: "[asf]", double: null, flag: null, keyB: "hff92hfgg=", q: "test1=test2", xyz: "=5"}
2. url-parse √
Object {abc: "foo", def: "[asf]", double: "", flag: "", keyB: "hff92hfgg=", q: "test1=test2", xyz: "=5"}
3. URLSearchParams √
Object {abc: "foo", def: "[asf]", double: "", flag: "", keyB: "hff92hfgg=", q: "test1=test2", xyz: "=5"}
So this fails if you have select multiple
- or any other input with multiple values that's named with square brackets:
<select name="statuses[]" multiple>...
Here's a slight adjustment, hopefully I'm not stepping on any edge cases:
function getUrlParams(search) {
const hashes = search.slice(search.indexOf('?') + 1).split('&')
const params = {}
hashes.map(hash => {
let [key, val] = hash.split('=')
key = decodeURIComponent(key)
if (key.indexOf('[') > -1) { // handle multiple type inputs
if (typeof params[key] === 'undefined') {
params[key] = []
}
params[key].push(decodeURIComponent(val))
} else {
params[key] = decodeURIComponent(val)
}
})
return params
}
Unfortunately even the native URLSearchParams
implementation doesn't handle array query parameters. :(
So, here's another take on array query parameters. Tested on
https://gist.github.com/pirate/9298155edda679510723?abc=foo&def=[asf]&xyz==5&flag&&double&q=test1=test2&keyB=hff92hfgg=&arr[]=ArrayValue1&arr[]=ArrayValue2&arr[]=ArrayValue3&arr2[0]=ArrayValue1&arr2[1]=ArrayValue2&arr2[2]=ArrayValue3&fields=kind,items(title,characteristics/length)
const getQueryParams = () => {
let params = {};
(new URLSearchParams(document.location.search)).forEach((d, e) => {
let a = decodeURIComponent(e), c = decodeURIComponent(d)
if (a.endsWith("[]")) {
a = a.replace("[]", ""), params[a] || (params[a] = []), params[a].push(c)
} else {
let b = a.match(/\[([a-z0-9_\/\s,.-])+\]$/g)
b ? (a = a.replace(b, ""), b = b[0].replace("[", "").replace("]", ""), params[a] || (params[a] = []), params[a][b] = c) : params[a] = c
}
})
return params
}
I create an alternative project if you want to use es6 module, with a very simple api:
query
@sharikovvladislav this gist is specifically for parsing the search portion of the URL. In your example that would be: