HashParams is a JavaScript library that lets you treat a URL hash (officially the "fragment identifier") as a set of named parameters. You can parse hash strings and build new ones.
var params = new HashParams("foreground", "background", "tags:set");
// User is on page.html#foreground=blue;background=green;tags=a,b. We can parse the hash:
params.setHash(window.location.hash);
// params.values.foreground === "blue"
// params.values.background === "green"
// params.values.tags is a Set containing "a" and "b"
// To build a hyperlink that changes foreground:
var newUrl = params.with("foreground", "red").getHash();
// newUrl is "#foreground=red;background=green;tags=a,b"HashParams is tested in the evergreen browsers (FireFox, Chrome, IE 11, and Edge). It may or may not work in older browsers.
You can install the latest release of HashParams using Bower:
bower install hashparams
Or get the bleeding-edge version by grabbing hashparams.js from the dist folder.
var params = new HashParams("foreground", "background");
function hashChanged() {
params.setHash(window.location.hash);
// do something with params.values
}
window.addEventListener("hashchange", hashChanged);
hashChanged();// In one of your React components:
var ... = React.createComponent(
...
getInitialState: function() {
return {
paramValues: {}
};
},
componentDidMount: function() {
var params = new HashParams("foreground", "background");
var self = this;
function hashChanged() {
params.setHash(window.location.hash);
self.setState({paramValues: params.values});
}
window.addEventListener("hashchange", hashChanged);
hashChanged();
},
render: function() {
// do something with this.state.paramValues
},
...
);The HashParams constructor takes a list of parameter names that your page expects, with optional types:
var params = new HashParams("foreground", "background", "tags:set");
// params.values.foreground and params.values.background are strings
// params.tags is a JavaScript Set objectCurrently supported types are:
scalar(default): a single string value.set: multiple (comma-separated) values, which are stored in a JavaScriptSetobject.
If you want, you can also pass instances of HashParams.types.scalar or HashParams.types.set.
new HashParams(new HashParams.types.scalar("foreground"), new HashParams.types.set("tags"))The current version does not support wildcards; you need to explicitly list every parameter name your page will use.
The values property contains the currently-parsed parameter values, as a JavaScript object.
When the HashParams instance is first created, values contains an empty string for each scalar parameter, and an empty Set for each set parameter:
var params = new HashParams("foreground", "background", "tags:set");
// params.values.foreground === ""
// params.values.background === ""
// params.values.tags is initialized to a new Set()You can modify values, though this is discouraged. It's better to use the with and without methods (see below).
The setHash method takes a string of the form #name1=value1;name2=value2 (the leading # is optional) and parses its values into the values property.
var params = new HashParams("foreground", "background", "tags:set");
// window.location.hash is "#foreground=blue;background=green;tags=a,b"
params.setHash(window.location.hash);
// params.values.foreground === "blue"
// params.values.background === "green"
// params.values.tags is a new Set() containing "a" and "b"The hash string can contain any characters from the Unicode Basic Multilingual Plane (U+0000 through U+FFFF), but currently won't work with UTF-16 surrogate pairs.
To ensure proper behavior as you navigate backwards and forwards through browser history, setHash clears any parameter values that are not included in the hash string:
var params = new HashParams("foreground", "background");
params.setHash("#foreground=blue;background=green");
// Then later:
params.setHash("#foreground=red");
// Now values.background has been reset to ""The with method returns a new clone of the HashParams object, with a new value for the specified parameter.
var params = new HashParams("foreground", "background");
params.setHash("#foreground=blue;background=green");
var newParams = params.with("foreground", "red");
expect(newParams.values).toEqual({foreground: "red", background: "green"});The original HashParams instance is not modified.
Typically you would call with and then immediately call getHash on the result, and put the resulting URL into a hyperlink. For example, in React:
<a href={params.with("foreground", "red").getHash()}>Change foreground to red</a>The without method returns a new clone of the HashParams object, with the specified parameter either cleared completely, or with a single value removed from the set.
If only parameterName is specifieid, the new clone contains a blank value ("" for scalars, new Set() for sets) for the specified parameter.
var params = new HashParams("foreground", "background", "tags:set");
params.setHash("#foreground=blue;background=green;tags=a,b");
var newParams = params.without("foreground").without("tags");
// newParams.foreground === ""
// newParams.background === "green" (unchanged)
// newParams.tags is an empty SetIf value is also specified and parameterName refers to a set-type parameter, that value is removed from the set.
var params = new HashParams("tags");
params.setHash("#tags=a,b");
var newParams = params.without("tags", "b");
// newParams.tags is a Set containing the value "a"The getHash method turns values back into a hash string.
The hash string is canonicalized, meaning if you had the same values in the HashParams (even if you added them in a different order), getHash will return the same string. Parameters are listed in the same order their names were originally passed to the constructor; sets list their values in sorted order; empty parameters are omitted.
var params = new HashParams("foreground", "background", "highlight");
params.values = {background: "green", foreground: "blue", highlight: ""};
expect(params.getHash()).toBe("#foreground=blue;background=green");
var params2 = new HashParams("tags:set");
params2.values.tags.add("b");
params2.values.tags.add("a");
expect(params2.getHash()).toBe("#tags=a,b");If you want to hack on the code, you'll need to install Node.js + npm and karma-cli (npm install -g karma-cli). You'll also need Python 2.7 (not version 3 or later, because for some ungodly reason the Karma test runner chooses to depend on technology that was obsolete back in 2008).
Then fork the HashParams repository, check out, and run:
npm install
You can start the tests with:
npm test
- Possible future features (ones I don't actually need, but may implement anyway):
- Support query strings as well as hashes.
- Parameters of type
array. - Parameters of type
number(e.g.#volume=11would result invalues.volume = 11as a number, rather than as a string). Likely constructor syntax:new HashParams("volume:number"). - Combined types, e.g.
tabStops:set<number>. - Wildcards (probably via regular expressions), e.g.
new HashParams.types.scalar(/.*/). - Maybe routing?
new HashParams("/products/:id:number", "foreground")+params.setHash("/products/5;foreground=green")could yieldparams.values = {id: 5, foreground: "green"}. You'd also need a way to name the routes sovaluescould tell you which route it matched. Suggestions welcome.
If you want something from the "possible future features" list, or something else not listed here, feel free to write up an issue, along with any details about how you'd like to use it. (Or better yet, send a pull request.)
- 0.2.0: Added the
settype and thewithoutmethod. - 0.1.0: First release. Scalar string values only.
setHash,with, andgetHashmethods.