aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/vendor/react-router
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2014-09-10 14:22:26 +1200
committerAldo Cortesi <aldo@nullcube.com>2014-09-10 14:23:10 +1200
commit0510c9b111aed03d0d3680db63614d50f231745c (patch)
tree0d2fec5d46a3cb984a8b12e36db2f44a1a8eaa5a /web/src/vendor/react-router
parent76982937a68a2adaf96ec2d258e369d7c871a609 (diff)
downloadmitmproxy-0510c9b111aed03d0d3680db63614d50f231745c.tar.gz
mitmproxy-0510c9b111aed03d0d3680db63614d50f231745c.tar.bz2
mitmproxy-0510c9b111aed03d0d3680db63614d50f231745c.zip
Client-side framework for web application
Diffstat (limited to 'web/src/vendor/react-router')
-rw-r--r--web/src/vendor/react-router/.bower.json38
-rw-r--r--web/src/vendor/react-router/CHANGELOG.md169
-rw-r--r--web/src/vendor/react-router/LICENSE19
-rw-r--r--web/src/vendor/react-router/README.md135
-rw-r--r--web/src/vendor/react-router/UPGRADE_GUIDE.md215
-rw-r--r--web/src/vendor/react-router/bower.json29
-rw-r--r--web/src/vendor/react-router/dist/react-router.js4635
-rw-r--r--web/src/vendor/react-router/dist/react-router.min.js2
-rw-r--r--web/src/vendor/react-router/docs/api/README.md32
-rw-r--r--web/src/vendor/react-router/docs/api/Router.md65
-rw-r--r--web/src/vendor/react-router/docs/api/components/DefaultRoute.md55
-rw-r--r--web/src/vendor/react-router/docs/api/components/Link.md71
-rw-r--r--web/src/vendor/react-router/docs/api/components/NotFoundRoute.md36
-rw-r--r--web/src/vendor/react-router/docs/api/components/Redirect.md59
-rw-r--r--web/src/vendor/react-router/docs/api/components/Route.md105
-rw-r--r--web/src/vendor/react-router/docs/api/components/RouteHandler.md108
-rw-r--r--web/src/vendor/react-router/docs/api/components/Routes.md69
-rw-r--r--web/src/vendor/react-router/docs/api/misc/Location.md66
-rw-r--r--web/src/vendor/react-router/docs/api/misc/transition.md24
-rw-r--r--web/src/vendor/react-router/docs/api/mixins/ActiveState.md58
-rw-r--r--web/src/vendor/react-router/docs/api/mixins/AsyncState.md115
-rw-r--r--web/src/vendor/react-router/docs/guides/overview.md373
-rw-r--r--web/src/vendor/react-router/docs/guides/path-matching.md83
-rw-r--r--web/src/vendor/react-router/eslint.json18
-rwxr-xr-xweb/src/vendor/react-router/scripts/build4
-rwxr-xr-xweb/src/vendor/react-router/scripts/build-examples18
-rwxr-xr-xweb/src/vendor/react-router/scripts/preview-release2
-rwxr-xr-xweb/src/vendor/react-router/scripts/release3
-rwxr-xr-xweb/src/vendor/react-router/scripts/test2
29 files changed, 6608 insertions, 0 deletions
diff --git a/web/src/vendor/react-router/.bower.json b/web/src/vendor/react-router/.bower.json
new file mode 100644
index 00000000..d8bf1ced
--- /dev/null
+++ b/web/src/vendor/react-router/.bower.json
@@ -0,0 +1,38 @@
+{
+ "name": "react-router",
+ "version": "0.7.0",
+ "homepage": "https://github.com/rackt/react-router",
+ "authors": [
+ "Ryan Florence",
+ "Michael Jackson"
+ ],
+ "description": "A complete routing library for React.js",
+ "main": "dist/react-router.js",
+ "keywords": [
+ "react",
+ "router"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "specs",
+ "modules",
+ "examples",
+ "script",
+ "CONTRIBUTING.md",
+ "karma.conf.js",
+ "package.json",
+ "webpack.config.js"
+ ],
+ "_release": "0.7.0",
+ "_resolution": {
+ "type": "version",
+ "tag": "v0.7.0",
+ "commit": "a000b732729f12b3445b4d917ec6474847ccd155"
+ },
+ "_source": "git://github.com/rpflorence/react-nested-router.git",
+ "_target": "*",
+ "_originalSource": "react-router"
+} \ No newline at end of file
diff --git a/web/src/vendor/react-router/CHANGELOG.md b/web/src/vendor/react-router/CHANGELOG.md
new file mode 100644
index 00000000..97714ed3
--- /dev/null
+++ b/web/src/vendor/react-router/CHANGELOG.md
@@ -0,0 +1,169 @@
+v0.7.0 - Tue, 02 Sep 2014 16:42:28 GMT
+--------------------------------------
+
+- [3796371](../../commit/3796371) [changed] Use Browserify to run specs
+- [0e649be](../../commit/0e649be) [changed] Use Browserify to build examples
+- [bb7b666](../../commit/bb7b666) [removed] .js files from repo root
+
+
+v0.6.1 - Sun, 31 Aug 2014 03:21:20 GMT
+--------------------------------------
+
+- [7536d96](../../commit/7536d96) [fixed] warning on links w/o params
+
+
+v0.6.0 - Fri, 29 Aug 2014 20:58:36 GMT
+--------------------------------------
+
+- [2a75f3e](../../commit/2a75f3e) [added] query argument to willTransitionTo
+- [b7e21bb](../../commit/b7e21bb) [fixed] Window scrolling
+- [5864531](../../commit/5864531) [changed] Default `<Redirect from>` to *
+- [1064881](../../commit/1064881) [changed] paths to inherit parents
+- [79caf99](../../commit/79caf99) [added] `<DefaultRoute name>`
+- [25adcab](../../commit/25adcab) [fixed] Using HashLocation without a preceeding /
+- [a63c940](../../commit/a63c940) [added] `<NotFoundRoute>`
+- [d5bd656](../../commit/d5bd656) [changed] path matching algorithm
+- [6526e70](../../commit/6526e70) [removed] location="disabled"
+- [8d2f3ed](../../commit/8d2f3ed) [changed] `<Link/>`s to take params property
+- [2a85b74](../../commit/2a85b74) [changed] handler keys to be optional
+
+
+v0.5.3 - Tue, 26 Aug 2014 03:36:42 GMT
+--------------------------------------
+
+- [273625a](../../commit/273625a) [fixed] Active state on `<Link>`s with key prop
+- [283d3f6](../../commit/283d3f6) [added] RouteStore#registerChildren
+- [a030648](../../commit/a030648) [changed] Relaxed MemoryStore invariant
+- [e028768](../../commit/e028768) [added] `<DefaultRoute>` component
+- [6878120](../../commit/6878120) [added] onAbortedTransition, onActiveStateChange, onTransitionError Routes props
+- [58073ca](../../commit/58073ca) [changed] Transition#cancelReason => abortReason
+- [6d1ae95](../../commit/6d1ae95) [fixed] sibling array route configs
+- [0e7a182](../../commit/0e7a182) [added] pluggable history implementations closes #166
+- [ca96f86](../../commit/ca96f86) [fixed] typo in Link
+- [f3dc513](../../commit/f3dc513) [added] onClick handler to `<Link />`
+- [b9f92f9](../../commit/b9f92f9) [changed] updated rf-changelog
+
+
+v0.5.2 - Thu, 07 Aug 2014 18:25:47 GMT
+--------------------------------------
+
+- [21f4f57](../../commit/21f4f57) [added] preserveScrollPosition Route/Routes props
+- [f3b4de8](../../commit/f3b4de8) [added] support for extra props in Links, fixes #170
+- [829a9ec](../../commit/829a9ec) [added] `<Redirect/>` component
+- [0a49665](../../commit/0a49665) [added] Router.makeHref
+- [2100b8c](../../commit/2100b8c) [changed] handlers receive route name
+- [154afba](../../commit/154afba) [changed] location of public modules
+
+
+v0.5.1 - Mon, 04 Aug 2014 22:16:38 GMT
+--------------------------------------
+
+- [08f5a69](../../commit/08f5a69) [fixed] location="history" fallback
+- [87b1c2a](../../commit/87b1c2a) [fixed] Navigation to root URL can fail
+- [760f021](../../commit/760f021) [fixed] infinite loop in RouteStore.unregisterRoute
+- [5fea685](../../commit/5fea685) [added] Router.AsyncState mixin
+- [395a590](../../commit/395a590) [changed] fallback to window.location for history
+- [2a3582e](../../commit/2a3582e) [changed] make URLStore.push idempotent
+- [4c4f87b](../../commit/4c4f87b) [fixed] alt click on Link should count as modified
+- [97c02f1](../../commit/97c02f1) [fixed] middle click on `<Link/>`
+
+
+v0.5.0 - Sat, 26 Jul 2014 22:38:36 GMT
+--------------------------------------
+
+- [5af49d4](../../commit/5af49d4) [changed] Split `<Routes>` component from `<Route>`
+
+
+v0.4.2 - Sat, 26 Jul 2014 18:23:43 GMT
+--------------------------------------
+
+- [2fc9976](../../commit/2fc9976) [fixed] eslint cleanup; trailing comma fix for IE
+- [b8018b1](../../commit/b8018b1) [added] animation example
+
+
+v0.4.1 - Thu, 24 Jul 2014 21:35:07 GMT
+--------------------------------------
+
+- [8152d67](../../commit/8152d67) [changed] repo location to rackt/react-router
+- [0ac4dea](../../commit/0ac4dea) [removed] Dependency on react/lib/emptyFunction
+
+
+v0.4.0 - Thu, 24 Jul 2014 19:41:04 GMT
+--------------------------------------
+
+- [0be4bf7](../../commit/0be4bf7) [changed] npm registry name to react-router :D
+
+
+v0.3.5 - Wed, 23 Jul 2014 14:52:30 GMT
+--------------------------------------
+
+- [0a7298c](../../commit/0a7298c) [removed] browserify.transforms from package.json
+- [ebf54ab](../../commit/ebf54ab) [removed] Dependency on react/lib/merge
+
+
+v0.3.4 - Tue, 22 Jul 2014 21:02:48 GMT
+--------------------------------------
+
+- [2598837](../../commit/2598837) [fixed] bower build
+- [8c428ff](../../commit/8c428ff) [fixed] dist min build
+
+
+v0.3.3 - Tue, 22 Jul 2014 20:46:57 GMT
+--------------------------------------
+
+- [92b9077](../../commit/92b9077) [changed] file name of dist builds
+
+
+v0.3.2 - Tue, 22 Jul 2014 19:47:41 GMT
+--------------------------------------
+
+- [3a4732e](../../commit/3a4732e) [changed] global export to ReactRouter
+
+
+v0.3.1 - Tue, 22 Jul 2014 19:40:14 GMT
+--------------------------------------
+
+- [baf2257](../../commit/baf2257) [fixed] dist files
+
+
+v0.3.0 - Tue, 22 Jul 2014 19:34:11 GMT
+--------------------------------------
+
+- [e827870](../../commit/e827870) [added] bower support
+- [58e7b98](../../commit/58e7b98) [changed] activeRoute -> activeRouteHandler
+- [0177cdd](../../commit/0177cdd) [fixed] Pass the correct component instance to willTransitionFrom hooks
+- [3b590e0](../../commit/3b590e0) [changed] Upgrade to React 0.11.0
+- [51e1be2](../../commit/51e1be2) [fixed] Use peerDeps
+- [a8df2f0](../../commit/a8df2f0) [added] Browser builds for version 0.2.1
+- [bb066b8](../../commit/bb066b8) [added] Browser build script
+- [baf79b6](../../commit/baf79b6) [fixed] Avoid some warnings
+- [8d30552](../../commit/8d30552) [changed] README to make use of activeRoute clearer in JSX.
+- [991dede](../../commit/991dede) [changed] activeRoute is a function that returns null when no child routes are active.
+- [73570ed](../../commit/73570ed) [changed] activeRoute can render with props and children.
+- [8562482](../../commit/8562482) [added] ActiveState mixin
+- [616f8bf](../../commit/616f8bf) [changed] Preserve forward slashes in URL params
+- [6c74c69](../../commit/6c74c69) [changed] Combine URL helpers into URL module
+
+
+v0.2.1 - Mon, 14 Jul 2014 17:31:21 GMT
+--------------------------------------
+
+- [0f86654](../../commit/0f86654) [fixed] checks for class instead of components
+- [a3d6e2a](../../commit/a3d6e2a) [changed] Render empty div before transition hooks
+- [f474ab1](../../commit/f474ab1) [changed] '.' is no longer a path delimeter
+- [f3dcdd7](../../commit/f3dcdd7) [fixed] injectParams invariant should not throw on values that coerce to false.
+- [468bf3b](../../commit/468bf3b) [changed] Deprecate Router interface
+- [31d1a6e](../../commit/31d1a6e) [added] renderComponentToString()
+
+
+v0.2.0 - Tue, 24 Jun 2014 04:59:24 GMT
+--------------------------------------
+
+- [468bf3b](../../commit/468bf3b) [changed] Deprecate Router interface
+- [31d1a6e](../../commit/31d1a6e) [added] renderComponentToString()
+
+
+v0.1.0 - Thu, 19 Jun 2014 19:11:38 GMT
+--------------------------------------
+
+
diff --git a/web/src/vendor/react-router/LICENSE b/web/src/vendor/react-router/LICENSE
new file mode 100644
index 00000000..04d1d06e
--- /dev/null
+++ b/web/src/vendor/react-router/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Ryan Florence, Michael Jackson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/web/src/vendor/react-router/README.md b/web/src/vendor/react-router/README.md
new file mode 100644
index 00000000..a3746aaf
--- /dev/null
+++ b/web/src/vendor/react-router/README.md
@@ -0,0 +1,135 @@
+React Router
+============
+
+[![Build Status](https://travis-ci.org/rackt/react-router.svg?branch=master)](https://travis-ci.org/rackt/react-router)
+
+A complete routing library for React.
+
+Docs
+----
+
+- [Guide: Overview](/docs/guides/overview.md)
+- [API](/docs/api/)
+
+Important Notes
+---------------
+
+### **** NPM USERS THIS PACKAGE MOVED ****
+
+This package has moved from `react-nested-router` to `react-router`.
+
+Update your package.json to point to the new package, or if you aren't
+ready to update, make sure your package.json specifically points to
+`0.3.5` or less, `0.3.6` just throws an error telling you the package
+has moved.
+
+### SemVer
+
+Before our `1.0` release, breaking API changes will cause a bump to
+`0.x`. For example, `0.4.1` and `0.4.8` will have the same API, but
+`0.5.0` will have breaking changes.
+
+Please refer to the [upgrade guide](/UPGRADE_GUIDE.md) and
+[changelog](/CHANGELOG.md) when upgrading.
+
+Installation
+------------
+
+```sh
+npm install react-router
+# or
+bower install react-router
+```
+
+This library is written with CommonJS modules. If you are using
+browserify, webpack, or similar, you can consume it like anything else
+installed from npm.
+
+There is also a UMD build available on bower, find the library on
+`window.ReactRouter`.
+
+Features
+--------
+
+- Nested views mapped to nested routes
+- Modular construction of route hierarchy
+- Fully asynchronous transition hooks
+- Transition abort / redirect / retry
+- Dynamic segments
+- Query parameters
+- Links with automatic `.active` class when their route is active
+- Multiple root routes
+- Hash or HTML5 history URLs
+
+Check out the `examples` directory to see how simple previously complex UI
+and workflows are to create.
+
+What's it look like?
+--------------------
+
+```js
+React.renderComponent((
+ <Routes location="history">
+ <Route path="/" handler={App}>
+ <DefaultRoute handler={Home} />
+ <Route name="about" handler={About} />
+ <Route name="users" handler={Users}>
+ <Route name="recent-users" path="recent" handler={RecentUsers} />
+ <Route name="user" path="/user/:userId" handler={User} />
+ <NotFoundRoute handler={UserRouteNotFound}/>
+ </Route>
+ </Route>
+ <NotFoundRoute handler={NotFound}/>
+ <Redirect path="company" to="about" />
+ </Routes>
+), document.body);
+```
+
+All of the `handler`s will render inside their parent route `handler`.
+
+See more in the [overview guide](/docs/guides/overview.md).
+
+Benefits of This Approach
+-------------------------
+
+1. **Incredible screen-creation productivity** - There is only one
+ use-case when a user visits a route: render something. Every user
+ interface has layers (or nesting) whether its a simple navbar or
+ multiple levels of master-detail. Coupling nested routes to these
+ nested views gets rid of a ton of work for the developer to wire all
+ of it together when the user switches routes. Adding new screens
+ could not get faster.
+
+2. **Immediate understanding of application structure** - When routes
+ are declared in one place, developers can easily construct a mental
+ image of the application. It's essentially a sitemap. There's not a
+ better way to get so much information about your app this quickly.
+
+3. **Code tractability** - When a developer gets a ticket to fix a bug
+ at as specific url they simply 1) look at the route config, then 2)
+ go find the handler for that route. Every entry point into your
+ application is represented by these routes.
+
+4. **URLs are your first thought, not an after-thought** - With React
+ Router, you don't get UI on the page without configuring a url first.
+ Fortunately, its wildly productive this way, too.
+
+Related Modules
+---------------
+
+- [rnr-constrained-route](https://github.com/bjyoungblood/rnr-constrained-route) - validate paths
+ and parameters on route handlers.
+- [react-router-bootstrap](https://github.com/mtscout6/react-router-bootstrap) - Integration with [react-bootstrap](https://github.com/react-bootstrap/react-bootstrap) components.
+
+Contributing
+------------
+
+Please see [CONTRIBUTING](CONTRIBUTING.md)
+
+Thanks, Ember
+-------------
+
+This library is highly inspired by the Ember.js routing API. In general,
+its a translation of the Ember router api to React. Huge thanks to the
+Ember team for solving the hardest part already.
+
diff --git a/web/src/vendor/react-router/UPGRADE_GUIDE.md b/web/src/vendor/react-router/UPGRADE_GUIDE.md
new file mode 100644
index 00000000..00295041
--- /dev/null
+++ b/web/src/vendor/react-router/UPGRADE_GUIDE.md
@@ -0,0 +1,215 @@
+Upgrade Guide
+=============
+
+To see discussion around these API changes, please refer to the
+[changelog](/CHANGELOG.md) and visit the commits and issues they
+reference.
+
+0.6.x -> 0.7.x
+--------------
+
+The package root modules were removed. Please import modules from the
+`Router` default export.
+
+```js
+// 0.6.x
+var Link = require('react-router/Link');
+
+// 0.7.x
+var Router = require('react-router');
+var Link = Router.Link;
+```
+
+0.5.x -> 0.6.x
+--------------
+
+### Path Matching
+
+Paths that start with `/` are absolute and work exactly as they used to.
+Paths that don't start with `/` are now relative, meaning they extend
+their parent route.
+
+Simply add `/` in front of all your paths to keep things working.
+
+```xml
+<!-- 0.5.x -->
+<Route path="/foo">
+ <Route path="bar"/>
+</Route>
+
+<!-- 0.6.x -->
+<Route path="/foo">
+ <Route path="/bar"/>
+</Route>
+```
+
+Though, you may want to embrace this new feature:
+
+```xml
+<!-- 0.5.x -->
+<Route path="/course/:courseId">
+ <Route path="/course/:courseId/assignments"/>
+ <Route path="/course/:courseId/announcements"/>
+</Route>
+
+<!-- 0.6.x -->
+<Route path="/course/:courseId">
+ <Route path="assignments"/>
+ <Route path="announcements"/>
+</Route>
+```
+
+Also `.` is no longer matched in dynamic segments.
+
+```xml
+<!-- 0.5.x -->
+<Route path="/file/:filename" />
+
+<!-- 0.6.x -->
+<Route path="/file/:filename.?:ext?" />
+
+<!--
+ or for a looser match to allow for multiple `.` note that the data
+ will be available on `this.props.params.splat` instead of
+ `this.props.params.filename`
+-->
+<Route path="/file/*" />
+```
+
+### Link params
+
+Links should now pass their params in the `params` property, though the
+old behavior will still work, you should update your code soon because
+it will be removed by `v1.0`
+
+```js
+// 0.5.x
+<Link to="user" userId="123"/>
+
+// 0.6.x
+<Link to="user" params={{userId: "123"}}/>
+```
+
+### Dynamic Segments, keys, and lifecycle methods
+
+If you have dynamic segments and are depending on `getInitialState`,
+`componentWillMount`, or `componentDidMount` to fire between transitions
+to the same route--like `users/123` and `users/456`--then you have two
+options:
+
+- add `addHandlerKey={true}` to your route and keep the previous
+ behavior (but lose out on performance), or
+- implement `componentWillReceiveProps`.
+
+```js
+// 0.5.x
+<Route handler={User} path="/user/:userId"/>
+
+// 0.6.x
+<Route handler={User} path="/user/:userId" addHandlerKey={true} />
+
+// 0.5.x
+var User = React.createClass({
+ getInitialState: function() {
+ return {
+ user: getUser(this.props.params.userId);
+ }
+ }
+});
+
+// 0.6.x
+var User = React.createClass({
+ getInitialState: function() {
+ return this.getState();
+ },
+
+ componentWillReceiveProps: function(newProps) {
+ this.setState(this.getState(newProps));
+ },
+
+ getState: function(props) {
+ props = props || this.props;
+ return {
+ user: getUser(props.params.userId)
+ };
+ }
+});
+```
+
+0.4.x -> 0.5.x
+--------------
+
+We brought back `<Routes/>`.
+
+```js
+// 0.4.x
+var routes = (
+ <Route handler={App} location="history">
+ <Route name="about" handler="about"/>
+ </Route>
+);
+
+// 0.5.x
+var routes = (
+ <Routes location="history">
+ <Route handler={App}>
+ <Route name="about" handler="about"/>
+ </Route>
+ </Routes>
+);
+```
+
+0.3.x -> 0.4.x
+--------------
+
+NPM users should point their apps to `react-router` instead of
+`react-nested-router`. Make sure to `npm prune`!
+
+0.2.x -> 0.3.x
+--------------
+
+- React `0.11.x` is now required.
+- `this.props.activeRoute` became `this.props.activeRouteHandler()`
+
+```js
+// 0.2.x
+
+var App = React.createClass({
+ render: function() {
+ return (
+ <div>
+ {this.props.activeRoute}
+ </div>
+ );
+ }
+});
+
+// 0.3.x
+var App = React.createClass({
+ render: function() {
+ // now you can send extra props to the active route handler
+ // and use the new jsx syntax
+ // <this.props.activeRouteHandler extraProp={something}/>
+ return (
+ <div>
+ {this.props.activeRouteHandler()}
+ </div>
+ );
+ }
+});
+```
+
+0.1.x -> 0.2.x
+--------------
+
+The `Router` function was removed.
+
+```js
+// 0.1.x
+var router = Router(routes);
+router.renderComponent(element);
+
+// 0.2.x
+React.renderComponent(routes, element);
+```
+
diff --git a/web/src/vendor/react-router/bower.json b/web/src/vendor/react-router/bower.json
new file mode 100644
index 00000000..ba6d4be9
--- /dev/null
+++ b/web/src/vendor/react-router/bower.json
@@ -0,0 +1,29 @@
+{
+ "name": "react-router",
+ "version": "0.7.0",
+ "homepage": "https://github.com/rackt/react-router",
+ "authors": [
+ "Ryan Florence",
+ "Michael Jackson"
+ ],
+ "description": "A complete routing library for React.js",
+ "main": "dist/react-router.js",
+ "keywords": [
+ "react",
+ "router"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "specs",
+ "modules",
+ "examples",
+ "script",
+ "CONTRIBUTING.md",
+ "karma.conf.js",
+ "package.json",
+ "webpack.config.js"
+ ]
+} \ No newline at end of file
diff --git a/web/src/vendor/react-router/dist/react-router.js b/web/src/vendor/react-router/dist/react-router.js
new file mode 100644
index 00000000..942a2fc7
--- /dev/null
+++ b/web/src/vendor/react-router/dist/react-router.js
@@ -0,0 +1,4635 @@
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.ReactRouter=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
+var LocationDispatcher = _dereq_('../dispatchers/LocationDispatcher');
+var makePath = _dereq_('../utils/makePath');
+
+/**
+ * Actions that modify the URL.
+ */
+var LocationActions = {
+
+ PUSH: 'push',
+ REPLACE: 'replace',
+ POP: 'pop',
+ UPDATE_SCROLL: 'update-scroll',
+
+ /**
+ * Transitions to the URL specified in the arguments by pushing
+ * a new URL onto the history stack.
+ */
+ transitionTo: function (to, params, query) {
+ LocationDispatcher.handleViewAction({
+ type: LocationActions.PUSH,
+ path: makePath(to, params, query)
+ });
+ },
+
+ /**
+ * Transitions to the URL specified in the arguments by replacing
+ * the current URL in the history stack.
+ */
+ replaceWith: function (to, params, query) {
+ LocationDispatcher.handleViewAction({
+ type: LocationActions.REPLACE,
+ path: makePath(to, params, query)
+ });
+ },
+
+ /**
+ * Transitions to the previous URL.
+ */
+ goBack: function () {
+ LocationDispatcher.handleViewAction({
+ type: LocationActions.POP
+ });
+ },
+
+ /**
+ * Updates the window's scroll position to the last known position
+ * for the current URL path.
+ */
+ updateScroll: function () {
+ LocationDispatcher.handleViewAction({
+ type: LocationActions.UPDATE_SCROLL
+ });
+ }
+
+};
+
+module.exports = LocationActions;
+
+},{"../dispatchers/LocationDispatcher":8,"../utils/makePath":26}],2:[function(_dereq_,module,exports){
+var merge = _dereq_('react/lib/merge');
+var Route = _dereq_('./Route');
+
+/**
+ * A <DefaultRoute> component is a special kind of <Route> that
+ * renders when its parent matches but none of its siblings do.
+ * Only one such route may be used at any given level in the
+ * route hierarchy.
+ */
+function DefaultRoute(props) {
+ return Route(
+ merge(props, {
+ path: null,
+ isDefault: true
+ })
+ );
+}
+
+module.exports = DefaultRoute;
+
+},{"./Route":6,"react/lib/merge":44}],3:[function(_dereq_,module,exports){
+var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
+var ActiveState = _dereq_('../mixins/ActiveState');
+var transitionTo = _dereq_('../actions/LocationActions').transitionTo;
+var withoutProperties = _dereq_('../utils/withoutProperties');
+var hasOwnProperty = _dereq_('../utils/hasOwnProperty');
+var makeHref = _dereq_('../utils/makeHref');
+var warning = _dereq_('react/lib/warning');
+
+function isLeftClickEvent(event) {
+ return event.button === 0;
+}
+
+function isModifiedEvent(event) {
+ return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
+}
+
+/**
+ * DEPRECATED: A map of <Link> component props that are reserved for use by the
+ * router and/or React. All other props are used as params that are
+ * interpolated into the link's path.
+ */
+var RESERVED_PROPS = {
+ to: true,
+ key: true,
+ className: true,
+ activeClassName: true,
+ query: true,
+ onClick:true,
+ children: true // ReactChildren
+};
+
+/**
+ * <Link> components are used to create an <a> element that links to a route.
+ * When that route is active, the link gets an "active" class name (or the
+ * value of its `activeClassName` prop).
+ *
+ * For example, assuming you have the following route:
+ *
+ * <Route name="showPost" path="/posts/:postId" handler={Post}/>
+ *
+ * You could use the following component to link to that route:
+ *
+ * <Link to="showPost" params={{postId: "123"}} />
+ *
+ * In addition to params, links may pass along query string parameters
+ * using the `query` prop.
+ *
+ * <Link to="showPost" params={{postId: "123"}} query={{show:true}}/>
+ */
+var Link = React.createClass({
+
+ displayName: 'Link',
+
+ mixins: [ ActiveState ],
+
+ statics: {
+
+ // TODO: Deprecate passing props as params in v1.0
+ getUnreservedProps: function (props) {
+ var props = withoutProperties(props, RESERVED_PROPS);
+ warning(
+ Object.keys(props).length === 0,
+ 'Passing props for params on <Link>s is deprecated, '+
+ 'please use the `params` property.'
+ );
+ return props;
+ },
+
+ /**
+ * Returns a hash of URL parameters to use in this <Link>'s path.
+ */
+ getParams: function (props) {
+ return props.params || Link.getUnreservedProps(props);
+ }
+
+ },
+
+ propTypes: {
+ to: React.PropTypes.string.isRequired,
+ activeClassName: React.PropTypes.string.isRequired,
+ params: React.PropTypes.object,
+ query: React.PropTypes.object,
+ onClick: React.PropTypes.func
+ },
+
+ getDefaultProps: function () {
+ return {
+ activeClassName: 'active'
+ };
+ },
+
+ getInitialState: function () {
+ return {
+ isActive: false
+ };
+ },
+
+ /**
+ * Returns the value of the "href" attribute to use on the DOM element.
+ */
+ getHref: function () {
+ return makeHref(this.props.to, Link.getParams(this.props), this.props.query);
+ },
+
+ /**
+ * Returns the value of the "class" attribute to use on the DOM element, which contains
+ * the value of the activeClassName property when this <Link> is active.
+ */
+ getClassName: function () {
+ var className = this.props.className || '';
+
+ if (this.state.isActive)
+ return className + ' ' + this.props.activeClassName;
+
+ return className;
+ },
+
+ componentWillReceiveProps: function (nextProps) {
+ var params = Link.getParams(nextProps);
+
+ this.setState({
+ isActive: Link.isActive(nextProps.to, params, nextProps.query)
+ });
+ },
+
+ updateActiveState: function () {
+ this.setState({
+ isActive: Link.isActive(this.props.to, Link.getParams(this.props), this.props.query)
+ });
+ },
+
+ handleClick: function (event) {
+ var allowTransition = true;
+ var ret;
+
+ if (this.props.onClick)
+ ret = this.props.onClick(event);
+
+ if (isModifiedEvent(event) || !isLeftClickEvent(event))
+ return;
+
+ if (ret === false || event.defaultPrevented === true)
+ allowTransition = false;
+
+ event.preventDefault();
+
+ if (allowTransition)
+ transitionTo(this.props.to, Link.getParams(this.props), this.props.query);
+ },
+
+ render: function () {
+ var props = {
+ href: this.getHref(),
+ className: this.getClassName(),
+ onClick: this.handleClick
+ };
+
+ // pull in props without overriding
+ for (var propName in this.props) {
+ if (hasOwnProperty(this.props, propName) && hasOwnProperty(props, propName) === false)
+ props[propName] = this.props[propName];
+ }
+
+ return React.DOM.a(props, this.props.children);
+ }
+
+});
+
+module.exports = Link;
+
+},{"../actions/LocationActions":1,"../mixins/ActiveState":15,"../utils/hasOwnProperty":24,"../utils/makeHref":25,"../utils/withoutProperties":29,"react/lib/warning":48}],4:[function(_dereq_,module,exports){
+var merge = _dereq_('react/lib/merge');
+var Route = _dereq_('./Route');
+
+/**
+ * A <NotFoundRoute> is a special kind of <Route> that
+ * renders when the beginning of its parent's path matches
+ * but none of its siblings do, including any <DefaultRoute>.
+ * Only one such route may be used at any given level in the
+ * route hierarchy.
+ */
+function NotFoundRoute(props) {
+ return Route(
+ merge(props, {
+ path: null,
+ catchAll: true
+ })
+ );
+}
+
+module.exports = NotFoundRoute;
+
+},{"./Route":6,"react/lib/merge":44}],5:[function(_dereq_,module,exports){
+var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
+var Route = _dereq_('./Route');
+
+function createRedirectHandler(to) {
+ return React.createClass({
+ statics: {
+ willTransitionTo: function (transition, params, query) {
+ transition.redirect(to, params, query);
+ }
+ },
+
+ render: function () {
+ return null;
+ }
+ });
+}
+
+/**
+ * A <Redirect> component is a special kind of <Route> that always
+ * redirects to another route when it matches.
+ */
+function Redirect(props) {
+ return Route({
+ name: props.name,
+ path: props.from || props.path || '*',
+ handler: createRedirectHandler(props.to)
+ });
+}
+
+module.exports = Redirect;
+
+},{"./Route":6}],6:[function(_dereq_,module,exports){
+var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
+var withoutProperties = _dereq_('../utils/withoutProperties');
+
+/**
+ * A map of <Route> component props that are reserved for use by the
+ * router and/or React. All other props are considered "static" and
+ * are passed through to the route handler.
+ */
+var RESERVED_PROPS = {
+ handler: true,
+ path: true,
+ defaultRoute: true,
+ paramNames: true,
+ children: true // ReactChildren
+};
+
+/**
+ * <Route> components specify components that are rendered to the page when the
+ * URL matches a given pattern.
+ *
+ * Routes are arranged in a nested tree structure. When a new URL is requested,
+ * the tree is searched depth-first to find a route whose path matches the URL.
+ * When one is found, all routes in the tree that lead to it are considered
+ * "active" and their components are rendered into the DOM, nested in the same
+ * order as they are in the tree.
+ *
+ * Unlike Ember, a nested route's path does not build upon that of its parents.
+ * This may seem like it creates more work up front in specifying URLs, but it
+ * has the nice benefit of decoupling nested UI from "nested" URLs.
+ *
+ * The preferred way to configure a router is using JSX. The XML-like syntax is
+ * a great way to visualize how routes are laid out in an application.
+ *
+ * React.renderComponent((
+ * <Routes handler={App}>
+ * <Route name="login" handler={Login}/>
+ * <Route name="logout" handler={Logout}/>
+ * <Route name="about" handler={About}/>
+ * </Routes>
+ * ), document.body);
+ *
+ * If you don't use JSX, you can also assemble a Router programmatically using
+ * the standard React component JavaScript API.
+ *
+ * React.renderComponent((
+ * Routes({ handler: App },
+ * Route({ name: 'login', handler: Login }),
+ * Route({ name: 'logout', handler: Logout }),
+ * Route({ name: 'about', handler: About })
+ * )
+ * ), document.body);
+ *
+ * Handlers for Route components that contain children can render their active
+ * child route using the activeRouteHandler prop.
+ *
+ * var App = React.createClass({
+ * render: function () {
+ * return (
+ * <div class="application">
+ * {this.props.activeRouteHandler()}
+ * </div>
+ * );
+ * }
+ * });
+ */
+var Route = React.createClass({
+
+ displayName: 'Route',
+
+ statics: {
+
+ getUnreservedProps: function (props) {
+ return withoutProperties(props, RESERVED_PROPS);
+ },
+
+ },
+
+ propTypes: {
+ preserveScrollPosition: React.PropTypes.bool.isRequired,
+ handler: React.PropTypes.any.isRequired,
+ path: React.PropTypes.string,
+ name: React.PropTypes.string
+ },
+
+ getDefaultProps: function () {
+ return {
+ preserveScrollPosition: false
+ };
+ },
+
+ render: function () {
+ throw new Error(
+ 'The <Route> component should not be rendered directly. You may be ' +
+ 'missing a <Routes> wrapper around your list of routes.'
+ );
+ }
+
+});
+
+module.exports = Route;
+
+},{"../utils/withoutProperties":29}],7:[function(_dereq_,module,exports){
+var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
+var warning = _dereq_('react/lib/warning');
+var copyProperties = _dereq_('react/lib/copyProperties');
+var Promise = _dereq_('when/lib/Promise');
+var LocationActions = _dereq_('../actions/LocationActions');
+var Route = _dereq_('../components/Route');
+var Path = _dereq_('../utils/Path');
+var Redirect = _dereq_('../utils/Redirect');
+var Transition = _dereq_('../utils/Transition');
+var DefaultLocation = _dereq_('../locations/DefaultLocation');
+var HashLocation = _dereq_('../locations/HashLocation');
+var HistoryLocation = _dereq_('../locations/HistoryLocation');
+var RefreshLocation = _dereq_('../locations/RefreshLocation');
+var ActiveStore = _dereq_('../stores/ActiveStore');
+var PathStore = _dereq_('../stores/PathStore');
+var RouteStore = _dereq_('../stores/RouteStore');
+
+/**
+ * The ref name that can be used to reference the active route component.
+ */
+var REF_NAME = '__activeRoute__';
+
+/**
+ * A hash of { name, location } pairs of all locations.
+ */
+var NAMED_LOCATIONS = {
+ hash: HashLocation,
+ history: HistoryLocation,
+ refresh: RefreshLocation
+};
+
+/**
+ * The default handler for aborted transitions. Redirects replace
+ * the current URL and all others roll it back.
+ */
+function defaultAbortedTransitionHandler(transition) {
+ var reason = transition.abortReason;
+
+ if (reason instanceof Redirect) {
+ LocationActions.replaceWith(reason.to, reason.params, reason.query);
+ } else {
+ LocationActions.goBack();
+ }
+}
+
+/**
+ * The default handler for active state updates.
+ */
+function defaultActiveStateChangeHandler(state) {
+ ActiveStore.updateState(state);
+}
+
+/**
+ * The default handler for errors that were thrown asynchronously
+ * while transitioning. The default behavior is to re-throw the
+ * error so that it isn't silently swallowed.
+ */
+function defaultTransitionErrorHandler(error) {
+ throw error; // This error probably originated in a transition hook.
+}
+
+function maybeUpdateScroll(routes, rootRoute) {
+ if (!routes.props.preserveScrollPosition && !rootRoute.props.preserveScrollPosition)
+ LocationActions.updateScroll();
+}
+
+/**
+ * The <Routes> component configures the route hierarchy and renders the
+ * route matching the current location when rendered into a document.
+ *
+ * See the <Route> component for more details.
+ */
+var Routes = React.createClass({
+
+ displayName: 'Routes',
+
+ propTypes: {
+ onAbortedTransition: React.PropTypes.func.isRequired,
+ onActiveStateChange: React.PropTypes.func.isRequired,
+ onTransitionError: React.PropTypes.func.isRequired,
+ preserveScrollPosition: React.PropTypes.bool,
+ location: function (props, propName, componentName) {
+ var location = props[propName];
+
+ if (typeof location === 'string' && !(location in NAMED_LOCATIONS))
+ return new Error('Unknown location "' + location + '", see ' + componentName);
+ }
+ },
+
+ getDefaultProps: function () {
+ return {
+ onAbortedTransition: defaultAbortedTransitionHandler,
+ onActiveStateChange: defaultActiveStateChangeHandler,
+ onTransitionError: defaultTransitionErrorHandler,
+ preserveScrollPosition: false,
+ location: DefaultLocation
+ };
+ },
+
+ getInitialState: function () {
+ return {
+ routes: RouteStore.registerChildren(this.props.children, this)
+ };
+ },
+
+ getLocation: function () {
+ var location = this.props.location;
+
+ if (typeof location === 'string')
+ return NAMED_LOCATIONS[location];
+
+ return location;
+ },
+
+ componentWillMount: function () {
+ PathStore.setup(this.getLocation());
+ PathStore.addChangeListener(this.handlePathChange);
+ },
+
+ componentDidMount: function () {
+ this.handlePathChange();
+ },
+
+ componentWillUnmount: function () {
+ PathStore.removeChangeListener(this.handlePathChange);
+ },
+
+ handlePathChange: function () {
+ this.dispatch(PathStore.getCurrentPath());
+ },
+
+ /**
+ * Performs a depth-first search for the first route in the tree that matches
+ * on the given path. Returns an array of all routes in the tree leading to
+ * the one that matched in the format { route, params } where params is an
+ * object that contains the URL parameters relevant to that route. Returns
+ * null if no route in the tree matches the path.
+ *
+ * React.renderComponent(
+ * <Routes>
+ * <Route handler={App}>
+ * <Route name="posts" handler={Posts}/>
+ * <Route name="post" path="/posts/:id" handler={Post}/>
+ * </Route>
+ * </Routes>
+ * ).match('/posts/123'); => [ { route: <AppRoute>, params: {} },
+ * { route: <PostRoute>, params: { id: '123' } } ]
+ */
+ match: function (path) {
+ return findMatches(Path.withoutQuery(path), this.state.routes, this.props.defaultRoute, this.props.notFoundRoute);
+ },
+
+ /**
+ * Performs a transition to the given path and returns a promise for the
+ * Transition object that was used.
+ *
+ * In order to do this, the router first determines which routes are involved
+ * in the transition beginning with the current route, up the route tree to
+ * the first parent route that is shared with the destination route, and back
+ * down the tree to the destination route. The willTransitionFrom static
+ * method is invoked on all route handlers we're transitioning away from, in
+ * reverse nesting order. Likewise, the willTransitionTo static method
+ * is invoked on all route handlers we're transitioning to.
+ *
+ * Both willTransitionFrom and willTransitionTo hooks may either abort or
+ * redirect the transition. If they need to resolve asynchronously, they may
+ * return a promise.
+ *
+ * Any error that occurs asynchronously during the transition is re-thrown in
+ * the top-level scope unless returnRejectedPromise is true, in which case a
+ * rejected promise is returned so the caller may handle the error.
+ *
+ * Note: This function does not update the URL in a browser's location bar.
+ * If you want to keep the URL in sync with transitions, use Router.transitionTo,
+ * Router.replaceWith, or Router.goBack instead.
+ */
+ dispatch: function (path, returnRejectedPromise) {
+ var transition = new Transition(path);
+ var routes = this;
+
+ var promise = runTransitionHooks(routes, transition).then(function (nextState) {
+ if (transition.isAborted) {
+ routes.props.onAbortedTransition(transition);
+ } else if (nextState) {
+ routes.setState(nextState);
+ routes.props.onActiveStateChange(nextState);
+
+ // TODO: add functional test
+ var rootMatch = getRootMatch(nextState.matches);
+
+ if (rootMatch)
+ maybeUpdateScroll(routes, rootMatch.route);
+ }
+
+ return transition;
+ });
+
+ if (!returnRejectedPromise) {
+ promise = promise.then(undefined, function (error) {
+ // Use setTimeout to break the promise chain.
+ setTimeout(function () {
+ routes.props.onTransitionError(error);
+ });
+ });
+ }
+
+ return promise;
+ },
+
+ render: function () {
+ if (!this.state.path)
+ return null;
+
+ var matches = this.state.matches;
+ if (matches.length) {
+ // matches[0] corresponds to the top-most match
+ return matches[0].route.props.handler(computeHandlerProps(matches, this.state.activeQuery));
+ } else {
+ return null;
+ }
+ }
+
+});
+
+function findMatches(path, routes, defaultRoute, notFoundRoute) {
+ var matches = null, route, params;
+
+ for (var i = 0, len = routes.length; i < len; ++i) {
+ route = routes[i];
+
+ // Check the subtree first to find the most deeply-nested match.
+ matches = findMatches(path, route.props.children, route.props.defaultRoute, route.props.notFoundRoute);
+
+ if (matches != null) {
+ var rootParams = getRootMatch(matches).params;
+
+ params = route.props.paramNames.reduce(function (params, paramName) {
+ params[paramName] = rootParams[paramName];
+ return params;
+ }, {});
+
+ matches.unshift(makeMatch(route, params));
+
+ return matches;
+ }
+
+ // No routes in the subtree matched, so check this route.
+ params = Path.extractParams(route.props.path, path);
+
+ if (params)
+ return [ makeMatch(route, params) ];
+ }
+
+ // No routes matched, so try the default route if there is one.
+ if (defaultRoute && (params = Path.extractParams(defaultRoute.props.path, path)))
+ return [ makeMatch(defaultRoute, params) ];
+
+ // Last attempt: does the "not found" route match?
+ if (notFoundRoute && (params = Path.extractParams(notFoundRoute.props.path, path)))
+ return [ makeMatch(notFoundRoute, params) ];
+
+ return matches;
+}
+
+function makeMatch(route, params) {
+ return { route: route, params: params };
+}
+
+function hasMatch(matches, match) {
+ return matches.some(function (m) {
+ if (m.route !== match.route)
+ return false;
+
+ for (var property in m.params) {
+ if (m.params[property] !== match.params[property])
+ return false;
+ }
+
+ return true;
+ });
+}
+
+function getRootMatch(matches) {
+ return matches[matches.length - 1];
+}
+
+function updateMatchComponents(matches, refs) {
+ var i = 0, component;
+ while (component = refs[REF_NAME]) {
+ matches[i++].component = component;
+ refs = component.refs;
+ }
+}
+
+/**
+ * Runs all transition hooks that are required to get from the current state
+ * to the state specified by the given transition and updates the current state
+ * if they all pass successfully. Returns a promise that resolves to the new
+ * state if it needs to be updated, or undefined if not.
+ */
+function runTransitionHooks(routes, transition) {
+ if (routes.state.path === transition.path)
+ return Promise.resolve(); // Nothing to do!
+
+ var currentMatches = routes.state.matches;
+ var nextMatches = routes.match(transition.path);
+
+ warning(
+ nextMatches,
+ 'No route matches path "' + transition.path + '". Make sure you have ' +
+ '<Route path="' + transition.path + '"> somewhere in your routes'
+ );
+
+ if (!nextMatches)
+ nextMatches = [];
+
+ var fromMatches, toMatches;
+ if (currentMatches) {
+ updateMatchComponents(currentMatches, routes.refs);
+
+ fromMatches = currentMatches.filter(function (match) {
+ return !hasMatch(nextMatches, match);
+ });
+
+ toMatches = nextMatches.filter(function (match) {
+ return !hasMatch(currentMatches, match);
+ });
+ } else {
+ fromMatches = [];
+ toMatches = nextMatches;
+ }
+
+ var query = Path.extractQuery(transition.path) || {};
+
+ return runTransitionFromHooks(fromMatches, transition).then(function () {
+ if (transition.isAborted)
+ return; // No need to continue.
+
+ return runTransitionToHooks(toMatches, transition, query).then(function () {
+ if (transition.isAborted)
+ return; // No need to continue.
+
+ var rootMatch = getRootMatch(nextMatches);
+ var params = (rootMatch && rootMatch.params) || {};
+
+ return {
+ path: transition.path,
+ matches: nextMatches,
+ activeParams: params,
+ activeQuery: query,
+ activeRoutes: nextMatches.map(function (match) {
+ return match.route;
+ })
+ };
+ });
+ });
+}
+
+/**
+ * Calls the willTransitionFrom hook of all handlers in the given matches
+ * serially in reverse with the transition object and the current instance of
+ * the route's handler, so that the deepest nested handlers are called first.
+ * Returns a promise that resolves after the last handler.
+ */
+function runTransitionFromHooks(matches, transition) {
+ var promise = Promise.resolve();
+
+ reversedArray(matches).forEach(function (match) {
+ promise = promise.then(function () {
+ var handler = match.route.props.handler;
+
+ if (!transition.isAborted && handler.willTransitionFrom)
+ return handler.willTransitionFrom(transition, match.component);
+ });
+ });
+
+ return promise;
+}
+
+/**
+ * Calls the willTransitionTo hook of all handlers in the given matches serially
+ * with the transition object and any params that apply to that handler. Returns
+ * a promise that resolves after the last handler.
+ */
+function runTransitionToHooks(matches, transition, query) {
+ var promise = Promise.resolve();
+
+ matches.forEach(function (match) {
+ promise = promise.then(function () {
+ var handler = match.route.props.handler;
+
+ if (!transition.isAborted && handler.willTransitionTo)
+ return handler.willTransitionTo(transition, match.params, query);
+ });
+ });
+
+ return promise;
+}
+
+/**
+ * Given an array of matches as returned by findMatches, return a descriptor for
+ * the handler hierarchy specified by the route.
+ */
+function computeHandlerProps(matches, query) {
+ var props = {
+ ref: null,
+ key: null,
+ params: null,
+ query: null,
+ activeRouteHandler: returnNull
+ };
+
+ var childHandler;
+ reversedArray(matches).forEach(function (match) {
+ var route = match.route;
+
+ props = Route.getUnreservedProps(route.props);
+
+ props.ref = REF_NAME;
+ props.params = match.params;
+ props.query = query;
+
+ if (route.props.addHandlerKey)
+ props.key = Path.injectParams(route.props.path, match.params);
+
+ if (childHandler) {
+ props.activeRouteHandler = childHandler;
+ } else {
+ props.activeRouteHandler = returnNull;
+ }
+
+ childHandler = function (props, addedProps) {
+ if (arguments.length > 2 && typeof arguments[2] !== 'undefined')
+ throw new Error('Passing children to a route handler is not supported');
+
+ return route.props.handler(copyProperties(props, addedProps));
+ }.bind(this, props);
+ });
+
+ return props;
+}
+
+function returnNull() {
+ return null;
+}
+
+function reversedArray(array) {
+ return array.slice(0).reverse();
+}
+
+module.exports = Routes;
+
+},{"../actions/LocationActions":1,"../components/Route":6,"../locations/DefaultLocation":10,"../locations/HashLocation":11,"../locations/HistoryLocation":12,"../locations/RefreshLocation":14,"../stores/ActiveStore":17,"../stores/PathStore":18,"../stores/RouteStore":19,"../utils/Path":20,"../utils/Redirect":21,"../utils/Transition":22,"react/lib/copyProperties":40,"react/lib/warning":48,"when/lib/Promise":49}],8:[function(_dereq_,module,exports){
+var copyProperties = _dereq_('react/lib/copyProperties');
+var Dispatcher = _dereq_('flux').Dispatcher;
+
+/**
+ * Dispatches actions that modify the URL.
+ */
+var LocationDispatcher = copyProperties(new Dispatcher, {
+
+ handleViewAction: function (action) {
+ this.dispatch({
+ source: 'VIEW_ACTION',
+ action: action
+ });
+ }
+
+});
+
+module.exports = LocationDispatcher;
+
+},{"flux":31,"react/lib/copyProperties":40}],9:[function(_dereq_,module,exports){
+exports.goBack = _dereq_('./actions/LocationActions').goBack;
+exports.replaceWith = _dereq_('./actions/LocationActions').replaceWith;
+exports.transitionTo = _dereq_('./actions/LocationActions').transitionTo;
+
+exports.DefaultRoute = _dereq_('./components/DefaultRoute');
+exports.Link = _dereq_('./components/Link');
+exports.NotFoundRoute = _dereq_('./components/NotFoundRoute');
+exports.Redirect = _dereq_('./components/Redirect');
+exports.Route = _dereq_('./components/Route');
+exports.Routes = _dereq_('./components/Routes');
+
+exports.ActiveState = _dereq_('./mixins/ActiveState');
+exports.AsyncState = _dereq_('./mixins/AsyncState');
+
+exports.makeHref = _dereq_('./utils/makeHref');
+
+},{"./actions/LocationActions":1,"./components/DefaultRoute":2,"./components/Link":3,"./components/NotFoundRoute":4,"./components/Redirect":5,"./components/Route":6,"./components/Routes":7,"./mixins/ActiveState":15,"./mixins/AsyncState":16,"./utils/makeHref":25}],10:[function(_dereq_,module,exports){
+module.exports = "production" === 'test'
+ ? _dereq_('./MemoryLocation')
+ : _dereq_('./HashLocation');
+
+},{"./HashLocation":11,"./MemoryLocation":13}],11:[function(_dereq_,module,exports){
+var invariant = _dereq_('react/lib/invariant');
+var ExecutionEnvironment = _dereq_('react/lib/ExecutionEnvironment');
+var getWindowPath = _dereq_('../utils/getWindowPath');
+
+function getHashPath() {
+ return window.location.hash.substr(1);
+}
+
+function ensureSlash() {
+ var path = getHashPath();
+
+ if (path.charAt(0) === '/')
+ return true;
+
+ HashLocation.replace('/' + path);
+
+ return false;
+}
+
+var _onChange;
+
+function handleHashChange() {
+ if (ensureSlash())
+ _onChange();
+}
+
+/**
+ * A Location that uses `window.location.hash`.
+ */
+var HashLocation = {
+
+ setup: function (onChange) {
+ invariant(
+ ExecutionEnvironment.canUseDOM,
+ 'You cannot use HashLocation in an environment with no DOM'
+ );
+
+ _onChange = onChange;
+
+ ensureSlash();
+
+ if (window.addEventListener) {
+ window.addEventListener('hashchange', handleHashChange, false);
+ } else {
+ window.attachEvent('onhashchange', handleHashChange);
+ }
+ },
+
+ teardown: function () {
+ if (window.removeEventListener) {
+ window.removeEventListener('hashchange', handleHashChange, false);
+ } else {
+ window.detachEvent('onhashchange', handleHashChange);
+ }
+ },
+
+ push: function (path) {
+ window.location.hash = path;
+ },
+
+ replace: function (path) {
+ window.location.replace(getWindowPath() + '#' + path);
+ },
+
+ pop: function () {
+ window.history.back();
+ },
+
+ getCurrentPath: getHashPath,
+
+ toString: function () {
+ return '<HashLocation>';
+ }
+
+};
+
+module.exports = HashLocation;
+
+},{"../utils/getWindowPath":23,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":42}],12:[function(_dereq_,module,exports){
+var invariant = _dereq_('react/lib/invariant');
+var ExecutionEnvironment = _dereq_('react/lib/ExecutionEnvironment');
+var getWindowPath = _dereq_('../utils/getWindowPath');
+
+var _onChange;
+
+/**
+ * A Location that uses HTML5 history.
+ */
+var HistoryLocation = {
+
+ setup: function (onChange) {
+ invariant(
+ ExecutionEnvironment.canUseDOM,
+ 'You cannot use HistoryLocation in an environment with no DOM'
+ );
+
+ _onChange = onChange;
+
+ if (window.addEventListener) {
+ window.addEventListener('popstate', _onChange, false);
+ } else {
+ window.attachEvent('popstate', _onChange);
+ }
+ },
+
+ teardown: function () {
+ if (window.removeEventListener) {
+ window.removeEventListener('popstate', _onChange, false);
+ } else {
+ window.detachEvent('popstate', _onChange);
+ }
+ },
+
+ push: function (path) {
+ window.history.pushState({ path: path }, '', path);
+ _onChange();
+ },
+
+ replace: function (path) {
+ window.history.replaceState({ path: path }, '', path);
+ _onChange();
+ },
+
+ pop: function () {
+ window.history.back();
+ },
+
+ getCurrentPath: getWindowPath,
+
+ toString: function () {
+ return '<HistoryLocation>';
+ }
+
+};
+
+module.exports = HistoryLocation;
+
+},{"../utils/getWindowPath":23,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":42}],13:[function(_dereq_,module,exports){
+var warning = _dereq_('react/lib/warning');
+
+var _lastPath = null;
+var _currentPath = null;
+var _onChange;
+
+/**
+ * A Location that does not require a DOM.
+ */
+var MemoryLocation = {
+
+ setup: function (onChange) {
+ _onChange = onChange;
+ },
+
+ push: function (path) {
+ _lastPath = _currentPath;
+ _currentPath = path;
+ _onChange();
+ },
+
+ replace: function (path) {
+ _currentPath = path;
+ _onChange();
+ },
+
+ pop: function () {
+ warning(
+ _lastPath != null,
+ 'You cannot use MemoryLocation to go back more than once'
+ );
+
+ _currentPath = _lastPath;
+ _lastPath = null;
+ _onChange();
+ },
+
+ getCurrentPath: function () {
+ return _currentPath || '/';
+ },
+
+ toString: function () {
+ return '<MemoryLocation>';
+ }
+
+};
+
+module.exports = MemoryLocation;
+
+},{"react/lib/warning":48}],14:[function(_dereq_,module,exports){
+var invariant = _dereq_('react/lib/invariant');
+var ExecutionEnvironment = _dereq_('react/lib/ExecutionEnvironment');
+var getWindowPath = _dereq_('../utils/getWindowPath');
+
+/**
+ * A Location that uses full page refreshes. This is used as
+ * the fallback for HistoryLocation in browsers that do not
+ * support the HTML5 history API.
+ */
+var RefreshLocation = {
+
+ setup: function () {
+ invariant(
+ ExecutionEnvironment.canUseDOM,
+ 'You cannot use RefreshLocation in an environment with no DOM'
+ );
+ },
+
+ push: function (path) {
+ window.location = path;
+ },
+
+ replace: function (path) {
+ window.location.replace(path);
+ },
+
+ pop: function () {
+ window.history.back();
+ },
+
+ getCurrentPath: getWindowPath,
+
+ toString: function () {
+ return '<RefreshLocation>';
+ }
+
+};
+
+module.exports = RefreshLocation;
+
+},{"../utils/getWindowPath":23,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":42}],15:[function(_dereq_,module,exports){
+var ActiveStore = _dereq_('../stores/ActiveStore');
+
+/**
+ * A mixin for components that need to know about the routes, params,
+ * and query that are currently active. Components that use it get two
+ * things:
+ *
+ * 1. An `isActive` static method they can use to check if a route,
+ * params, and query are active.
+ * 2. An `updateActiveState` instance method that is called when the
+ * active state changes.
+ *
+ * Example:
+ *
+ * var Tab = React.createClass({
+ *
+ * mixins: [ Router.ActiveState ],
+ *
+ * getInitialState: function () {
+ * return {
+ * isActive: false
+ * };
+ * },
+ *
+ * updateActiveState: function () {
+ * this.setState({
+ * isActive: Tab.isActive(routeName, params, query)
+ * })
+ * }
+ *
+ * });
+ */
+var ActiveState = {
+
+ statics: {
+
+ /**
+ * Returns true if the route with the given name, URL parameters, and query
+ * are all currently active.
+ */
+ isActive: ActiveStore.isActive
+
+ },
+
+ componentWillMount: function () {
+ ActiveStore.addChangeListener(this.handleActiveStateChange);
+ },
+
+ componentDidMount: function () {
+ if (this.updateActiveState)
+ this.updateActiveState();
+ },
+
+ componentWillUnmount: function () {
+ ActiveStore.removeChangeListener(this.handleActiveStateChange);
+ },
+
+ handleActiveStateChange: function () {
+ if (this.isMounted() && typeof this.updateActiveState === 'function')
+ this.updateActiveState();
+ }
+
+};
+
+module.exports = ActiveState;
+
+},{"../stores/ActiveStore":17}],16:[function(_dereq_,module,exports){
+var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
+var resolveAsyncState = _dereq_('../utils/resolveAsyncState');
+
+/**
+ * A mixin for route handler component classes that fetch at least
+ * part of their state asynchronously. Classes that use it should
+ * declare a static `getInitialAsyncState` method that fetches state
+ * for a component after it mounts. This function is given three
+ * arguments: 1) the current route params, 2) the current query and
+ * 3) a function that can be used to set state as it is received.
+ *
+ * Much like the familiar `getInitialState` method, `getInitialAsyncState`
+ * should return a hash of key/value pairs to use in the component's
+ * state. The difference is that the values may be promises. As these
+ * values resolve, the component's state is updated. You should only
+ * ever need to use the setState function for doing things like
+ * streaming data and/or updating progress.
+ *
+ * Example:
+ *
+ * var User = React.createClass({
+ *
+ * statics: {
+ *
+ * getInitialAsyncState: function (params, query, setState) {
+ * // Return a hash with keys named after the state variables
+ * // you want to set, as you normally do in getInitialState,
+ * // except the values may be immediate values or promises.
+ * // The state is automatically updated as promises resolve.
+ * return {
+ * user: getUserByID(params.userID) // may be a promise
+ * };
+ *
+ * // Or, use the setState function to stream data!
+ * var buffer = '';
+ *
+ * return {
+ *
+ * // Same as above, the stream state variable is set to the
+ * // value returned by this promise when it resolves.
+ * stream: getStreamingData(params.userID, function (chunk) {
+ * buffer += chunk;
+ *
+ * // Notify of progress.
+ * setState({
+ * streamBuffer: buffer
+ * });
+ * })
+ *
+ * };
+ * }
+ *
+ * },
+ *
+ * getInitialState: function () {
+ * return {
+ * user: null, // Receives a value when getUserByID resolves.
+ * stream: null, // Receives a value when getStreamingData resolves.
+ * streamBuffer: '' // Used to track data as it loads.
+ * };
+ * },
+ *
+ * render: function () {
+ * if (!this.state.user)
+ * return <LoadingUser/>;
+ *
+ * return (
+ * <div>
+ * <p>Welcome {this.state.user.name}!</p>
+ * <p>So far, you've received {this.state.streamBuffer.length} data!</p>
+ * </div>
+ * );
+ * }
+ *
+ * });
+ *
+ * When testing, use the `initialAsyncState` prop to simulate asynchronous
+ * data fetching. When this prop is present, no attempt is made to retrieve
+ * additional state via `getInitialAsyncState`.
+ */
+var AsyncState = {
+
+ propTypes: {
+ initialAsyncState: React.PropTypes.object
+ },
+
+ getInitialState: function () {
+ return this.props.initialAsyncState || null;
+ },
+
+ updateAsyncState: function (state) {
+ if (this.isMounted())
+ this.setState(state);
+ },
+
+ componentDidMount: function () {
+ if (this.props.initialAsyncState || typeof this.constructor.getInitialAsyncState !== 'function')
+ return;
+
+ resolveAsyncState(
+ this.constructor.getInitialAsyncState(this.props.params, this.props.query, this.updateAsyncState),
+ this.updateAsyncState
+ );
+ }
+
+};
+
+module.exports = AsyncState;
+
+},{"../utils/resolveAsyncState":27}],17:[function(_dereq_,module,exports){
+var EventEmitter = _dereq_('events').EventEmitter;
+
+var CHANGE_EVENT = 'change';
+var _events = new EventEmitter;
+
+_events.setMaxListeners(0);
+
+function notifyChange() {
+ _events.emit(CHANGE_EVENT);
+}
+
+var _activeRoutes = [];
+var _activeParams = {};
+var _activeQuery = {};
+
+function routeIsActive(routeName) {
+ return _activeRoutes.some(function (route) {
+ return route.props.name === routeName;
+ });
+}
+
+function paramsAreActive(params) {
+ for (var property in params) {
+ if (_activeParams[property] !== String(params[property]))
+ return false;
+ }
+
+ return true;
+}
+
+function queryIsActive(query) {
+ for (var property in query) {
+ if (_activeQuery[property] !== String(query[property]))
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * The ActiveStore keeps track of which routes, URL and query parameters are
+ * currently active on a page. <Link>s subscribe to the ActiveStore to know
+ * whether or not they are active.
+ */
+var ActiveStore = {
+
+ addChangeListener: function (listener) {
+ _events.on(CHANGE_EVENT, listener);
+ },
+
+ removeChangeListener: function (listener) {
+ _events.removeListener(CHANGE_EVENT, listener);
+ },
+
+ /**
+ * Updates the currently active state and notifies all listeners.
+ * This is automatically called by routes as they become active.
+ */
+ updateState: function (state) {
+ state = state || {};
+
+ _activeRoutes = state.activeRoutes || [];
+ _activeParams = state.activeParams || {};
+ _activeQuery = state.activeQuery || {};
+
+ notifyChange();
+ },
+
+ /**
+ * Returns true if the route with the given name, URL parameters, and query
+ * are all currently active.
+ */
+ isActive: function (routeName, params, query) {
+ var isActive = routeIsActive(routeName) && paramsAreActive(params);
+
+ if (query)
+ return isActive && queryIsActive(query);
+
+ return isActive;
+ }
+
+};
+
+module.exports = ActiveStore;
+
+},{"events":30}],18:[function(_dereq_,module,exports){
+var warning = _dereq_('react/lib/warning');
+var EventEmitter = _dereq_('events').EventEmitter;
+var LocationActions = _dereq_('../actions/LocationActions');
+var LocationDispatcher = _dereq_('../dispatchers/LocationDispatcher');
+var supportsHistory = _dereq_('../utils/supportsHistory');
+var HistoryLocation = _dereq_('../locations/HistoryLocation');
+var RefreshLocation = _dereq_('../locations/RefreshLocation');
+
+var CHANGE_EVENT = 'change';
+var _events = new EventEmitter;
+
+function notifyChange() {
+ _events.emit(CHANGE_EVENT);
+}
+
+var _scrollPositions = {};
+
+function recordScrollPosition(path) {
+ _scrollPositions[path] = {
+ x: window.scrollX,
+ y: window.scrollY
+ };
+}
+
+function updateScrollPosition(path) {
+ var p = PathStore.getScrollPosition(path);
+ window.scrollTo(p.x, p.y);
+}
+
+var _location;
+
+/**
+ * The PathStore keeps track of the current URL path and manages
+ * the location strategy that is used to update the URL.
+ */
+var PathStore = {
+
+ addChangeListener: function (listener) {
+ _events.on(CHANGE_EVENT, listener);
+ },
+
+ removeChangeListener: function (listener) {
+ _events.removeListener(CHANGE_EVENT, listener);
+
+ // Automatically teardown when the last listener is removed.
+ if (EventEmitter.listenerCount(_events, CHANGE_EVENT) === 0)
+ PathStore.teardown();
+ },
+
+ setup: function (location) {
+ // When using HistoryLocation, automatically fallback
+ // to RefreshLocation in browsers that do not support
+ // the HTML5 history API.
+ if (location === HistoryLocation && !supportsHistory())
+ location = RefreshLocation;
+
+ if (_location == null) {
+ _location = location;
+
+ if (_location && typeof _location.setup === 'function')
+ _location.setup(notifyChange);
+ } else {
+ warning(
+ _location === location,
+ 'Cannot use location %s, already using %s', location, _location
+ );
+ }
+ },
+
+ teardown: function () {
+ _events.removeAllListeners(CHANGE_EVENT);
+
+ if (_location && typeof _location.teardown === 'function')
+ _location.teardown();
+
+ _location = null;
+ },
+
+ /**
+ * Returns the location object currently in use.
+ */
+ getLocation: function () {
+ return _location;
+ },
+
+ /**
+ * Returns the current URL path.
+ */
+ getCurrentPath: function () {
+ return _location.getCurrentPath();
+ },
+
+ /**
+ * Returns the last known scroll position for the given path.
+ */
+ getScrollPosition: function (path) {
+ return _scrollPositions[path] || { x: 0, y: 0 };
+ },
+
+ dispatchToken: LocationDispatcher.register(function (payload) {
+ var action = payload.action;
+ var currentPath = _location.getCurrentPath();
+
+ switch (action.type) {
+ case LocationActions.PUSH:
+ if (currentPath !== action.path) {
+ recordScrollPosition(currentPath);
+ _location.push(action.path);
+ }
+ break;
+
+ case LocationActions.REPLACE:
+ if (currentPath !== action.path) {
+ recordScrollPosition(currentPath);
+ _location.replace(action.path);
+ }
+ break;
+
+ case LocationActions.POP:
+ recordScrollPosition(currentPath);
+ _location.pop();
+ break;
+
+ case LocationActions.UPDATE_SCROLL:
+ updateScrollPosition(currentPath);
+ break;
+ }
+ })
+
+};
+
+module.exports = PathStore;
+
+},{"../actions/LocationActions":1,"../dispatchers/LocationDispatcher":8,"../locations/HistoryLocation":12,"../locations/RefreshLocation":14,"../utils/supportsHistory":28,"events":30,"react/lib/warning":48}],19:[function(_dereq_,module,exports){
+var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
+var invariant = _dereq_('react/lib/invariant');
+var warning = _dereq_('react/lib/warning');
+var Path = _dereq_('../utils/Path');
+
+var _namedRoutes = {};
+
+/**
+ * The RouteStore contains a directory of all <Route>s in the system. It is
+ * used primarily for looking up routes by name so that <Link>s can use a
+ * route name in the "to" prop and users can use route names in `Router.transitionTo`
+ * and other high-level utility methods.
+ */
+var RouteStore = {
+
+ /**
+ * Removes all references to <Route>s from the store. Should only ever
+ * really be used in tests to clear the store between test runs.
+ */
+ unregisterAllRoutes: function () {
+ _namedRoutes = {};
+ },
+
+ /**
+ * Removes the reference to the given <Route> and all of its children
+ * from the store.
+ */
+ unregisterRoute: function (route) {
+ var props = route.props;
+
+ if (props.name)
+ delete _namedRoutes[props.name];
+
+ React.Children.forEach(props.children, RouteStore.unregisterRoute);
+ },
+
+ /**
+ * Registers a <Route> and all of its children with the store. Also,
+ * does some normalization and validation on route props.
+ */
+ registerRoute: function (route, parentRoute) {
+ // Note: parentRoute may be a <Route> _or_ a <Routes>.
+ var props = route.props;
+
+ invariant(
+ React.isValidClass(props.handler),
+ 'The handler for the "%s" route must be a valid React class',
+ props.name || props.path
+ );
+
+ var parentPath = (parentRoute && parentRoute.props.path) || '/';
+
+ if ((props.path || props.name) && !props.isDefault && !props.catchAll) {
+ var path = props.path || props.name;
+
+ // Relative paths extend their parent.
+ if (!Path.isAbsolute(path))
+ path = Path.join(parentPath, path);
+
+ props.path = Path.normalize(path);
+ } else {
+ props.path = parentPath;
+
+ if (props.catchAll)
+ props.path += '*';
+ }
+
+ props.paramNames = Path.extractParamNames(props.path);
+
+ // Make sure the route's path has all params its parent needs.
+ if (parentRoute && Array.isArray(parentRoute.props.paramNames)) {
+ parentRoute.props.paramNames.forEach(function (paramName) {
+ invariant(
+ props.paramNames.indexOf(paramName) !== -1,
+ 'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"',
+ props.path, paramName, parentRoute.props.path
+ );
+ });
+ }
+
+ // Make sure the route can be looked up by <Link>s.
+ if (props.name) {
+ var existingRoute = _namedRoutes[props.name];
+
+ invariant(
+ !existingRoute || route === existingRoute,
+ 'You cannot use the name "%s" for more than one route',
+ props.name
+ );
+
+ _namedRoutes[props.name] = route;
+ }
+
+ if (props.catchAll) {
+ invariant(
+ parentRoute,
+ '<NotFoundRoute> must have a parent <Route>'
+ );
+
+ invariant(
+ parentRoute.props.notFoundRoute == null,
+ 'You may not have more than one <NotFoundRoute> per <Route>'
+ );
+
+ parentRoute.props.notFoundRoute = route;
+
+ return null;
+ }
+
+ if (props.isDefault) {
+ invariant(
+ parentRoute,
+ '<DefaultRoute> must have a parent <Route>'
+ );
+
+ invariant(
+ parentRoute.props.defaultRoute == null,
+ 'You may not have more than one <DefaultRoute> per <Route>'
+ );
+
+ parentRoute.props.defaultRoute = route;
+
+ return null;
+ }
+
+ // Make sure children is an array.
+ props.children = RouteStore.registerChildren(props.children, route);
+
+ return route;
+ },
+
+ /**
+ * Registers many children routes at once, always returning an array.
+ */
+ registerChildren: function (children, parentRoute) {
+ var routes = [];
+
+ React.Children.forEach(children, function (child) {
+ // Exclude <DefaultRoute>s.
+ if (child = RouteStore.registerRoute(child, parentRoute))
+ routes.push(child);
+ });
+
+ return routes;
+ },
+
+ /**
+ * Returns the Route object with the given name, if one exists.
+ */
+ getRouteByName: function (routeName) {
+ return _namedRoutes[routeName] || null;
+ }
+
+};
+
+module.exports = RouteStore;
+
+},{"../utils/Path":20,"react/lib/invariant":42,"react/lib/warning":48}],20:[function(_dereq_,module,exports){
+var invariant = _dereq_('react/lib/invariant');
+var merge = _dereq_('qs/lib/utils').merge;
+var qs = _dereq_('qs');
+
+function encodeURL(url) {
+ return encodeURIComponent(url).replace(/%20/g, '+');
+}
+
+function decodeURL(url) {
+ return decodeURIComponent(url.replace(/\+/g, ' '));
+}
+
+function encodeURLPath(path) {
+ return String(path).split('/').map(encodeURL).join('/');
+}
+
+var paramMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$]*)|[*.()\[\]\\+|{}^$]/g;
+var queryMatcher = /\?(.+)/;
+
+var _compiledPatterns = {};
+
+function compilePattern(pattern) {
+ if (!(pattern in _compiledPatterns)) {
+ var paramNames = [];
+ var source = pattern.replace(paramMatcher, function (match, paramName) {
+ if (paramName) {
+ paramNames.push(paramName);
+ return '([^./?#]+)';
+ } else if (match === '*') {
+ paramNames.push('splat');
+ return '(.*?)';
+ } else {
+ return '\\' + match;
+ }
+ });
+
+ _compiledPatterns[pattern] = {
+ matcher: new RegExp('^' + source + '$', 'i'),
+ paramNames: paramNames
+ };
+ }
+
+ return _compiledPatterns[pattern];
+}
+
+var Path = {
+
+ /**
+ * Returns an array of the names of all parameters in the given pattern.
+ */
+ extractParamNames: function (pattern) {
+ return compilePattern(pattern).paramNames;
+ },
+
+ /**
+ * Extracts the portions of the given URL path that match the given pattern
+ * and returns an object of param name => value pairs. Returns null if the
+ * pattern does not match the given path.
+ */
+ extractParams: function (pattern, path) {
+ var object = compilePattern(pattern);
+ var match = decodeURL(path).match(object.matcher);
+
+ if (!match)
+ return null;
+
+ var params = {};
+
+ object.paramNames.forEach(function (paramName, index) {
+ params[paramName] = match[index + 1];
+ });
+
+ return params;
+ },
+
+ /**
+ * Returns a version of the given route path with params interpolated. Throws
+ * if there is a dynamic segment of the route path for which there is no param.
+ */
+ injectParams: function (pattern, params) {
+ params = params || {};
+
+ var splatIndex = 0;
+
+ return pattern.replace(paramMatcher, function (match, paramName) {
+ paramName = paramName || 'splat';
+
+ invariant(
+ params[paramName] != null,
+ 'Missing "' + paramName + '" parameter for path "' + pattern + '"'
+ );
+
+ var segment;
+ if (paramName === 'splat' && Array.isArray(params[paramName])) {
+ segment = params[paramName][splatIndex++];
+
+ invariant(
+ segment != null,
+ 'Missing splat # ' + splatIndex + ' for path "' + pattern + '"'
+ );
+ } else {
+ segment = params[paramName];
+ }
+
+ return encodeURLPath(segment);
+ });
+ },
+
+ /**
+ * Returns an object that is the result of parsing any query string contained
+ * in the given path, null if the path contains no query string.
+ */
+ extractQuery: function (path) {
+ var match = decodeURL(path).match(queryMatcher);
+ return match && qs.parse(match[1]);
+ },
+
+ /**
+ * Returns a version of the given path without the query string.
+ */
+ withoutQuery: function (path) {
+ return path.replace(queryMatcher, '');
+ },
+
+ /**
+ * Returns a version of the given path with the parameters in the given
+ * query merged into the query string.
+ */
+ withQuery: function (path, query) {
+ var existingQuery = Path.extractQuery(path);
+
+ if (existingQuery)
+ query = query ? merge(existingQuery, query) : existingQuery;
+
+ var queryString = query && qs.stringify(query);
+
+ if (queryString)
+ return Path.withoutQuery(path) + '?' + queryString;
+
+ return path;
+ },
+
+ /**
+ * Returns true if the given path is absolute.
+ */
+ isAbsolute: function (path) {
+ return path.charAt(0) === '/';
+ },
+
+ /**
+ * Returns a normalized version of the given path.
+ */
+ normalize: function (path, parentRoute) {
+ return path.replace(/^\/*/, '/');
+ },
+
+ /**
+ * Joins two URL paths together.
+ */
+ join: function (a, b) {
+ return a.replace(/\/*$/, '/') + b;
+ }
+
+};
+
+module.exports = Path;
+
+},{"qs":34,"qs/lib/utils":38,"react/lib/invariant":42}],21:[function(_dereq_,module,exports){
+/**
+ * Encapsulates a redirect to the given route.
+ */
+function Redirect(to, params, query) {
+ this.to = to;
+ this.params = params;
+ this.query = query;
+}
+
+module.exports = Redirect;
+
+},{}],22:[function(_dereq_,module,exports){
+var mixInto = _dereq_('react/lib/mixInto');
+var transitionTo = _dereq_('../actions/LocationActions').transitionTo;
+var Redirect = _dereq_('./Redirect');
+
+/**
+ * Encapsulates a transition to a given path.
+ *
+ * The willTransitionTo and willTransitionFrom handlers receive
+ * an instance of this class as their first argument.
+ */
+function Transition(path) {
+ this.path = path;
+ this.abortReason = null;
+ this.isAborted = false;
+}
+
+mixInto(Transition, {
+
+ abort: function (reason) {
+ this.abortReason = reason;
+ this.isAborted = true;
+ },
+
+ redirect: function (to, params, query) {
+ this.abort(new Redirect(to, params, query));
+ },
+
+ retry: function () {
+ transitionTo(this.path);
+ }
+
+});
+
+module.exports = Transition;
+
+},{"../actions/LocationActions":1,"./Redirect":21,"react/lib/mixInto":47}],23:[function(_dereq_,module,exports){
+/**
+ * Returns the current URL path from `window.location`, including query string
+ */
+function getWindowPath() {
+ return window.location.pathname + window.location.search;
+}
+
+module.exports = getWindowPath;
+
+
+},{}],24:[function(_dereq_,module,exports){
+module.exports = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
+
+},{}],25:[function(_dereq_,module,exports){
+var HashLocation = _dereq_('../locations/HashLocation');
+var PathStore = _dereq_('../stores/PathStore');
+var makePath = _dereq_('./makePath');
+
+/**
+ * Returns a string that may safely be used as the href of a
+ * link to the route with the given name.
+ */
+function makeHref(to, params, query) {
+ var path = makePath(to, params, query);
+
+ if (PathStore.getLocation() === HashLocation)
+ return '#' + path;
+
+ return path;
+}
+
+module.exports = makeHref;
+
+},{"../locations/HashLocation":11,"../stores/PathStore":18,"./makePath":26}],26:[function(_dereq_,module,exports){
+var invariant = _dereq_('react/lib/invariant');
+var RouteStore = _dereq_('../stores/RouteStore');
+var Path = _dereq_('./Path');
+
+/**
+ * Returns an absolute URL path created from the given route name, URL
+ * parameters, and query values.
+ */
+function makePath(to, params, query) {
+ var path;
+ if (Path.isAbsolute(to)) {
+ path = Path.normalize(to);
+ } else {
+ var route = RouteStore.getRouteByName(to);
+
+ invariant(
+ route,
+ 'Unable to find a route named "' + to + '". Make sure you have ' +
+ 'a <Route name="' + to + '"> defined somewhere in your routes'
+ );
+
+ path = route.props.path;
+ }
+
+ return Path.withQuery(Path.injectParams(path, params), query);
+}
+
+module.exports = makePath;
+
+},{"../stores/RouteStore":19,"./Path":20,"react/lib/invariant":42}],27:[function(_dereq_,module,exports){
+var Promise = _dereq_('when/lib/Promise');
+
+/**
+ * Resolves all values in asyncState and calls the setState
+ * function with new state as they resolve. Returns a promise
+ * that resolves after all values are resolved.
+ */
+function resolveAsyncState(asyncState, setState) {
+ if (asyncState == null)
+ return Promise.resolve();
+
+ var keys = Object.keys(asyncState);
+
+ return Promise.all(
+ keys.map(function (key) {
+ return Promise.resolve(asyncState[key]).then(function (value) {
+ var newState = {};
+ newState[key] = value;
+ setState(newState);
+ });
+ })
+ );
+}
+
+module.exports = resolveAsyncState;
+
+},{"when/lib/Promise":49}],28:[function(_dereq_,module,exports){
+function supportsHistory() {
+ /*! taken from modernizr
+ * https://github.com/Modernizr/Modernizr/blob/master/LICENSE
+ * https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js
+ */
+ var ua = navigator.userAgent;
+ if ((ua.indexOf('Android 2.') !== -1 ||
+ (ua.indexOf('Android 4.0') !== -1)) &&
+ ua.indexOf('Mobile Safari') !== -1 &&
+ ua.indexOf('Chrome') === -1) {
+ return false;
+ }
+ return (window.history && 'pushState' in window.history);
+}
+
+module.exports = supportsHistory;
+
+},{}],29:[function(_dereq_,module,exports){
+function withoutProperties(object, properties) {
+ var result = {};
+
+ for (var property in object) {
+ if (object.hasOwnProperty(property) && !properties[property])
+ result[property] = object[property];
+ }
+
+ return result;
+}
+
+module.exports = withoutProperties;
+
+},{}],30:[function(_dereq_,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+function EventEmitter() {
+ this._events = this._events || {};
+ this._maxListeners = this._maxListeners || undefined;
+}
+module.exports = EventEmitter;
+
+// Backwards-compat with node 0.10.x
+EventEmitter.EventEmitter = EventEmitter;
+
+EventEmitter.prototype._events = undefined;
+EventEmitter.prototype._maxListeners = undefined;
+
+// By default EventEmitters will print a warning if more than 10 listeners are
+// added to it. This is a useful default which helps finding memory leaks.
+EventEmitter.defaultMaxListeners = 10;
+
+// Obviously not all Emitters should be limited to 10. This function allows
+// that to be increased. Set to zero for unlimited.
+EventEmitter.prototype.setMaxListeners = function(n) {
+ if (!isNumber(n) || n < 0 || isNaN(n))
+ throw TypeError('n must be a positive number');
+ this._maxListeners = n;
+ return this;
+};
+
+EventEmitter.prototype.emit = function(type) {
+ var er, handler, len, args, i, listeners;
+
+ if (!this._events)
+ this._events = {};
+
+ // If there is no 'error' event listener then throw.
+ if (type === 'error') {
+ if (!this._events.error ||
+ (isObject(this._events.error) && !this._events.error.length)) {
+ er = arguments[1];
+ if (er instanceof Error) {
+ throw er; // Unhandled 'error' event
+ } else {
+ throw TypeError('Uncaught, unspecified "error" event.');
+ }
+ return false;
+ }
+ }
+
+ handler = this._events[type];
+
+ if (isUndefined(handler))
+ return false;
+
+ if (isFunction(handler)) {
+ switch (arguments.length) {
+ // fast cases
+ case 1:
+ handler.call(this);
+ break;
+ case 2:
+ handler.call(this, arguments[1]);
+ break;
+ case 3:
+ handler.call(this, arguments[1], arguments[2]);
+ break;
+ // slower
+ default:
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+ handler.apply(this, args);
+ }
+ } else if (isObject(handler)) {
+ len = arguments.length;
+ args = new Array(len - 1);
+ for (i = 1; i < len; i++)
+ args[i - 1] = arguments[i];
+
+ listeners = handler.slice();
+ len = listeners.length;
+ for (i = 0; i < len; i++)
+ listeners[i].apply(this, args);
+ }
+
+ return true;
+};
+
+EventEmitter.prototype.addListener = function(type, listener) {
+ var m;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events)
+ this._events = {};
+
+ // To avoid recursion in the case that type === "newListener"! Before
+ // adding it to the listeners, first emit "newListener".
+ if (this._events.newListener)
+ this.emit('newListener', type,
+ isFunction(listener.listener) ?
+ listener.listener : listener);
+
+ if (!this._events[type])
+ // Optimize the case of one listener. Don't need the extra array object.
+ this._events[type] = listener;
+ else if (isObject(this._events[type]))
+ // If we've already got an array, just append.
+ this._events[type].push(listener);
+ else
+ // Adding the second element, need to change to array.
+ this._events[type] = [this._events[type], listener];
+
+ // Check for listener leak
+ if (isObject(this._events[type]) && !this._events[type].warned) {
+ var m;
+ if (!isUndefined(this._maxListeners)) {
+ m = this._maxListeners;
+ } else {
+ m = EventEmitter.defaultMaxListeners;
+ }
+
+ if (m && m > 0 && this._events[type].length > m) {
+ this._events[type].warned = true;
+ console.error('(node) warning: possible EventEmitter memory ' +
+ 'leak detected. %d listeners added. ' +
+ 'Use emitter.setMaxListeners() to increase limit.',
+ this._events[type].length);
+ if (typeof console.trace === 'function') {
+ // not supported in IE 10
+ console.trace();
+ }
+ }
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.once = function(type, listener) {
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ var fired = false;
+
+ function g() {
+ this.removeListener(type, g);
+
+ if (!fired) {
+ fired = true;
+ listener.apply(this, arguments);
+ }
+ }
+
+ g.listener = listener;
+ this.on(type, g);
+
+ return this;
+};
+
+// emits a 'removeListener' event iff the listener was removed
+EventEmitter.prototype.removeListener = function(type, listener) {
+ var list, position, length, i;
+
+ if (!isFunction(listener))
+ throw TypeError('listener must be a function');
+
+ if (!this._events || !this._events[type])
+ return this;
+
+ list = this._events[type];
+ length = list.length;
+ position = -1;
+
+ if (list === listener ||
+ (isFunction(list.listener) && list.listener === listener)) {
+ delete this._events[type];
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+
+ } else if (isObject(list)) {
+ for (i = length; i-- > 0;) {
+ if (list[i] === listener ||
+ (list[i].listener && list[i].listener === listener)) {
+ position = i;
+ break;
+ }
+ }
+
+ if (position < 0)
+ return this;
+
+ if (list.length === 1) {
+ list.length = 0;
+ delete this._events[type];
+ } else {
+ list.splice(position, 1);
+ }
+
+ if (this._events.removeListener)
+ this.emit('removeListener', type, listener);
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.removeAllListeners = function(type) {
+ var key, listeners;
+
+ if (!this._events)
+ return this;
+
+ // not listening for removeListener, no need to emit
+ if (!this._events.removeListener) {
+ if (arguments.length === 0)
+ this._events = {};
+ else if (this._events[type])
+ delete this._events[type];
+ return this;
+ }
+
+ // emit removeListener for all listeners on all events
+ if (arguments.length === 0) {
+ for (key in this._events) {
+ if (key === 'removeListener') continue;
+ this.removeAllListeners(key);
+ }
+ this.removeAllListeners('removeListener');
+ this._events = {};
+ return this;
+ }
+
+ listeners = this._events[type];
+
+ if (isFunction(listeners)) {
+ this.removeListener(type, listeners);
+ } else {
+ // LIFO order
+ while (listeners.length)
+ this.removeListener(type, listeners[listeners.length - 1]);
+ }
+ delete this._events[type];
+
+ return this;
+};
+
+EventEmitter.prototype.listeners = function(type) {
+ var ret;
+ if (!this._events || !this._events[type])
+ ret = [];
+ else if (isFunction(this._events[type]))
+ ret = [this._events[type]];
+ else
+ ret = this._events[type].slice();
+ return ret;
+};
+
+EventEmitter.listenerCount = function(emitter, type) {
+ var ret;
+ if (!emitter._events || !emitter._events[type])
+ ret = 0;
+ else if (isFunction(emitter._events[type]))
+ ret = 1;
+ else
+ ret = emitter._events[type].length;
+ return ret;
+};
+
+function isFunction(arg) {
+ return typeof arg === 'function';
+}
+
+function isNumber(arg) {
+ return typeof arg === 'number';
+}
+
+function isObject(arg) {
+ return typeof arg === 'object' && arg !== null;
+}
+
+function isUndefined(arg) {
+ return arg === void 0;
+}
+
+},{}],31:[function(_dereq_,module,exports){
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+module.exports.Dispatcher = _dereq_('./lib/Dispatcher')
+
+},{"./lib/Dispatcher":32}],32:[function(_dereq_,module,exports){
+/*
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule Dispatcher
+ * @typechecks
+ */
+
+var invariant = _dereq_('./invariant');
+
+var _lastID = 1;
+var _prefix = 'ID_';
+
+/**
+ * Dispatcher is used to broadcast payloads to registered callbacks. This is
+ * different from generic pub-sub systems in two ways:
+ *
+ * 1) Callbacks are not subscribed to particular events. Every payload is
+ * dispatched to every registered callback.
+ * 2) Callbacks can be deferred in whole or part until other callbacks have
+ * been executed.
+ *
+ * For example, consider this hypothetical flight destination form, which
+ * selects a default city when a country is selected:
+ *
+ * var flightDispatcher = new Dispatcher();
+ *
+ * // Keeps track of which country is selected
+ * var CountryStore = {country: null};
+ *
+ * // Keeps track of which city is selected
+ * var CityStore = {city: null};
+ *
+ * // Keeps track of the base flight price of the selected city
+ * var FlightPriceStore = {price: null}
+ *
+ * When a user changes the selected city, we dispatch the payload:
+ *
+ * flightDispatcher.dispatch({
+ * actionType: 'city-update',
+ * selectedCity: 'paris'
+ * });
+ *
+ * This payload is digested by `CityStore`:
+ *
+ * flightDispatcher.register(function(payload) {
+ * if (payload.actionType === 'city-update') {
+ * CityStore.city = payload.selectedCity;
+ * }
+ * });
+ *
+ * When the user selects a country, we dispatch the payload:
+ *
+ * flightDispatcher.dispatch({
+ * actionType: 'country-update',
+ * selectedCountry: 'australia'
+ * });
+ *
+ * This payload is digested by both stores:
+ *
+ * CountryStore.dispatchToken = flightDispatcher.register(function(payload) {
+ * if (payload.actionType === 'country-update') {
+ * CountryStore.country = payload.selectedCountry;
+ * }
+ * });
+ *
+ * When the callback to update `CountryStore` is registered, we save a reference
+ * to the returned token. Using this token with `waitFor()`, we can guarantee
+ * that `CountryStore` is updated before the callback that updates `CityStore`
+ * needs to query its data.
+ *
+ * CityStore.dispatchToken = flightDispatcher.register(function(payload) {
+ * if (payload.actionType === 'country-update') {
+ * // `CountryStore.country` may not be updated.
+ * flightDispatcher.waitFor([CountryStore.dispatchToken]);
+ * // `CountryStore.country` is now guaranteed to be updated.
+ *
+ * // Select the default city for the new country
+ * CityStore.city = getDefaultCityForCountry(CountryStore.country);
+ * }
+ * });
+ *
+ * The usage of `waitFor()` can be chained, for example:
+ *
+ * FlightPriceStore.dispatchToken =
+ * flightDispatcher.register(function(payload) {
+ * switch (payload.actionType) {
+ * case 'country-update':
+ * flightDispatcher.waitFor([CityStore.dispatchToken]);
+ * FlightPriceStore.price =
+ * getFlightPriceStore(CountryStore.country, CityStore.city);
+ * break;
+ *
+ * case 'city-update':
+ * FlightPriceStore.price =
+ * FlightPriceStore(CountryStore.country, CityStore.city);
+ * break;
+ * }
+ * });
+ *
+ * The `country-update` payload will be guaranteed to invoke the stores'
+ * registered callbacks in order: `CountryStore`, `CityStore`, then
+ * `FlightPriceStore`.
+ */
+
+ function Dispatcher() {"use strict";
+ this.$Dispatcher_callbacks = {};
+ this.$Dispatcher_isPending = {};
+ this.$Dispatcher_isHandled = {};
+ this.$Dispatcher_isDispatching = false;
+ this.$Dispatcher_pendingPayload = null;
+ }
+
+ /**
+ * Registers a callback to be invoked with every dispatched payload. Returns
+ * a token that can be used with `waitFor()`.
+ *
+ * @param {function} callback
+ * @return {string}
+ */
+ Dispatcher.prototype.register=function(callback) {"use strict";
+ var id = _prefix + _lastID++;
+ this.$Dispatcher_callbacks[id] = callback;
+ return id;
+ };
+
+ /**
+ * Removes a callback based on its token.
+ *
+ * @param {string} id
+ */
+ Dispatcher.prototype.unregister=function(id) {"use strict";
+ invariant(
+ this.$Dispatcher_callbacks[id],
+ 'Dispatcher.unregister(...): `%s` does not map to a registered callback.',
+ id
+ );
+ delete this.$Dispatcher_callbacks[id];
+ };
+
+ /**
+ * Waits for the callbacks specified to be invoked before continuing execution
+ * of the current callback. This method should only be used by a callback in
+ * response to a dispatched payload.
+ *
+ * @param {array<string>} ids
+ */
+ Dispatcher.prototype.waitFor=function(ids) {"use strict";
+ invariant(
+ this.$Dispatcher_isDispatching,
+ 'Dispatcher.waitFor(...): Must be invoked while dispatching.'
+ );
+ for (var ii = 0; ii < ids.length; ii++) {
+ var id = ids[ii];
+ if (this.$Dispatcher_isPending[id]) {
+ invariant(
+ this.$Dispatcher_isHandled[id],
+ 'Dispatcher.waitFor(...): Circular dependency detected while ' +
+ 'waiting for `%s`.',
+ id
+ );
+ continue;
+ }
+ invariant(
+ this.$Dispatcher_callbacks[id],
+ 'Dispatcher.waitFor(...): `%s` does not map to a registered callback.',
+ id
+ );
+ this.$Dispatcher_invokeCallback(id);
+ }
+ };
+
+ /**
+ * Dispatches a payload to all registered callbacks.
+ *
+ * @param {object} payload
+ */
+ Dispatcher.prototype.dispatch=function(payload) {"use strict";
+ invariant(
+ !this.$Dispatcher_isDispatching,
+ 'Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.'
+ );
+ this.$Dispatcher_startDispatching(payload);
+ try {
+ for (var id in this.$Dispatcher_callbacks) {
+ if (this.$Dispatcher_isPending[id]) {
+ continue;
+ }
+ this.$Dispatcher_invokeCallback(id);
+ }
+ } finally {
+ this.$Dispatcher_stopDispatching();
+ }
+ };
+
+ /**
+ * Is this Dispatcher currently dispatching.
+ *
+ * @return {boolean}
+ */
+ Dispatcher.prototype.isDispatching=function() {"use strict";
+ return this.$Dispatcher_isDispatching;
+ };
+
+ /**
+ * Call the callback stored with the given id. Also do some internal
+ * bookkeeping.
+ *
+ * @param {string} id
+ * @internal
+ */
+ Dispatcher.prototype.$Dispatcher_invokeCallback=function(id) {"use strict";
+ this.$Dispatcher_isPending[id] = true;
+ this.$Dispatcher_callbacks[id](this.$Dispatcher_pendingPayload);
+ this.$Dispatcher_isHandled[id] = true;
+ };
+
+ /**
+ * Set up bookkeeping needed when dispatching.
+ *
+ * @param {object} payload
+ * @internal
+ */
+ Dispatcher.prototype.$Dispatcher_startDispatching=function(payload) {"use strict";
+ for (var id in this.$Dispatcher_callbacks) {
+ this.$Dispatcher_isPending[id] = false;
+ this.$Dispatcher_isHandled[id] = false;
+ }
+ this.$Dispatcher_pendingPayload = payload;
+ this.$Dispatcher_isDispatching = true;
+ };
+
+ /**
+ * Clear bookkeeping used for dispatching.
+ *
+ * @internal
+ */
+ Dispatcher.prototype.$Dispatcher_stopDispatching=function() {"use strict";
+ this.$Dispatcher_pendingPayload = null;
+ this.$Dispatcher_isDispatching = false;
+ };
+
+
+module.exports = Dispatcher;
+
+},{"./invariant":33}],33:[function(_dereq_,module,exports){
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule invariant
+ */
+
+"use strict";
+
+/**
+ * Use invariant() to assert state which your program assumes to be true.
+ *
+ * Provide sprintf-style format (only %s is supported) and arguments
+ * to provide information about what broke and what you were
+ * expecting.
+ *
+ * The invariant message will be stripped in production, but the invariant
+ * will remain to ensure logic does not differ in production.
+ */
+
+var invariant = function(condition, format, a, b, c, d, e, f) {
+ if (false) {
+ if (format === undefined) {
+ throw new Error('invariant requires an error message argument');
+ }
+ }
+
+ if (!condition) {
+ var error;
+ if (format === undefined) {
+ error = new Error(
+ 'Minified exception occurred; use the non-minified dev environment ' +
+ 'for the full error message and additional helpful warnings.'
+ );
+ } else {
+ var args = [a, b, c, d, e, f];
+ var argIndex = 0;
+ error = new Error(
+ 'Invariant Violation: ' +
+ format.replace(/%s/g, function() { return args[argIndex++]; })
+ );
+ }
+
+ error.framesToPop = 1; // we don't care about invariant's own frame
+ throw error;
+ }
+};
+
+module.exports = invariant;
+
+},{}],34:[function(_dereq_,module,exports){
+module.exports = _dereq_('./lib');
+
+},{"./lib":35}],35:[function(_dereq_,module,exports){
+// Load modules
+
+var Stringify = _dereq_('./stringify');
+var Parse = _dereq_('./parse');
+
+
+// Declare internals
+
+var internals = {};
+
+
+module.exports = {
+ stringify: Stringify,
+ parse: Parse
+};
+
+},{"./parse":36,"./stringify":37}],36:[function(_dereq_,module,exports){
+// Load modules
+
+var Utils = _dereq_('./utils');
+
+
+// Declare internals
+
+var internals = {
+ delimiter: '&',
+ depth: 5,
+ arrayLimit: 20,
+ parameterLimit: 1000
+};
+
+
+internals.parseValues = function (str, options) {
+
+ var obj = {};
+ var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
+
+ for (var i = 0, il = parts.length; i < il; ++i) {
+ var part = parts[i];
+ var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
+
+ if (pos === -1) {
+ obj[Utils.decode(part)] = '';
+ }
+ else {
+ var key = Utils.decode(part.slice(0, pos));
+ var val = Utils.decode(part.slice(pos + 1));
+
+ if (!obj[key]) {
+ obj[key] = val;
+ }
+ else {
+ obj[key] = [].concat(obj[key]).concat(val);
+ }
+ }
+ }
+
+ return obj;
+};
+
+
+internals.parseObject = function (chain, val, options) {
+
+ if (!chain.length) {
+ return val;
+ }
+
+ var root = chain.shift();
+
+ var obj = {};
+ if (root === '[]') {
+ obj = [];
+ obj = obj.concat(internals.parseObject(chain, val, options));
+ }
+ else {
+ var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
+ var index = parseInt(cleanRoot, 10);
+ if (!isNaN(index) &&
+ root !== cleanRoot &&
+ index <= options.arrayLimit) {
+
+ obj = [];
+ obj[index] = internals.parseObject(chain, val, options);
+ }
+ else {
+ obj[cleanRoot] = internals.parseObject(chain, val, options);
+ }
+ }
+
+ return obj;
+};
+
+
+internals.parseKeys = function (key, val, options) {
+
+ if (!key) {
+ return;
+ }
+
+ // The regex chunks
+
+ var parent = /^([^\[\]]*)/;
+ var child = /(\[[^\[\]]*\])/g;
+
+ // Get the parent
+
+ var segment = parent.exec(key);
+
+ // Don't allow them to overwrite object prototype properties
+
+ if (Object.prototype.hasOwnProperty(segment[1])) {
+ return;
+ }
+
+ // Stash the parent if it exists
+
+ var keys = [];
+ if (segment[1]) {
+ keys.push(segment[1]);
+ }
+
+ // Loop through children appending to the array until we hit depth
+
+ var i = 0;
+ while ((segment = child.exec(key)) !== null && i < options.depth) {
+
+ ++i;
+ if (!Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) {
+ keys.push(segment[1]);
+ }
+ }
+
+ // If there's a remainder, just add whatever is left
+
+ if (segment) {
+ keys.push('[' + key.slice(segment.index) + ']');
+ }
+
+ return internals.parseObject(keys, val, options);
+};
+
+
+module.exports = function (str, options) {
+
+ if (str === '' ||
+ str === null ||
+ typeof str === 'undefined') {
+
+ return {};
+ }
+
+ options = options || {};
+ options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter;
+ options.depth = typeof options.depth === 'number' ? options.depth : internals.depth;
+ options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit;
+ options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit;
+
+ var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str;
+ var obj = {};
+
+ // Iterate over the keys and setup the new object
+
+ var keys = Object.keys(tempObj);
+ for (var i = 0, il = keys.length; i < il; ++i) {
+ var key = keys[i];
+ var newObj = internals.parseKeys(key, tempObj[key], options);
+ obj = Utils.merge(obj, newObj);
+ }
+
+ return Utils.compact(obj);
+};
+
+},{"./utils":38}],37:[function(_dereq_,module,exports){
+// Load modules
+
+var Utils = _dereq_('./utils');
+
+
+// Declare internals
+
+var internals = {
+ delimiter: '&'
+};
+
+
+internals.stringify = function (obj, prefix) {
+
+ if (Utils.isBuffer(obj)) {
+ obj = obj.toString();
+ }
+ else if (obj instanceof Date) {
+ obj = obj.toISOString();
+ }
+ else if (obj === null) {
+ obj = '';
+ }
+
+ if (typeof obj === 'string' ||
+ typeof obj === 'number' ||
+ typeof obj === 'boolean') {
+
+ return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)];
+ }
+
+ var values = [];
+
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']'));
+ }
+ }
+
+ return values;
+};
+
+
+module.exports = function (obj, options) {
+
+ options = options || {};
+ var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
+
+ var keys = [];
+
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ keys = keys.concat(internals.stringify(obj[key], key));
+ }
+ }
+
+ return keys.join(delimiter);
+};
+
+},{"./utils":38}],38:[function(_dereq_,module,exports){
+// Load modules
+
+
+// Declare internals
+
+var internals = {};
+
+
+exports.arrayToObject = function (source) {
+
+ var obj = {};
+ for (var i = 0, il = source.length; i < il; ++i) {
+ if (typeof source[i] !== 'undefined') {
+
+ obj[i] = source[i];
+ }
+ }
+
+ return obj;
+};
+
+
+exports.merge = function (target, source) {
+
+ if (!source) {
+ return target;
+ }
+
+ if (Array.isArray(source)) {
+ for (var i = 0, il = source.length; i < il; ++i) {
+ if (typeof source[i] !== 'undefined') {
+ if (typeof target[i] === 'object') {
+ target[i] = exports.merge(target[i], source[i]);
+ }
+ else {
+ target[i] = source[i];
+ }
+ }
+ }
+
+ return target;
+ }
+
+ if (Array.isArray(target)) {
+ if (typeof source !== 'object') {
+ target.push(source);
+ return target;
+ }
+ else {
+ target = exports.arrayToObject(target);
+ }
+ }
+
+ var keys = Object.keys(source);
+ for (var k = 0, kl = keys.length; k < kl; ++k) {
+ var key = keys[k];
+ var value = source[key];
+
+ if (value &&
+ typeof value === 'object') {
+
+ if (!target[key]) {
+ target[key] = value;
+ }
+ else {
+ target[key] = exports.merge(target[key], value);
+ }
+ }
+ else {
+ target[key] = value;
+ }
+ }
+
+ return target;
+};
+
+
+exports.decode = function (str) {
+
+ try {
+ return decodeURIComponent(str.replace(/\+/g, ' '));
+ } catch (e) {
+ return str;
+ }
+};
+
+
+exports.compact = function (obj, refs) {
+
+ if (typeof obj !== 'object' ||
+ obj === null) {
+
+ return obj;
+ }
+
+ refs = refs || [];
+ var lookup = refs.indexOf(obj);
+ if (lookup !== -1) {
+ return refs[lookup];
+ }
+
+ refs.push(obj);
+
+ if (Array.isArray(obj)) {
+ var compacted = [];
+
+ for (var i = 0, l = obj.length; i < l; ++i) {
+ if (typeof obj[i] !== 'undefined') {
+ compacted.push(obj[i]);
+ }
+ }
+
+ return compacted;
+ }
+
+ var keys = Object.keys(obj);
+ for (var i = 0, il = keys.length; i < il; ++i) {
+ var key = keys[i];
+ obj[key] = exports.compact(obj[key], refs);
+ }
+
+ return obj;
+};
+
+
+exports.isRegExp = function (obj) {
+ return Object.prototype.toString.call(obj) === '[object RegExp]';
+};
+
+
+exports.isBuffer = function (obj) {
+
+ if (typeof Buffer !== 'undefined') {
+ return Buffer.isBuffer(obj);
+ }
+ else {
+ return false;
+ }
+};
+
+},{}],39:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule ExecutionEnvironment
+ */
+
+/*jslint evil: true */
+
+"use strict";
+
+var canUseDOM = !!(
+ typeof window !== 'undefined' &&
+ window.document &&
+ window.document.createElement
+);
+
+/**
+ * Simple, lightweight module assisting with the detection and context of
+ * Worker. Helps avoid circular dependencies and allows code to reason about
+ * whether or not they are in a Worker, even if they never include the main
+ * `ReactWorker` dependency.
+ */
+var ExecutionEnvironment = {
+
+ canUseDOM: canUseDOM,
+
+ canUseWorkers: typeof Worker !== 'undefined',
+
+ canUseEventListeners:
+ canUseDOM && !!(window.addEventListener || window.attachEvent),
+
+ canUseViewport: canUseDOM && !!window.screen,
+
+ isInWorker: !canUseDOM // For now, this is true - might change in the future.
+
+};
+
+module.exports = ExecutionEnvironment;
+
+},{}],40:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule copyProperties
+ */
+
+/**
+ * Copy properties from one or more objects (up to 5) into the first object.
+ * This is a shallow copy. It mutates the first object and also returns it.
+ *
+ * NOTE: `arguments` has a very significant performance penalty, which is why
+ * we don't support unlimited arguments.
+ */
+function copyProperties(obj, a, b, c, d, e, f) {
+ obj = obj || {};
+
+ if ("production" !== "production") {
+ if (f) {
+ throw new Error('Too many arguments passed to copyProperties');
+ }
+ }
+
+ var args = [a, b, c, d, e];
+ var ii = 0, v;
+ while (args[ii]) {
+ v = args[ii++];
+ for (var k in v) {
+ obj[k] = v[k];
+ }
+
+ // IE ignores toString in object iteration.. See:
+ // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html
+ if (v.hasOwnProperty && v.hasOwnProperty('toString') &&
+ (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) {
+ obj.toString = v.toString;
+ }
+ }
+
+ return obj;
+}
+
+module.exports = copyProperties;
+
+},{}],41:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule emptyFunction
+ */
+
+var copyProperties = _dereq_("./copyProperties");
+
+function makeEmptyFunction(arg) {
+ return function() {
+ return arg;
+ };
+}
+
+/**
+ * This function accepts and discards inputs; it has no side effects. This is
+ * primarily useful idiomatically for overridable function endpoints which
+ * always need to be callable, since JS lacks a null-call idiom ala Cocoa.
+ */
+function emptyFunction() {}
+
+copyProperties(emptyFunction, {
+ thatReturns: makeEmptyFunction,
+ thatReturnsFalse: makeEmptyFunction(false),
+ thatReturnsTrue: makeEmptyFunction(true),
+ thatReturnsNull: makeEmptyFunction(null),
+ thatReturnsThis: function() { return this; },
+ thatReturnsArgument: function(arg) { return arg; }
+});
+
+module.exports = emptyFunction;
+
+},{"./copyProperties":40}],42:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule invariant
+ */
+
+"use strict";
+
+/**
+ * Use invariant() to assert state which your program assumes to be true.
+ *
+ * Provide sprintf-style format (only %s is supported) and arguments
+ * to provide information about what broke and what you were
+ * expecting.
+ *
+ * The invariant message will be stripped in production, but the invariant
+ * will remain to ensure logic does not differ in production.
+ */
+
+var invariant = function(condition, format, a, b, c, d, e, f) {
+ if ("production" !== "production") {
+ if (format === undefined) {
+ throw new Error('invariant requires an error message argument');
+ }
+ }
+
+ if (!condition) {
+ var error;
+ if (format === undefined) {
+ error = new Error(
+ 'Minified exception occurred; use the non-minified dev environment ' +
+ 'for the full error message and additional helpful warnings.'
+ );
+ } else {
+ var args = [a, b, c, d, e, f];
+ var argIndex = 0;
+ error = new Error(
+ 'Invariant Violation: ' +
+ format.replace(/%s/g, function() { return args[argIndex++]; })
+ );
+ }
+
+ error.framesToPop = 1; // we don't care about invariant's own frame
+ throw error;
+ }
+};
+
+module.exports = invariant;
+
+},{}],43:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule keyMirror
+ * @typechecks static-only
+ */
+
+"use strict";
+
+var invariant = _dereq_("./invariant");
+
+/**
+ * Constructs an enumeration with keys equal to their value.
+ *
+ * For example:
+ *
+ * var COLORS = keyMirror({blue: null, red: null});
+ * var myColor = COLORS.blue;
+ * var isColorValid = !!COLORS[myColor];
+ *
+ * The last line could not be performed if the values of the generated enum were
+ * not equal to their keys.
+ *
+ * Input: {key1: val1, key2: val2}
+ * Output: {key1: key1, key2: key2}
+ *
+ * @param {object} obj
+ * @return {object}
+ */
+var keyMirror = function(obj) {
+ var ret = {};
+ var key;
+ ("production" !== "production" ? invariant(
+ obj instanceof Object && !Array.isArray(obj),
+ 'keyMirror(...): Argument must be an object.'
+ ) : invariant(obj instanceof Object && !Array.isArray(obj)));
+ for (key in obj) {
+ if (!obj.hasOwnProperty(key)) {
+ continue;
+ }
+ ret[key] = key;
+ }
+ return ret;
+};
+
+module.exports = keyMirror;
+
+},{"./invariant":42}],44:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule merge
+ */
+
+"use strict";
+
+var mergeInto = _dereq_("./mergeInto");
+
+/**
+ * Shallow merges two structures into a return value, without mutating either.
+ *
+ * @param {?object} one Optional object with properties to merge from.
+ * @param {?object} two Optional object with properties to merge from.
+ * @return {object} The shallow extension of one by two.
+ */
+var merge = function(one, two) {
+ var result = {};
+ mergeInto(result, one);
+ mergeInto(result, two);
+ return result;
+};
+
+module.exports = merge;
+
+},{"./mergeInto":46}],45:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule mergeHelpers
+ *
+ * requiresPolyfills: Array.isArray
+ */
+
+"use strict";
+
+var invariant = _dereq_("./invariant");
+var keyMirror = _dereq_("./keyMirror");
+
+/**
+ * Maximum number of levels to traverse. Will catch circular structures.
+ * @const
+ */
+var MAX_MERGE_DEPTH = 36;
+
+/**
+ * We won't worry about edge cases like new String('x') or new Boolean(true).
+ * Functions are considered terminals, and arrays are not.
+ * @param {*} o The item/object/value to test.
+ * @return {boolean} true iff the argument is a terminal.
+ */
+var isTerminal = function(o) {
+ return typeof o !== 'object' || o === null;
+};
+
+var mergeHelpers = {
+
+ MAX_MERGE_DEPTH: MAX_MERGE_DEPTH,
+
+ isTerminal: isTerminal,
+
+ /**
+ * Converts null/undefined values into empty object.
+ *
+ * @param {?Object=} arg Argument to be normalized (nullable optional)
+ * @return {!Object}
+ */
+ normalizeMergeArg: function(arg) {
+ return arg === undefined || arg === null ? {} : arg;
+ },
+
+ /**
+ * If merging Arrays, a merge strategy *must* be supplied. If not, it is
+ * likely the caller's fault. If this function is ever called with anything
+ * but `one` and `two` being `Array`s, it is the fault of the merge utilities.
+ *
+ * @param {*} one Array to merge into.
+ * @param {*} two Array to merge from.
+ */
+ checkMergeArrayArgs: function(one, two) {
+ ("production" !== "production" ? invariant(
+ Array.isArray(one) && Array.isArray(two),
+ 'Tried to merge arrays, instead got %s and %s.',
+ one,
+ two
+ ) : invariant(Array.isArray(one) && Array.isArray(two)));
+ },
+
+ /**
+ * @param {*} one Object to merge into.
+ * @param {*} two Object to merge from.
+ */
+ checkMergeObjectArgs: function(one, two) {
+ mergeHelpers.checkMergeObjectArg(one);
+ mergeHelpers.checkMergeObjectArg(two);
+ },
+
+ /**
+ * @param {*} arg
+ */
+ checkMergeObjectArg: function(arg) {
+ ("production" !== "production" ? invariant(
+ !isTerminal(arg) && !Array.isArray(arg),
+ 'Tried to merge an object, instead got %s.',
+ arg
+ ) : invariant(!isTerminal(arg) && !Array.isArray(arg)));
+ },
+
+ /**
+ * @param {*} arg
+ */
+ checkMergeIntoObjectArg: function(arg) {
+ ("production" !== "production" ? invariant(
+ (!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg),
+ 'Tried to merge into an object, instead got %s.',
+ arg
+ ) : invariant((!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg)));
+ },
+
+ /**
+ * Checks that a merge was not given a circular object or an object that had
+ * too great of depth.
+ *
+ * @param {number} Level of recursion to validate against maximum.
+ */
+ checkMergeLevel: function(level) {
+ ("production" !== "production" ? invariant(
+ level < MAX_MERGE_DEPTH,
+ 'Maximum deep merge depth exceeded. You may be attempting to merge ' +
+ 'circular structures in an unsupported way.'
+ ) : invariant(level < MAX_MERGE_DEPTH));
+ },
+
+ /**
+ * Checks that the supplied merge strategy is valid.
+ *
+ * @param {string} Array merge strategy.
+ */
+ checkArrayStrategy: function(strategy) {
+ ("production" !== "production" ? invariant(
+ strategy === undefined || strategy in mergeHelpers.ArrayStrategies,
+ 'You must provide an array strategy to deep merge functions to ' +
+ 'instruct the deep merge how to resolve merging two arrays.'
+ ) : invariant(strategy === undefined || strategy in mergeHelpers.ArrayStrategies));
+ },
+
+ /**
+ * Set of possible behaviors of merge algorithms when encountering two Arrays
+ * that must be merged together.
+ * - `clobber`: The left `Array` is ignored.
+ * - `indexByIndex`: The result is achieved by recursively deep merging at
+ * each index. (not yet supported.)
+ */
+ ArrayStrategies: keyMirror({
+ Clobber: true,
+ IndexByIndex: true
+ })
+
+};
+
+module.exports = mergeHelpers;
+
+},{"./invariant":42,"./keyMirror":43}],46:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule mergeInto
+ * @typechecks static-only
+ */
+
+"use strict";
+
+var mergeHelpers = _dereq_("./mergeHelpers");
+
+var checkMergeObjectArg = mergeHelpers.checkMergeObjectArg;
+var checkMergeIntoObjectArg = mergeHelpers.checkMergeIntoObjectArg;
+
+/**
+ * Shallow merges two structures by mutating the first parameter.
+ *
+ * @param {object|function} one Object to be merged into.
+ * @param {?object} two Optional object with properties to merge from.
+ */
+function mergeInto(one, two) {
+ checkMergeIntoObjectArg(one);
+ if (two != null) {
+ checkMergeObjectArg(two);
+ for (var key in two) {
+ if (!two.hasOwnProperty(key)) {
+ continue;
+ }
+ one[key] = two[key];
+ }
+ }
+}
+
+module.exports = mergeInto;
+
+},{"./mergeHelpers":45}],47:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule mixInto
+ */
+
+"use strict";
+
+/**
+ * Simply copies properties to the prototype.
+ */
+var mixInto = function(constructor, methodBag) {
+ var methodName;
+ for (methodName in methodBag) {
+ if (!methodBag.hasOwnProperty(methodName)) {
+ continue;
+ }
+ constructor.prototype[methodName] = methodBag[methodName];
+ }
+};
+
+module.exports = mixInto;
+
+},{}],48:[function(_dereq_,module,exports){
+/**
+ * Copyright 2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule warning
+ */
+
+"use strict";
+
+var emptyFunction = _dereq_("./emptyFunction");
+
+/**
+ * Similar to invariant but only logs a warning if the condition is not met.
+ * This can be used to log issues in development environments in critical
+ * paths. Removing the logging code for production environments will keep the
+ * same logic and follow the same code paths.
+ */
+
+var warning = emptyFunction;
+
+if ("production" !== "production") {
+ warning = function(condition, format ) {var args=Array.prototype.slice.call(arguments,2);
+ if (format === undefined) {
+ throw new Error(
+ '`warning(condition, format, ...args)` requires a warning ' +
+ 'message argument'
+ );
+ }
+
+ if (!condition) {
+ var argIndex = 0;
+ console.warn('Warning: ' + format.replace(/%s/g, function() {return args[argIndex++];}));
+ }
+ };
+}
+
+module.exports = warning;
+
+},{"./emptyFunction":41}],49:[function(_dereq_,module,exports){
+/** @license MIT License (c) copyright 2010-2014 original author or authors */
+/** @author Brian Cavalier */
+/** @author John Hann */
+
+(function(define) { 'use strict';
+define(function (_dereq_) {
+
+ var makePromise = _dereq_('./makePromise');
+ var Scheduler = _dereq_('./Scheduler');
+ var async = _dereq_('./async');
+
+ return makePromise({
+ scheduler: new Scheduler(async)
+ });
+
+});
+})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(_dereq_); });
+
+},{"./Scheduler":51,"./async":52,"./makePromise":53}],50:[function(_dereq_,module,exports){
+/** @license MIT License (c) copyright 2010-2014 original author or authors */
+/** @author Brian Cavalier */
+/** @author John Hann */
+
+(function(define) { 'use strict';
+define(function() {
+ /**
+ * Circular queue
+ * @param {number} capacityPow2 power of 2 to which this queue's capacity
+ * will be set initially. eg when capacityPow2 == 3, queue capacity
+ * will be 8.
+ * @constructor
+ */
+ function Queue(capacityPow2) {
+ this.head = this.tail = this.length = 0;
+ this.buffer = new Array(1 << capacityPow2);
+ }
+
+ Queue.prototype.push = function(x) {
+ if(this.length === this.buffer.length) {
+ this._ensureCapacity(this.length * 2);
+ }
+
+ this.buffer[this.tail] = x;
+ this.tail = (this.tail + 1) & (this.buffer.length - 1);
+ ++this.length;
+ return this.length;
+ };
+
+ Queue.prototype.shift = function() {
+ var x = this.buffer[this.head];
+ this.buffer[this.head] = void 0;
+ this.head = (this.head + 1) & (this.buffer.length - 1);
+ --this.length;
+ return x;
+ };
+
+ Queue.prototype._ensureCapacity = function(capacity) {
+ var head = this.head;
+ var buffer = this.buffer;
+ var newBuffer = new Array(capacity);
+ var i = 0;
+ var len;
+
+ if(head === 0) {
+ len = this.length;
+ for(; i<len; ++i) {
+ newBuffer[i] = buffer[i];
+ }
+ } else {
+ capacity = buffer.length;
+ len = this.tail;
+ for(; head<capacity; ++i, ++head) {
+ newBuffer[i] = buffer[head];
+ }
+
+ for(head=0; head<len; ++i, ++head) {
+ newBuffer[i] = buffer[head];
+ }
+ }
+
+ this.buffer = newBuffer;
+ this.head = 0;
+ this.tail = this.length;
+ };
+
+ return Queue;
+
+});
+}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
+
+},{}],51:[function(_dereq_,module,exports){
+/** @license MIT License (c) copyright 2010-2014 original author or authors */
+/** @author Brian Cavalier */
+/** @author John Hann */
+
+(function(define) { 'use strict';
+define(function(_dereq_) {
+
+ var Queue = _dereq_('./Queue');
+
+ // Credit to Twisol (https://github.com/Twisol) for suggesting
+ // this type of extensible queue + trampoline approach for next-tick conflation.
+
+ /**
+ * Async task scheduler
+ * @param {function} async function to schedule a single async function
+ * @constructor
+ */
+ function Scheduler(async) {
+ this._async = async;
+ this._queue = new Queue(15);
+ this._afterQueue = new Queue(5);
+ this._running = false;
+
+ var self = this;
+ this.drain = function() {
+ self._drain();
+ };
+ }
+
+ /**
+ * Enqueue a task
+ * @param {{ run:function }} task
+ */
+ Scheduler.prototype.enqueue = function(task) {
+ this._add(this._queue, task);
+ };
+
+ /**
+ * Enqueue a task to run after the main task queue
+ * @param {{ run:function }} task
+ */
+ Scheduler.prototype.afterQueue = function(task) {
+ this._add(this._afterQueue, task);
+ };
+
+ /**
+ * Drain the handler queue entirely, and then the after queue
+ */
+ Scheduler.prototype._drain = function() {
+ runQueue(this._queue);
+ this._running = false;
+ runQueue(this._afterQueue);
+ };
+
+ /**
+ * Add a task to the q, and schedule drain if not already scheduled
+ * @param {Queue} queue
+ * @param {{run:function}} task
+ * @private
+ */
+ Scheduler.prototype._add = function(queue, task) {
+ queue.push(task);
+ if(!this._running) {
+ this._running = true;
+ this._async(this.drain);
+ }
+ };
+
+ /**
+ * Run all the tasks in the q
+ * @param queue
+ */
+ function runQueue(queue) {
+ while(queue.length > 0) {
+ queue.shift().run();
+ }
+ }
+
+ return Scheduler;
+
+});
+}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); }));
+
+},{"./Queue":50}],52:[function(_dereq_,module,exports){
+/** @license MIT License (c) copyright 2010-2014 original author or authors */
+/** @author Brian Cavalier */
+/** @author John Hann */
+
+(function(define) { 'use strict';
+define(function(_dereq_) {
+
+ // Sniff "best" async scheduling option
+ // Prefer process.nextTick or MutationObserver, then check for
+ // vertx and finally fall back to setTimeout
+
+ /*jshint maxcomplexity:6*/
+ /*global process,document,setTimeout,MutationObserver,WebKitMutationObserver*/
+ var nextTick, MutationObs;
+
+ if (typeof process !== 'undefined' && process !== null &&
+ typeof process.nextTick === 'function') {
+ nextTick = function(f) {
+ process.nextTick(f);
+ };
+
+ } else if (MutationObs =
+ (typeof MutationObserver === 'function' && MutationObserver) ||
+ (typeof WebKitMutationObserver === 'function' && WebKitMutationObserver)) {
+ nextTick = (function (document, MutationObserver) {
+ var scheduled;
+ var el = document.createElement('div');
+ var o = new MutationObserver(run);
+ o.observe(el, { attributes: true });
+
+ function run() {
+ var f = scheduled;
+ scheduled = void 0;
+ f();
+ }
+
+ return function (f) {
+ scheduled = f;
+ el.setAttribute('class', 'x');
+ };
+ }(document, MutationObs));
+
+ } else {
+ nextTick = (function(cjsRequire) {
+ try {
+ // vert.x 1.x || 2.x
+ return cjsRequire('vertx').runOnLoop || cjsRequire('vertx').runOnContext;
+ } catch (ignore) {}
+
+ // capture setTimeout to avoid being caught by fake timers
+ // used in time based tests
+ var capturedSetTimeout = setTimeout;
+ return function (t) {
+ capturedSetTimeout(t, 0);
+ };
+ }(_dereq_));
+ }
+
+ return nextTick;
+});
+}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); }));
+
+},{}],53:[function(_dereq_,module,exports){
+/** @license MIT License (c) copyright 2010-2014 original author or authors */
+/** @author Brian Cavalier */
+/** @author John Hann */
+
+(function(define) { 'use strict';
+define(function() {
+
+ return function makePromise(environment) {
+
+ var tasks = environment.scheduler;
+
+ var objectCreate = Object.create ||
+ function(proto) {
+ function Child() {}
+ Child.prototype = proto;
+ return new Child();
+ };
+
+ /**
+ * Create a promise whose fate is determined by resolver
+ * @constructor
+ * @returns {Promise} promise
+ * @name Promise
+ */
+ function Promise(resolver, handler) {
+ this._handler = resolver === Handler ? handler : init(resolver);
+ }
+
+ /**
+ * Run the supplied resolver
+ * @param resolver
+ * @returns {Pending}
+ */
+ function init(resolver) {
+ var handler = new Pending();
+
+ try {
+ resolver(promiseResolve, promiseReject, promiseNotify);
+ } catch (e) {
+ promiseReject(e);
+ }
+
+ return handler;
+
+ /**
+ * Transition from pre-resolution state to post-resolution state, notifying
+ * all listeners of the ultimate fulfillment or rejection
+ * @param {*} x resolution value
+ */
+ function promiseResolve (x) {
+ handler.resolve(x);
+ }
+ /**
+ * Reject this promise with reason, which will be used verbatim
+ * @param {Error|*} reason rejection reason, strongly suggested
+ * to be an Error type
+ */
+ function promiseReject (reason) {
+ handler.reject(reason);
+ }
+
+ /**
+ * Issue a progress event, notifying all progress listeners
+ * @param {*} x progress event payload to pass to all listeners
+ */
+ function promiseNotify (x) {
+ handler.notify(x);
+ }
+ }
+
+ // Creation
+
+ Promise.resolve = resolve;
+ Promise.reject = reject;
+ Promise.never = never;
+
+ Promise._defer = defer;
+ Promise._handler = getHandler;
+
+ /**
+ * Returns a trusted promise. If x is already a trusted promise, it is
+ * returned, otherwise returns a new trusted Promise which follows x.
+ * @param {*} x
+ * @return {Promise} promise
+ */
+ function resolve(x) {
+ return isPromise(x) ? x
+ : new Promise(Handler, new Async(getHandler(x)));
+ }
+
+ /**
+ * Return a reject promise with x as its reason (x is used verbatim)
+ * @param {*} x
+ * @returns {Promise} rejected promise
+ */
+ function reject(x) {
+ return new Promise(Handler, new Async(new Rejected(x)));
+ }
+
+ /**
+ * Return a promise that remains pending forever
+ * @returns {Promise} forever-pending promise.
+ */
+ function never() {
+ return foreverPendingPromise; // Should be frozen
+ }
+
+ /**
+ * Creates an internal {promise, resolver} pair
+ * @private
+ * @returns {Promise}
+ */
+ function defer() {
+ return new Promise(Handler, new Pending());
+ }
+
+ // Transformation and flow control
+
+ /**
+ * Transform this promise's fulfillment value, returning a new Promise
+ * for the transformed result. If the promise cannot be fulfilled, onRejected
+ * is called with the reason. onProgress *may* be called with updates toward
+ * this promise's fulfillment.
+ * @param {function=} onFulfilled fulfillment handler
+ * @param {function=} onRejected rejection handler
+ * @deprecated @param {function=} onProgress progress handler
+ * @return {Promise} new promise
+ */
+ Promise.prototype.then = function(onFulfilled, onRejected) {
+ var parent = this._handler;
+
+ if (typeof onFulfilled !== 'function' && parent.join().state() > 0) {
+ // Short circuit: value will not change, simply share handler
+ return new Promise(Handler, parent);
+ }
+
+ var p = this._beget();
+ var child = p._handler;
+
+ parent.chain(child, parent.receiver, onFulfilled, onRejected,
+ arguments.length > 2 ? arguments[2] : void 0);
+
+ return p;
+ };
+
+ /**
+ * If this promise cannot be fulfilled due to an error, call onRejected to
+ * handle the error. Shortcut for .then(undefined, onRejected)
+ * @param {function?} onRejected
+ * @return {Promise}
+ */
+ Promise.prototype['catch'] = function(onRejected) {
+ return this.then(void 0, onRejected);
+ };
+
+ /**
+ * Creates a new, pending promise of the same type as this promise
+ * @private
+ * @returns {Promise}
+ */
+ Promise.prototype._beget = function() {
+ var parent = this._handler;
+ var child = new Pending(parent.receiver, parent.join().context);
+ return new this.constructor(Handler, child);
+ };
+
+ // Array combinators
+
+ Promise.all = all;
+ Promise.race = race;
+
+ /**
+ * Return a promise that will fulfill when all promises in the
+ * input array have fulfilled, or will reject when one of the
+ * promises rejects.
+ * @param {array} promises array of promises
+ * @returns {Promise} promise for array of fulfillment values
+ */
+ function all(promises) {
+ /*jshint maxcomplexity:8*/
+ var resolver = new Pending();
+ var pending = promises.length >>> 0;
+ var results = new Array(pending);
+
+ var i, h, x, s;
+ for (i = 0; i < promises.length; ++i) {
+ x = promises[i];
+
+ if (x === void 0 && !(i in promises)) {
+ --pending;
+ continue;
+ }
+
+ if (maybeThenable(x)) {
+ h = isPromise(x)
+ ? x._handler.join()
+ : getHandlerUntrusted(x);
+
+ s = h.state();
+ if (s === 0) {
+ h.fold(settleAt, i, results, resolver);
+ } else if (s > 0) {
+ results[i] = h.value;
+ --pending;
+ } else {
+ resolver.become(h);
+ break;
+ }
+
+ } else {
+ results[i] = x;
+ --pending;
+ }
+ }
+
+ if(pending === 0) {
+ resolver.become(new Fulfilled(results));
+ }
+
+ return new Promise(Handler, resolver);
+
+ function settleAt(i, x, resolver) {
+ /*jshint validthis:true*/
+ this[i] = x;
+ if(--pending === 0) {
+ resolver.become(new Fulfilled(this));
+ }
+ }
+ }
+
+ /**
+ * Fulfill-reject competitive race. Return a promise that will settle
+ * to the same state as the earliest input promise to settle.
+ *
+ * WARNING: The ES6 Promise spec requires that race()ing an empty array
+ * must return a promise that is pending forever. This implementation
+ * returns a singleton forever-pending promise, the same singleton that is
+ * returned by Promise.never(), thus can be checked with ===
+ *
+ * @param {array} promises array of promises to race
+ * @returns {Promise} if input is non-empty, a promise that will settle
+ * to the same outcome as the earliest input promise to settle. if empty
+ * is empty, returns a promise that will never settle.
+ */
+ function race(promises) {
+ // Sigh, race([]) is untestable unless we return *something*
+ // that is recognizable without calling .then() on it.
+ if(Object(promises) === promises && promises.length === 0) {
+ return never();
+ }
+
+ var h = new Pending();
+ var i, x;
+ for(i=0; i<promises.length; ++i) {
+ x = promises[i];
+ if (x !== void 0 && i in promises) {
+ getHandler(x).visit(h, h.resolve, h.reject);
+ }
+ }
+ return new Promise(Handler, h);
+ }
+
+ // Promise internals
+ // Below this, everything is @private
+
+ /**
+ * Get an appropriate handler for x, without checking for cycles
+ * @param {*} x
+ * @returns {object} handler
+ */
+ function getHandler(x) {
+ if(isPromise(x)) {
+ return x._handler.join();
+ }
+ return maybeThenable(x) ? getHandlerUntrusted(x) : new Fulfilled(x);
+ }
+
+ /**
+ * Get a handler for potentially untrusted thenable x
+ * @param {*} x
+ * @returns {object} handler
+ */
+ function getHandlerUntrusted(x) {
+ try {
+ var untrustedThen = x.then;
+ return typeof untrustedThen === 'function'
+ ? new Thenable(untrustedThen, x)
+ : new Fulfilled(x);
+ } catch(e) {
+ return new Rejected(e);
+ }
+ }
+
+ /**
+ * Handler for a promise that is pending forever
+ * @constructor
+ */
+ function Handler() {}
+
+ Handler.prototype.when
+ = Handler.prototype.become
+ = Handler.prototype.notify
+ = Handler.prototype.fail
+ = Handler.prototype._unreport
+ = Handler.prototype._report
+ = noop;
+
+ Handler.prototype._state = 0;
+
+ Handler.prototype.state = function() {
+ return this._state;
+ };
+
+ /**
+ * Recursively collapse handler chain to find the handler
+ * nearest to the fully resolved value.
+ * @returns {object} handler nearest the fully resolved value
+ */
+ Handler.prototype.join = function() {
+ var h = this;
+ while(h.handler !== void 0) {
+ h = h.handler;
+ }
+ return h;
+ };
+
+ Handler.prototype.chain = function(to, receiver, fulfilled, rejected, progress) {
+ this.when({
+ resolver: to,
+ receiver: receiver,
+ fulfilled: fulfilled,
+ rejected: rejected,
+ progress: progress
+ });
+ };
+
+ Handler.prototype.visit = function(receiver, fulfilled, rejected, progress) {
+ this.chain(failIfRejected, receiver, fulfilled, rejected, progress);
+ };
+
+ Handler.prototype.fold = function(f, z, c, to) {
+ this.visit(to, function(x) {
+ f.call(c, z, x, this);
+ }, to.reject, to.notify);
+ };
+
+ /**
+ * Handler that invokes fail() on any handler it becomes
+ * @constructor
+ */
+ function FailIfRejected() {}
+
+ inherit(Handler, FailIfRejected);
+
+ FailIfRejected.prototype.become = function(h) {
+ h.fail();
+ };
+
+ var failIfRejected = new FailIfRejected();
+
+ /**
+ * Handler that manages a queue of consumers waiting on a pending promise
+ * @constructor
+ */
+ function Pending(receiver, inheritedContext) {
+ Promise.createContext(this, inheritedContext);
+
+ this.consumers = void 0;
+ this.receiver = receiver;
+ this.handler = void 0;
+ this.resolved = false;
+ }
+
+ inherit(Handler, Pending);
+
+ Pending.prototype._state = 0;
+
+ Pending.prototype.resolve = function(x) {
+ this.become(getHandler(x));
+ };
+
+ Pending.prototype.reject = function(x) {
+ if(this.resolved) {
+ return;
+ }
+
+ this.become(new Rejected(x));
+ };
+
+ Pending.prototype.join = function() {
+ if (!this.resolved) {
+ return this;
+ }
+
+ var h = this;
+
+ while (h.handler !== void 0) {
+ h = h.handler;
+ if (h === this) {
+ return this.handler = cycle();
+ }
+ }
+
+ return h;
+ };
+
+ Pending.prototype.run = function() {
+ var q = this.consumers;
+ var handler = this.join();
+ this.consumers = void 0;
+
+ for (var i = 0; i < q.length; ++i) {
+ handler.when(q[i]);
+ }
+ };
+
+ Pending.prototype.become = function(handler) {
+ if(this.resolved) {
+ return;
+ }
+
+ this.resolved = true;
+ this.handler = handler;
+ if(this.consumers !== void 0) {
+ tasks.enqueue(this);
+ }
+
+ if(this.context !== void 0) {
+ handler._report(this.context);
+ }
+ };
+
+ Pending.prototype.when = function(continuation) {
+ if(this.resolved) {
+ tasks.enqueue(new ContinuationTask(continuation, this.handler));
+ } else {
+ if(this.consumers === void 0) {
+ this.consumers = [continuation];
+ } else {
+ this.consumers.push(continuation);
+ }
+ }
+ };
+
+ Pending.prototype.notify = function(x) {
+ if(!this.resolved) {
+ tasks.enqueue(new ProgressTask(x, this));
+ }
+ };
+
+ Pending.prototype.fail = function(context) {
+ var c = typeof context === 'undefined' ? this.context : context;
+ this.resolved && this.handler.join().fail(c);
+ };
+
+ Pending.prototype._report = function(context) {
+ this.resolved && this.handler.join()._report(context);
+ };
+
+ Pending.prototype._unreport = function() {
+ this.resolved && this.handler.join()._unreport();
+ };
+
+ /**
+ * Wrap another handler and force it into a future stack
+ * @param {object} handler
+ * @constructor
+ */
+ function Async(handler) {
+ this.handler = handler;
+ }
+
+ inherit(Handler, Async);
+
+ Async.prototype.when = function(continuation) {
+ tasks.enqueue(new ContinuationTask(continuation, this));
+ };
+
+ Async.prototype._report = function(context) {
+ this.join()._report(context);
+ };
+
+ Async.prototype._unreport = function() {
+ this.join()._unreport();
+ };
+
+ /**
+ * Handler that wraps an untrusted thenable and assimilates it in a future stack
+ * @param {function} then
+ * @param {{then: function}} thenable
+ * @constructor
+ */
+ function Thenable(then, thenable) {
+ Pending.call(this);
+ tasks.enqueue(new AssimilateTask(then, thenable, this));
+ }
+
+ inherit(Pending, Thenable);
+
+ /**
+ * Handler for a fulfilled promise
+ * @param {*} x fulfillment value
+ * @constructor
+ */
+ function Fulfilled(x) {
+ Promise.createContext(this);
+ this.value = x;
+ }
+
+ inherit(Handler, Fulfilled);
+
+ Fulfilled.prototype._state = 1;
+
+ Fulfilled.prototype.fold = function(f, z, c, to) {
+ runContinuation3(f, z, this, c, to);
+ };
+
+ Fulfilled.prototype.when = function(cont) {
+ runContinuation1(cont.fulfilled, this, cont.receiver, cont.resolver);
+ };
+
+ var errorId = 0;
+
+ /**
+ * Handler for a rejected promise
+ * @param {*} x rejection reason
+ * @constructor
+ */
+ function Rejected(x) {
+ Promise.createContext(this);
+
+ this.id = ++errorId;
+ this.value = x;
+ this.handled = false;
+ this.reported = false;
+
+ this._report();
+ }
+
+ inherit(Handler, Rejected);
+
+ Rejected.prototype._state = -1;
+
+ Rejected.prototype.fold = function(f, z, c, to) {
+ to.become(this);
+ };
+
+ Rejected.prototype.when = function(cont) {
+ if(typeof cont.rejected === 'function') {
+ this._unreport();
+ }
+ runContinuation1(cont.rejected, this, cont.receiver, cont.resolver);
+ };
+
+ Rejected.prototype._report = function(context) {
+ tasks.afterQueue(new ReportTask(this, context));
+ };
+
+ Rejected.prototype._unreport = function() {
+ this.handled = true;
+ tasks.afterQueue(new UnreportTask(this));
+ };
+
+ Rejected.prototype.fail = function(context) {
+ Promise.onFatalRejection(this, context === void 0 ? this.context : context);
+ };
+
+ function ReportTask(rejection, context) {
+ this.rejection = rejection;
+ this.context = context;
+ }
+
+ ReportTask.prototype.run = function() {
+ if(!this.rejection.handled) {
+ this.rejection.reported = true;
+ Promise.onPotentiallyUnhandledRejection(this.rejection, this.context);
+ }
+ };
+
+ function UnreportTask(rejection) {
+ this.rejection = rejection;
+ }
+
+ UnreportTask.prototype.run = function() {
+ if(this.rejection.reported) {
+ Promise.onPotentiallyUnhandledRejectionHandled(this.rejection);
+ }
+ };
+
+ // Unhandled rejection hooks
+ // By default, everything is a noop
+
+ // TODO: Better names: "annotate"?
+ Promise.createContext
+ = Promise.enterContext
+ = Promise.exitContext
+ = Promise.onPotentiallyUnhandledRejection
+ = Promise.onPotentiallyUnhandledRejectionHandled
+ = Promise.onFatalRejection
+ = noop;
+
+ // Errors and singletons
+
+ var foreverPendingHandler = new Handler();
+ var foreverPendingPromise = new Promise(Handler, foreverPendingHandler);
+
+ function cycle() {
+ return new Rejected(new TypeError('Promise cycle'));
+ }
+
+ // Task runners
+
+ /**
+ * Run a single consumer
+ * @constructor
+ */
+ function ContinuationTask(continuation, handler) {
+ this.continuation = continuation;
+ this.handler = handler;
+ }
+
+ ContinuationTask.prototype.run = function() {
+ this.handler.join().when(this.continuation);
+ };
+
+ /**
+ * Run a queue of progress handlers
+ * @constructor
+ */
+ function ProgressTask(value, handler) {
+ this.handler = handler;
+ this.value = value;
+ }
+
+ ProgressTask.prototype.run = function() {
+ var q = this.handler.consumers;
+ if(q === void 0) {
+ return;
+ }
+
+ for (var c, i = 0; i < q.length; ++i) {
+ c = q[i];
+ runNotify(c.progress, this.value, this.handler, c.receiver, c.resolver);
+ }
+ };
+
+ /**
+ * Assimilate a thenable, sending it's value to resolver
+ * @param {function} then
+ * @param {object|function} thenable
+ * @param {object} resolver
+ * @constructor
+ */
+ function AssimilateTask(then, thenable, resolver) {
+ this._then = then;
+ this.thenable = thenable;
+ this.resolver = resolver;
+ }
+
+ AssimilateTask.prototype.run = function() {
+ var h = this.resolver;
+ tryAssimilate(this._then, this.thenable, _resolve, _reject, _notify);
+
+ function _resolve(x) { h.resolve(x); }
+ function _reject(x) { h.reject(x); }
+ function _notify(x) { h.notify(x); }
+ };
+
+ function tryAssimilate(then, thenable, resolve, reject, notify) {
+ try {
+ then.call(thenable, resolve, reject, notify);
+ } catch (e) {
+ reject(e);
+ }
+ }
+
+ // Other helpers
+
+ /**
+ * @param {*} x
+ * @returns {boolean} true iff x is a trusted Promise
+ */
+ function isPromise(x) {
+ return x instanceof Promise;
+ }
+
+ /**
+ * Test just enough to rule out primitives, in order to take faster
+ * paths in some code
+ * @param {*} x
+ * @returns {boolean} false iff x is guaranteed *not* to be a thenable
+ */
+ function maybeThenable(x) {
+ return (typeof x === 'object' || typeof x === 'function') && x !== null;
+ }
+
+ function runContinuation1(f, h, receiver, next) {
+ if(typeof f !== 'function') {
+ return next.become(h);
+ }
+
+ Promise.enterContext(h);
+ tryCatchReject(f, h.value, receiver, next);
+ Promise.exitContext();
+ }
+
+ function runContinuation3(f, x, h, receiver, next) {
+ if(typeof f !== 'function') {
+ return next.become(h);
+ }
+
+ Promise.enterContext(h);
+ tryCatchReject3(f, x, h.value, receiver, next);
+ Promise.exitContext();
+ }
+
+ function runNotify(f, x, h, receiver, next) {
+ if(typeof f !== 'function') {
+ return next.notify(x);
+ }
+
+ Promise.enterContext(h);
+ tryCatchReturn(f, x, receiver, next);
+ Promise.exitContext();
+ }
+
+ /**
+ * Return f.call(thisArg, x), or if it throws return a rejected promise for
+ * the thrown exception
+ */
+ function tryCatchReject(f, x, thisArg, next) {
+ try {
+ next.become(getHandler(f.call(thisArg, x)));
+ } catch(e) {
+ next.become(new Rejected(e));
+ }
+ }
+
+ /**
+ * Same as above, but includes the extra argument parameter.
+ */
+ function tryCatchReject3(f, x, y, thisArg, next) {
+ try {
+ f.call(thisArg, x, y, next);
+ } catch(e) {
+ next.become(new Rejected(e));
+ }
+ }
+
+ /**
+ * Return f.call(thisArg, x), or if it throws, *return* the exception
+ */
+ function tryCatchReturn(f, x, thisArg, next) {
+ try {
+ next.notify(f.call(thisArg, x));
+ } catch(e) {
+ next.notify(e);
+ }
+ }
+
+ function inherit(Parent, Child) {
+ Child.prototype = objectCreate(Parent.prototype);
+ Child.prototype.constructor = Child;
+ }
+
+ function noop() {}
+
+ return Promise;
+ };
+});
+}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
+
+},{}]},{},[9])
+(9)
+}); \ No newline at end of file
diff --git a/web/src/vendor/react-router/dist/react-router.min.js b/web/src/vendor/react-router/dist/react-router.min.js
new file mode 100644
index 00000000..d6e8a003
--- /dev/null
+++ b/web/src/vendor/react-router/dist/react-router.min.js
@@ -0,0 +1,2 @@
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.ReactRouter=e()}}(function(){var define;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)s(r[o]);return s}({1:[function(_dereq_,module){var LocationDispatcher=_dereq_("../dispatchers/LocationDispatcher"),makePath=_dereq_("../utils/makePath"),LocationActions={PUSH:"push",REPLACE:"replace",POP:"pop",UPDATE_SCROLL:"update-scroll",transitionTo:function(to,params,query){LocationDispatcher.handleViewAction({type:LocationActions.PUSH,path:makePath(to,params,query)})},replaceWith:function(to,params,query){LocationDispatcher.handleViewAction({type:LocationActions.REPLACE,path:makePath(to,params,query)})},goBack:function(){LocationDispatcher.handleViewAction({type:LocationActions.POP})},updateScroll:function(){LocationDispatcher.handleViewAction({type:LocationActions.UPDATE_SCROLL})}};module.exports=LocationActions},{"../dispatchers/LocationDispatcher":8,"../utils/makePath":26}],2:[function(_dereq_,module){function DefaultRoute(props){return Route(merge(props,{path:null,isDefault:!0}))}var merge=_dereq_("react/lib/merge"),Route=_dereq_("./Route");module.exports=DefaultRoute},{"./Route":6,"react/lib/merge":44}],3:[function(_dereq_,module){function isLeftClickEvent(event){return 0===event.button}function isModifiedEvent(event){return!!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,ActiveState=_dereq_("../mixins/ActiveState"),transitionTo=_dereq_("../actions/LocationActions").transitionTo,withoutProperties=_dereq_("../utils/withoutProperties"),hasOwnProperty=_dereq_("../utils/hasOwnProperty"),makeHref=_dereq_("../utils/makeHref"),warning=_dereq_("react/lib/warning"),RESERVED_PROPS={to:!0,key:!0,className:!0,activeClassName:!0,query:!0,onClick:!0,children:!0},Link=React.createClass({displayName:"Link",mixins:[ActiveState],statics:{getUnreservedProps:function(props){var props=withoutProperties(props,RESERVED_PROPS);return warning(0===Object.keys(props).length,"Passing props for params on <Link>s is deprecated, please use the `params` property."),props},getParams:function(props){return props.params||Link.getUnreservedProps(props)}},propTypes:{to:React.PropTypes.string.isRequired,activeClassName:React.PropTypes.string.isRequired,params:React.PropTypes.object,query:React.PropTypes.object,onClick:React.PropTypes.func},getDefaultProps:function(){return{activeClassName:"active"}},getInitialState:function(){return{isActive:!1}},getHref:function(){return makeHref(this.props.to,Link.getParams(this.props),this.props.query)},getClassName:function(){var className=this.props.className||"";return this.state.isActive?className+" "+this.props.activeClassName:className},componentWillReceiveProps:function(nextProps){var params=Link.getParams(nextProps);this.setState({isActive:Link.isActive(nextProps.to,params,nextProps.query)})},updateActiveState:function(){this.setState({isActive:Link.isActive(this.props.to,Link.getParams(this.props),this.props.query)})},handleClick:function(event){var ret,allowTransition=!0;this.props.onClick&&(ret=this.props.onClick(event)),!isModifiedEvent(event)&&isLeftClickEvent(event)&&((ret===!1||event.defaultPrevented===!0)&&(allowTransition=!1),event.preventDefault(),allowTransition&&transitionTo(this.props.to,Link.getParams(this.props),this.props.query))},render:function(){var props={href:this.getHref(),className:this.getClassName(),onClick:this.handleClick};for(var propName in this.props)hasOwnProperty(this.props,propName)&&hasOwnProperty(props,propName)===!1&&(props[propName]=this.props[propName]);return React.DOM.a(props,this.props.children)}});module.exports=Link},{"../actions/LocationActions":1,"../mixins/ActiveState":15,"../utils/hasOwnProperty":24,"../utils/makeHref":25,"../utils/withoutProperties":29,"react/lib/warning":48}],4:[function(_dereq_,module){function NotFoundRoute(props){return Route(merge(props,{path:null,catchAll:!0}))}var merge=_dereq_("react/lib/merge"),Route=_dereq_("./Route");module.exports=NotFoundRoute},{"./Route":6,"react/lib/merge":44}],5:[function(_dereq_,module){function createRedirectHandler(to){return React.createClass({statics:{willTransitionTo:function(transition,params,query){transition.redirect(to,params,query)}},render:function(){return null}})}function Redirect(props){return Route({name:props.name,path:props.from||props.path||"*",handler:createRedirectHandler(props.to)})}var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,Route=_dereq_("./Route");module.exports=Redirect},{"./Route":6}],6:[function(_dereq_,module){var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,withoutProperties=_dereq_("../utils/withoutProperties"),RESERVED_PROPS={handler:!0,path:!0,defaultRoute:!0,paramNames:!0,children:!0},Route=React.createClass({displayName:"Route",statics:{getUnreservedProps:function(props){return withoutProperties(props,RESERVED_PROPS)}},propTypes:{preserveScrollPosition:React.PropTypes.bool.isRequired,handler:React.PropTypes.any.isRequired,path:React.PropTypes.string,name:React.PropTypes.string},getDefaultProps:function(){return{preserveScrollPosition:!1}},render:function(){throw new Error("The <Route> component should not be rendered directly. You may be missing a <Routes> wrapper around your list of routes.")}});module.exports=Route},{"../utils/withoutProperties":29}],7:[function(_dereq_,module){function defaultAbortedTransitionHandler(transition){var reason=transition.abortReason;reason instanceof Redirect?LocationActions.replaceWith(reason.to,reason.params,reason.query):LocationActions.goBack()}function defaultActiveStateChangeHandler(state){ActiveStore.updateState(state)}function defaultTransitionErrorHandler(error){throw error}function maybeUpdateScroll(routes,rootRoute){routes.props.preserveScrollPosition||rootRoute.props.preserveScrollPosition||LocationActions.updateScroll()}function findMatches(path,routes,defaultRoute,notFoundRoute){for(var route,params,matches=null,i=0,len=routes.length;len>i;++i){if(route=routes[i],matches=findMatches(path,route.props.children,route.props.defaultRoute,route.props.notFoundRoute),null!=matches){var rootParams=getRootMatch(matches).params;return params=route.props.paramNames.reduce(function(params,paramName){return params[paramName]=rootParams[paramName],params},{}),matches.unshift(makeMatch(route,params)),matches}if(params=Path.extractParams(route.props.path,path))return[makeMatch(route,params)]}return defaultRoute&&(params=Path.extractParams(defaultRoute.props.path,path))?[makeMatch(defaultRoute,params)]:notFoundRoute&&(params=Path.extractParams(notFoundRoute.props.path,path))?[makeMatch(notFoundRoute,params)]:matches}function makeMatch(route,params){return{route:route,params:params}}function hasMatch(matches,match){return matches.some(function(m){if(m.route!==match.route)return!1;for(var property in m.params)if(m.params[property]!==match.params[property])return!1;return!0})}function getRootMatch(matches){return matches[matches.length-1]}function updateMatchComponents(matches,refs){for(var component,i=0;component=refs[REF_NAME];)matches[i++].component=component,refs=component.refs}function runTransitionHooks(routes,transition){if(routes.state.path===transition.path)return Promise.resolve();var currentMatches=routes.state.matches,nextMatches=routes.match(transition.path);warning(nextMatches,'No route matches path "'+transition.path+'". Make sure you have <Route path="'+transition.path+'"> somewhere in your routes'),nextMatches||(nextMatches=[]);var fromMatches,toMatches;currentMatches?(updateMatchComponents(currentMatches,routes.refs),fromMatches=currentMatches.filter(function(match){return!hasMatch(nextMatches,match)}),toMatches=nextMatches.filter(function(match){return!hasMatch(currentMatches,match)})):(fromMatches=[],toMatches=nextMatches);var query=Path.extractQuery(transition.path)||{};return runTransitionFromHooks(fromMatches,transition).then(function(){return transition.isAborted?void 0:runTransitionToHooks(toMatches,transition,query).then(function(){if(!transition.isAborted){var rootMatch=getRootMatch(nextMatches),params=rootMatch&&rootMatch.params||{};return{path:transition.path,matches:nextMatches,activeParams:params,activeQuery:query,activeRoutes:nextMatches.map(function(match){return match.route})}}})})}function runTransitionFromHooks(matches,transition){var promise=Promise.resolve();return reversedArray(matches).forEach(function(match){promise=promise.then(function(){var handler=match.route.props.handler;return!transition.isAborted&&handler.willTransitionFrom?handler.willTransitionFrom(transition,match.component):void 0})}),promise}function runTransitionToHooks(matches,transition,query){var promise=Promise.resolve();return matches.forEach(function(match){promise=promise.then(function(){var handler=match.route.props.handler;return!transition.isAborted&&handler.willTransitionTo?handler.willTransitionTo(transition,match.params,query):void 0})}),promise}function computeHandlerProps(matches,query){var childHandler,props={ref:null,key:null,params:null,query:null,activeRouteHandler:returnNull};return reversedArray(matches).forEach(function(match){var route=match.route;props=Route.getUnreservedProps(route.props),props.ref=REF_NAME,props.params=match.params,props.query=query,route.props.addHandlerKey&&(props.key=Path.injectParams(route.props.path,match.params)),props.activeRouteHandler=childHandler?childHandler:returnNull,childHandler=function(props,addedProps){if(arguments.length>2&&"undefined"!=typeof arguments[2])throw new Error("Passing children to a route handler is not supported");return route.props.handler(copyProperties(props,addedProps))}.bind(this,props)}),props}function returnNull(){return null}function reversedArray(array){return array.slice(0).reverse()}var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,warning=_dereq_("react/lib/warning"),copyProperties=_dereq_("react/lib/copyProperties"),Promise=_dereq_("when/lib/Promise"),LocationActions=_dereq_("../actions/LocationActions"),Route=_dereq_("../components/Route"),Path=_dereq_("../utils/Path"),Redirect=_dereq_("../utils/Redirect"),Transition=_dereq_("../utils/Transition"),DefaultLocation=_dereq_("../locations/DefaultLocation"),HashLocation=_dereq_("../locations/HashLocation"),HistoryLocation=_dereq_("../locations/HistoryLocation"),RefreshLocation=_dereq_("../locations/RefreshLocation"),ActiveStore=_dereq_("../stores/ActiveStore"),PathStore=_dereq_("../stores/PathStore"),RouteStore=_dereq_("../stores/RouteStore"),REF_NAME="__activeRoute__",NAMED_LOCATIONS={hash:HashLocation,history:HistoryLocation,refresh:RefreshLocation},Routes=React.createClass({displayName:"Routes",propTypes:{onAbortedTransition:React.PropTypes.func.isRequired,onActiveStateChange:React.PropTypes.func.isRequired,onTransitionError:React.PropTypes.func.isRequired,preserveScrollPosition:React.PropTypes.bool,location:function(props,propName,componentName){var location=props[propName];return"string"!=typeof location||location in NAMED_LOCATIONS?void 0:new Error('Unknown location "'+location+'", see '+componentName)}},getDefaultProps:function(){return{onAbortedTransition:defaultAbortedTransitionHandler,onActiveStateChange:defaultActiveStateChangeHandler,onTransitionError:defaultTransitionErrorHandler,preserveScrollPosition:!1,location:DefaultLocation}},getInitialState:function(){return{routes:RouteStore.registerChildren(this.props.children,this)}},getLocation:function(){var location=this.props.location;return"string"==typeof location?NAMED_LOCATIONS[location]:location},componentWillMount:function(){PathStore.setup(this.getLocation()),PathStore.addChangeListener(this.handlePathChange)},componentDidMount:function(){this.handlePathChange()},componentWillUnmount:function(){PathStore.removeChangeListener(this.handlePathChange)},handlePathChange:function(){this.dispatch(PathStore.getCurrentPath())},match:function(path){return findMatches(Path.withoutQuery(path),this.state.routes,this.props.defaultRoute,this.props.notFoundRoute)},dispatch:function(path,returnRejectedPromise){var transition=new Transition(path),routes=this,promise=runTransitionHooks(routes,transition).then(function(nextState){if(transition.isAborted)routes.props.onAbortedTransition(transition);else if(nextState){routes.setState(nextState),routes.props.onActiveStateChange(nextState);var rootMatch=getRootMatch(nextState.matches);rootMatch&&maybeUpdateScroll(routes,rootMatch.route)}return transition});return returnRejectedPromise||(promise=promise.then(void 0,function(error){setTimeout(function(){routes.props.onTransitionError(error)})})),promise},render:function(){if(!this.state.path)return null;var matches=this.state.matches;return matches.length?matches[0].route.props.handler(computeHandlerProps(matches,this.state.activeQuery)):null}});module.exports=Routes},{"../actions/LocationActions":1,"../components/Route":6,"../locations/DefaultLocation":10,"../locations/HashLocation":11,"../locations/HistoryLocation":12,"../locations/RefreshLocation":14,"../stores/ActiveStore":17,"../stores/PathStore":18,"../stores/RouteStore":19,"../utils/Path":20,"../utils/Redirect":21,"../utils/Transition":22,"react/lib/copyProperties":40,"react/lib/warning":48,"when/lib/Promise":49}],8:[function(_dereq_,module){var copyProperties=_dereq_("react/lib/copyProperties"),Dispatcher=_dereq_("flux").Dispatcher,LocationDispatcher=copyProperties(new Dispatcher,{handleViewAction:function(action){this.dispatch({source:"VIEW_ACTION",action:action})}});module.exports=LocationDispatcher},{flux:31,"react/lib/copyProperties":40}],9:[function(_dereq_,module,exports){exports.goBack=_dereq_("./actions/LocationActions").goBack,exports.replaceWith=_dereq_("./actions/LocationActions").replaceWith,exports.transitionTo=_dereq_("./actions/LocationActions").transitionTo,exports.DefaultRoute=_dereq_("./components/DefaultRoute"),exports.Link=_dereq_("./components/Link"),exports.NotFoundRoute=_dereq_("./components/NotFoundRoute"),exports.Redirect=_dereq_("./components/Redirect"),exports.Route=_dereq_("./components/Route"),exports.Routes=_dereq_("./components/Routes"),exports.ActiveState=_dereq_("./mixins/ActiveState"),exports.AsyncState=_dereq_("./mixins/AsyncState"),exports.makeHref=_dereq_("./utils/makeHref")},{"./actions/LocationActions":1,"./components/DefaultRoute":2,"./components/Link":3,"./components/NotFoundRoute":4,"./components/Redirect":5,"./components/Route":6,"./components/Routes":7,"./mixins/ActiveState":15,"./mixins/AsyncState":16,"./utils/makeHref":25}],10:[function(_dereq_,module){module.exports=_dereq_("./HashLocation")},{"./HashLocation":11,"./MemoryLocation":13}],11:[function(_dereq_,module){function getHashPath(){return window.location.hash.substr(1)}function ensureSlash(){var path=getHashPath();return"/"===path.charAt(0)?!0:(HashLocation.replace("/"+path),!1)}function handleHashChange(){ensureSlash()&&_onChange()}var _onChange,invariant=_dereq_("react/lib/invariant"),ExecutionEnvironment=_dereq_("react/lib/ExecutionEnvironment"),getWindowPath=_dereq_("../utils/getWindowPath"),HashLocation={setup:function(onChange){invariant(ExecutionEnvironment.canUseDOM,"You cannot use HashLocation in an environment with no DOM"),_onChange=onChange,ensureSlash(),window.addEventListener?window.addEventListener("hashchange",handleHashChange,!1):window.attachEvent("onhashchange",handleHashChange)},teardown:function(){window.removeEventListener?window.removeEventListener("hashchange",handleHashChange,!1):window.detachEvent("onhashchange",handleHashChange)},push:function(path){window.location.hash=path},replace:function(path){window.location.replace(getWindowPath()+"#"+path)},pop:function(){window.history.back()},getCurrentPath:getHashPath,toString:function(){return"<HashLocation>"}};module.exports=HashLocation},{"../utils/getWindowPath":23,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":42}],12:[function(_dereq_,module){var _onChange,invariant=_dereq_("react/lib/invariant"),ExecutionEnvironment=_dereq_("react/lib/ExecutionEnvironment"),getWindowPath=_dereq_("../utils/getWindowPath"),HistoryLocation={setup:function(onChange){invariant(ExecutionEnvironment.canUseDOM,"You cannot use HistoryLocation in an environment with no DOM"),_onChange=onChange,window.addEventListener?window.addEventListener("popstate",_onChange,!1):window.attachEvent("popstate",_onChange)},teardown:function(){window.removeEventListener?window.removeEventListener("popstate",_onChange,!1):window.detachEvent("popstate",_onChange)},push:function(path){window.history.pushState({path:path},"",path),_onChange()},replace:function(path){window.history.replaceState({path:path},"",path),_onChange()},pop:function(){window.history.back()},getCurrentPath:getWindowPath,toString:function(){return"<HistoryLocation>"}};module.exports=HistoryLocation},{"../utils/getWindowPath":23,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":42}],13:[function(_dereq_,module){var _onChange,warning=_dereq_("react/lib/warning"),_lastPath=null,_currentPath=null,MemoryLocation={setup:function(onChange){_onChange=onChange},push:function(path){_lastPath=_currentPath,_currentPath=path,_onChange()},replace:function(path){_currentPath=path,_onChange()},pop:function(){warning(null!=_lastPath,"You cannot use MemoryLocation to go back more than once"),_currentPath=_lastPath,_lastPath=null,_onChange()},getCurrentPath:function(){return _currentPath||"/"},toString:function(){return"<MemoryLocation>"}};module.exports=MemoryLocation},{"react/lib/warning":48}],14:[function(_dereq_,module){var invariant=_dereq_("react/lib/invariant"),ExecutionEnvironment=_dereq_("react/lib/ExecutionEnvironment"),getWindowPath=_dereq_("../utils/getWindowPath"),RefreshLocation={setup:function(){invariant(ExecutionEnvironment.canUseDOM,"You cannot use RefreshLocation in an environment with no DOM")},push:function(path){window.location=path},replace:function(path){window.location.replace(path)},pop:function(){window.history.back()},getCurrentPath:getWindowPath,toString:function(){return"<RefreshLocation>"}};module.exports=RefreshLocation},{"../utils/getWindowPath":23,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":42}],15:[function(_dereq_,module){var ActiveStore=_dereq_("../stores/ActiveStore"),ActiveState={statics:{isActive:ActiveStore.isActive},componentWillMount:function(){ActiveStore.addChangeListener(this.handleActiveStateChange)},componentDidMount:function(){this.updateActiveState&&this.updateActiveState()},componentWillUnmount:function(){ActiveStore.removeChangeListener(this.handleActiveStateChange)},handleActiveStateChange:function(){this.isMounted()&&"function"==typeof this.updateActiveState&&this.updateActiveState()}};module.exports=ActiveState},{"../stores/ActiveStore":17}],16:[function(_dereq_,module){var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,resolveAsyncState=_dereq_("../utils/resolveAsyncState"),AsyncState={propTypes:{initialAsyncState:React.PropTypes.object},getInitialState:function(){return this.props.initialAsyncState||null},updateAsyncState:function(state){this.isMounted()&&this.setState(state)},componentDidMount:function(){this.props.initialAsyncState||"function"!=typeof this.constructor.getInitialAsyncState||resolveAsyncState(this.constructor.getInitialAsyncState(this.props.params,this.props.query,this.updateAsyncState),this.updateAsyncState)}};module.exports=AsyncState},{"../utils/resolveAsyncState":27}],17:[function(_dereq_,module){function notifyChange(){_events.emit(CHANGE_EVENT)}function routeIsActive(routeName){return _activeRoutes.some(function(route){return route.props.name===routeName})}function paramsAreActive(params){for(var property in params)if(_activeParams[property]!==String(params[property]))return!1;return!0}function queryIsActive(query){for(var property in query)if(_activeQuery[property]!==String(query[property]))return!1;return!0}var EventEmitter=_dereq_("events").EventEmitter,CHANGE_EVENT="change",_events=new EventEmitter;_events.setMaxListeners(0);var _activeRoutes=[],_activeParams={},_activeQuery={},ActiveStore={addChangeListener:function(listener){_events.on(CHANGE_EVENT,listener)},removeChangeListener:function(listener){_events.removeListener(CHANGE_EVENT,listener)},updateState:function(state){state=state||{},_activeRoutes=state.activeRoutes||[],_activeParams=state.activeParams||{},_activeQuery=state.activeQuery||{},notifyChange()},isActive:function(routeName,params,query){var isActive=routeIsActive(routeName)&&paramsAreActive(params);return query?isActive&&queryIsActive(query):isActive}};module.exports=ActiveStore},{events:30}],18:[function(_dereq_,module){function notifyChange(){_events.emit(CHANGE_EVENT)}function recordScrollPosition(path){_scrollPositions[path]={x:window.scrollX,y:window.scrollY}}function updateScrollPosition(path){var p=PathStore.getScrollPosition(path);window.scrollTo(p.x,p.y)}var _location,warning=_dereq_("react/lib/warning"),EventEmitter=_dereq_("events").EventEmitter,LocationActions=_dereq_("../actions/LocationActions"),LocationDispatcher=_dereq_("../dispatchers/LocationDispatcher"),supportsHistory=_dereq_("../utils/supportsHistory"),HistoryLocation=_dereq_("../locations/HistoryLocation"),RefreshLocation=_dereq_("../locations/RefreshLocation"),CHANGE_EVENT="change",_events=new EventEmitter,_scrollPositions={},PathStore={addChangeListener:function(listener){_events.on(CHANGE_EVENT,listener)},removeChangeListener:function(listener){_events.removeListener(CHANGE_EVENT,listener),0===EventEmitter.listenerCount(_events,CHANGE_EVENT)&&PathStore.teardown()},setup:function(location){location!==HistoryLocation||supportsHistory()||(location=RefreshLocation),null==_location?(_location=location,_location&&"function"==typeof _location.setup&&_location.setup(notifyChange)):warning(_location===location,"Cannot use location %s, already using %s",location,_location)},teardown:function(){_events.removeAllListeners(CHANGE_EVENT),_location&&"function"==typeof _location.teardown&&_location.teardown(),_location=null},getLocation:function(){return _location},getCurrentPath:function(){return _location.getCurrentPath()},getScrollPosition:function(path){return _scrollPositions[path]||{x:0,y:0}},dispatchToken:LocationDispatcher.register(function(payload){var action=payload.action,currentPath=_location.getCurrentPath();switch(action.type){case LocationActions.PUSH:currentPath!==action.path&&(recordScrollPosition(currentPath),_location.push(action.path));break;case LocationActions.REPLACE:currentPath!==action.path&&(recordScrollPosition(currentPath),_location.replace(action.path));break;case LocationActions.POP:recordScrollPosition(currentPath),_location.pop();break;case LocationActions.UPDATE_SCROLL:updateScrollPosition(currentPath)}})};module.exports=PathStore},{"../actions/LocationActions":1,"../dispatchers/LocationDispatcher":8,"../locations/HistoryLocation":12,"../locations/RefreshLocation":14,"../utils/supportsHistory":28,events:30,"react/lib/warning":48}],19:[function(_dereq_,module){var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,invariant=_dereq_("react/lib/invariant"),Path=(_dereq_("react/lib/warning"),_dereq_("../utils/Path")),_namedRoutes={},RouteStore={unregisterAllRoutes:function(){_namedRoutes={}},unregisterRoute:function(route){var props=route.props;props.name&&delete _namedRoutes[props.name],React.Children.forEach(props.children,RouteStore.unregisterRoute)},registerRoute:function(route,parentRoute){var props=route.props;invariant(React.isValidClass(props.handler),'The handler for the "%s" route must be a valid React class',props.name||props.path);var parentPath=parentRoute&&parentRoute.props.path||"/";if(!props.path&&!props.name||props.isDefault||props.catchAll)props.path=parentPath,props.catchAll&&(props.path+="*");else{var path=props.path||props.name;Path.isAbsolute(path)||(path=Path.join(parentPath,path)),props.path=Path.normalize(path)}if(props.paramNames=Path.extractParamNames(props.path),parentRoute&&Array.isArray(parentRoute.props.paramNames)&&parentRoute.props.paramNames.forEach(function(paramName){invariant(-1!==props.paramNames.indexOf(paramName),'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"',props.path,paramName,parentRoute.props.path)}),props.name){var existingRoute=_namedRoutes[props.name];invariant(!existingRoute||route===existingRoute,'You cannot use the name "%s" for more than one route',props.name),_namedRoutes[props.name]=route}return props.catchAll?(invariant(parentRoute,"<NotFoundRoute> must have a parent <Route>"),invariant(null==parentRoute.props.notFoundRoute,"You may not have more than one <NotFoundRoute> per <Route>"),parentRoute.props.notFoundRoute=route,null):props.isDefault?(invariant(parentRoute,"<DefaultRoute> must have a parent <Route>"),invariant(null==parentRoute.props.defaultRoute,"You may not have more than one <DefaultRoute> per <Route>"),parentRoute.props.defaultRoute=route,null):(props.children=RouteStore.registerChildren(props.children,route),route)},registerChildren:function(children,parentRoute){var routes=[];return React.Children.forEach(children,function(child){(child=RouteStore.registerRoute(child,parentRoute))&&routes.push(child)}),routes},getRouteByName:function(routeName){return _namedRoutes[routeName]||null}};module.exports=RouteStore},{"../utils/Path":20,"react/lib/invariant":42,"react/lib/warning":48}],20:[function(_dereq_,module){function encodeURL(url){return encodeURIComponent(url).replace(/%20/g,"+")}function decodeURL(url){return decodeURIComponent(url.replace(/\+/g," "))}function encodeURLPath(path){return String(path).split("/").map(encodeURL).join("/")}function compilePattern(pattern){if(!(pattern in _compiledPatterns)){var paramNames=[],source=pattern.replace(paramMatcher,function(match,paramName){return paramName?(paramNames.push(paramName),"([^./?#]+)"):"*"===match?(paramNames.push("splat"),"(.*?)"):"\\"+match});_compiledPatterns[pattern]={matcher:new RegExp("^"+source+"$","i"),paramNames:paramNames}}return _compiledPatterns[pattern]}var invariant=_dereq_("react/lib/invariant"),merge=_dereq_("qs/lib/utils").merge,qs=_dereq_("qs"),paramMatcher=/:([a-zA-Z_$][a-zA-Z0-9_$]*)|[*.()\[\]\\+|{}^$]/g,queryMatcher=/\?(.+)/,_compiledPatterns={},Path={extractParamNames:function(pattern){return compilePattern(pattern).paramNames},extractParams:function(pattern,path){var object=compilePattern(pattern),match=decodeURL(path).match(object.matcher);if(!match)return null;var params={};return object.paramNames.forEach(function(paramName,index){params[paramName]=match[index+1]}),params},injectParams:function(pattern,params){params=params||{};var splatIndex=0;return pattern.replace(paramMatcher,function(match,paramName){paramName=paramName||"splat",invariant(null!=params[paramName],'Missing "'+paramName+'" parameter for path "'+pattern+'"');var segment;return"splat"===paramName&&Array.isArray(params[paramName])?(segment=params[paramName][splatIndex++],invariant(null!=segment,"Missing splat # "+splatIndex+' for path "'+pattern+'"')):segment=params[paramName],encodeURLPath(segment)})},extractQuery:function(path){var match=decodeURL(path).match(queryMatcher);return match&&qs.parse(match[1])},withoutQuery:function(path){return path.replace(queryMatcher,"")},withQuery:function(path,query){var existingQuery=Path.extractQuery(path);existingQuery&&(query=query?merge(existingQuery,query):existingQuery);var queryString=query&&qs.stringify(query);return queryString?Path.withoutQuery(path)+"?"+queryString:path},isAbsolute:function(path){return"/"===path.charAt(0)},normalize:function(path){return path.replace(/^\/*/,"/")},join:function(a,b){return a.replace(/\/*$/,"/")+b}};module.exports=Path},{qs:34,"qs/lib/utils":38,"react/lib/invariant":42}],21:[function(_dereq_,module){function Redirect(to,params,query){this.to=to,this.params=params,this.query=query}module.exports=Redirect},{}],22:[function(_dereq_,module){function Transition(path){this.path=path,this.abortReason=null,this.isAborted=!1}var mixInto=_dereq_("react/lib/mixInto"),transitionTo=_dereq_("../actions/LocationActions").transitionTo,Redirect=_dereq_("./Redirect");mixInto(Transition,{abort:function(reason){this.abortReason=reason,this.isAborted=!0},redirect:function(to,params,query){this.abort(new Redirect(to,params,query))},retry:function(){transitionTo(this.path)}}),module.exports=Transition},{"../actions/LocationActions":1,"./Redirect":21,"react/lib/mixInto":47}],23:[function(_dereq_,module){function getWindowPath(){return window.location.pathname+window.location.search}module.exports=getWindowPath},{}],24:[function(_dereq_,module){module.exports=Function.prototype.call.bind(Object.prototype.hasOwnProperty)},{}],25:[function(_dereq_,module){function makeHref(to,params,query){var path=makePath(to,params,query);return PathStore.getLocation()===HashLocation?"#"+path:path}var HashLocation=_dereq_("../locations/HashLocation"),PathStore=_dereq_("../stores/PathStore"),makePath=_dereq_("./makePath");module.exports=makeHref},{"../locations/HashLocation":11,"../stores/PathStore":18,"./makePath":26}],26:[function(_dereq_,module){function makePath(to,params,query){var path;if(Path.isAbsolute(to))path=Path.normalize(to);else{var route=RouteStore.getRouteByName(to);invariant(route,'Unable to find a route named "'+to+'". Make sure you have a <Route name="'+to+'"> defined somewhere in your routes'),path=route.props.path}return Path.withQuery(Path.injectParams(path,params),query)}var invariant=_dereq_("react/lib/invariant"),RouteStore=_dereq_("../stores/RouteStore"),Path=_dereq_("./Path");module.exports=makePath},{"../stores/RouteStore":19,"./Path":20,"react/lib/invariant":42}],27:[function(_dereq_,module){function resolveAsyncState(asyncState,setState){if(null==asyncState)return Promise.resolve();var keys=Object.keys(asyncState);return Promise.all(keys.map(function(key){return Promise.resolve(asyncState[key]).then(function(value){var newState={};newState[key]=value,setState(newState)})}))}var Promise=_dereq_("when/lib/Promise");module.exports=resolveAsyncState},{"when/lib/Promise":49}],28:[function(_dereq_,module){function supportsHistory(){var ua=navigator.userAgent;return-1===ua.indexOf("Android 2.")&&-1===ua.indexOf("Android 4.0")||-1===ua.indexOf("Mobile Safari")||-1!==ua.indexOf("Chrome")?window.history&&"pushState"in window.history:!1}module.exports=supportsHistory},{}],29:[function(_dereq_,module){function withoutProperties(object,properties){var result={};for(var property in object)object.hasOwnProperty(property)&&!properties[property]&&(result[property]=object[property]);return result}module.exports=withoutProperties},{}],30:[function(_dereq_,module){function EventEmitter(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function isFunction(arg){return"function"==typeof arg}function isNumber(arg){return"number"==typeof arg}function isObject(arg){return"object"==typeof arg&&null!==arg}function isUndefined(arg){return void 0===arg}module.exports=EventEmitter,EventEmitter.EventEmitter=EventEmitter,EventEmitter.prototype._events=void 0,EventEmitter.prototype._maxListeners=void 0,EventEmitter.defaultMaxListeners=10,EventEmitter.prototype.setMaxListeners=function(n){if(!isNumber(n)||0>n||isNaN(n))throw TypeError("n must be a positive number");
+return this._maxListeners=n,this},EventEmitter.prototype.emit=function(type){var er,handler,len,args,i,listeners;if(this._events||(this._events={}),"error"===type&&(!this._events.error||isObject(this._events.error)&&!this._events.error.length))throw er=arguments[1],er instanceof Error?er:TypeError('Uncaught, unspecified "error" event.');if(handler=this._events[type],isUndefined(handler))return!1;if(isFunction(handler))switch(arguments.length){case 1:handler.call(this);break;case 2:handler.call(this,arguments[1]);break;case 3:handler.call(this,arguments[1],arguments[2]);break;default:for(len=arguments.length,args=new Array(len-1),i=1;len>i;i++)args[i-1]=arguments[i];handler.apply(this,args)}else if(isObject(handler)){for(len=arguments.length,args=new Array(len-1),i=1;len>i;i++)args[i-1]=arguments[i];for(listeners=handler.slice(),len=listeners.length,i=0;len>i;i++)listeners[i].apply(this,args)}return!0},EventEmitter.prototype.addListener=function(type,listener){var m;if(!isFunction(listener))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",type,isFunction(listener.listener)?listener.listener:listener),this._events[type]?isObject(this._events[type])?this._events[type].push(listener):this._events[type]=[this._events[type],listener]:this._events[type]=listener,isObject(this._events[type])&&!this._events[type].warned){var m;m=isUndefined(this._maxListeners)?EventEmitter.defaultMaxListeners:this._maxListeners,m&&m>0&&this._events[type].length>m&&(this._events[type].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[type].length),"function"==typeof console.trace&&console.trace())}return this},EventEmitter.prototype.on=EventEmitter.prototype.addListener,EventEmitter.prototype.once=function(type,listener){function g(){this.removeListener(type,g),fired||(fired=!0,listener.apply(this,arguments))}if(!isFunction(listener))throw TypeError("listener must be a function");var fired=!1;return g.listener=listener,this.on(type,g),this},EventEmitter.prototype.removeListener=function(type,listener){var list,position,length,i;if(!isFunction(listener))throw TypeError("listener must be a function");if(!this._events||!this._events[type])return this;if(list=this._events[type],length=list.length,position=-1,list===listener||isFunction(list.listener)&&list.listener===listener)delete this._events[type],this._events.removeListener&&this.emit("removeListener",type,listener);else if(isObject(list)){for(i=length;i-->0;)if(list[i]===listener||list[i].listener&&list[i].listener===listener){position=i;break}if(0>position)return this;1===list.length?(list.length=0,delete this._events[type]):list.splice(position,1),this._events.removeListener&&this.emit("removeListener",type,listener)}return this},EventEmitter.prototype.removeAllListeners=function(type){var key,listeners;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[type]&&delete this._events[type],this;if(0===arguments.length){for(key in this._events)"removeListener"!==key&&this.removeAllListeners(key);return this.removeAllListeners("removeListener"),this._events={},this}if(listeners=this._events[type],isFunction(listeners))this.removeListener(type,listeners);else for(;listeners.length;)this.removeListener(type,listeners[listeners.length-1]);return delete this._events[type],this},EventEmitter.prototype.listeners=function(type){var ret;return ret=this._events&&this._events[type]?isFunction(this._events[type])?[this._events[type]]:this._events[type].slice():[]},EventEmitter.listenerCount=function(emitter,type){var ret;return ret=emitter._events&&emitter._events[type]?isFunction(emitter._events[type])?1:emitter._events[type].length:0}},{}],31:[function(_dereq_,module){module.exports.Dispatcher=_dereq_("./lib/Dispatcher")},{"./lib/Dispatcher":32}],32:[function(_dereq_,module){function Dispatcher(){"use strict";this.$Dispatcher_callbacks={},this.$Dispatcher_isPending={},this.$Dispatcher_isHandled={},this.$Dispatcher_isDispatching=!1,this.$Dispatcher_pendingPayload=null}var invariant=_dereq_("./invariant"),_lastID=1,_prefix="ID_";Dispatcher.prototype.register=function(callback){"use strict";var id=_prefix+_lastID++;return this.$Dispatcher_callbacks[id]=callback,id},Dispatcher.prototype.unregister=function(id){"use strict";invariant(this.$Dispatcher_callbacks[id],"Dispatcher.unregister(...): `%s` does not map to a registered callback.",id),delete this.$Dispatcher_callbacks[id]},Dispatcher.prototype.waitFor=function(ids){"use strict";invariant(this.$Dispatcher_isDispatching,"Dispatcher.waitFor(...): Must be invoked while dispatching.");for(var ii=0;ii<ids.length;ii++){var id=ids[ii];this.$Dispatcher_isPending[id]?invariant(this.$Dispatcher_isHandled[id],"Dispatcher.waitFor(...): Circular dependency detected while waiting for `%s`.",id):(invariant(this.$Dispatcher_callbacks[id],"Dispatcher.waitFor(...): `%s` does not map to a registered callback.",id),this.$Dispatcher_invokeCallback(id))}},Dispatcher.prototype.dispatch=function(payload){"use strict";invariant(!this.$Dispatcher_isDispatching,"Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch."),this.$Dispatcher_startDispatching(payload);try{for(var id in this.$Dispatcher_callbacks)this.$Dispatcher_isPending[id]||this.$Dispatcher_invokeCallback(id)}finally{this.$Dispatcher_stopDispatching()}},Dispatcher.prototype.isDispatching=function(){"use strict";return this.$Dispatcher_isDispatching},Dispatcher.prototype.$Dispatcher_invokeCallback=function(id){"use strict";this.$Dispatcher_isPending[id]=!0,this.$Dispatcher_callbacks[id](this.$Dispatcher_pendingPayload),this.$Dispatcher_isHandled[id]=!0},Dispatcher.prototype.$Dispatcher_startDispatching=function(payload){"use strict";for(var id in this.$Dispatcher_callbacks)this.$Dispatcher_isPending[id]=!1,this.$Dispatcher_isHandled[id]=!1;this.$Dispatcher_pendingPayload=payload,this.$Dispatcher_isDispatching=!0},Dispatcher.prototype.$Dispatcher_stopDispatching=function(){"use strict";this.$Dispatcher_pendingPayload=null,this.$Dispatcher_isDispatching=!1},module.exports=Dispatcher},{"./invariant":33}],33:[function(_dereq_,module){"use strict";var invariant=function(condition,format,a,b,c,d,e,f){if(!condition){var error;if(void 0===format)error=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var args=[a,b,c,d,e,f],argIndex=0;error=new Error("Invariant Violation: "+format.replace(/%s/g,function(){return args[argIndex++]}))}throw error.framesToPop=1,error}};module.exports=invariant},{}],34:[function(_dereq_,module){module.exports=_dereq_("./lib")},{"./lib":35}],35:[function(_dereq_,module){var Stringify=_dereq_("./stringify"),Parse=_dereq_("./parse");module.exports={stringify:Stringify,parse:Parse}},{"./parse":36,"./stringify":37}],36:[function(_dereq_,module){var Utils=_dereq_("./utils"),internals={delimiter:"&",depth:5,arrayLimit:20,parameterLimit:1e3};internals.parseValues=function(str,options){for(var obj={},parts=str.split(options.delimiter,1/0===options.parameterLimit?void 0:options.parameterLimit),i=0,il=parts.length;il>i;++i){var part=parts[i],pos=-1===part.indexOf("]=")?part.indexOf("="):part.indexOf("]=")+1;if(-1===pos)obj[Utils.decode(part)]="";else{var key=Utils.decode(part.slice(0,pos)),val=Utils.decode(part.slice(pos+1));obj[key]=obj[key]?[].concat(obj[key]).concat(val):val}}return obj},internals.parseObject=function(chain,val,options){if(!chain.length)return val;var root=chain.shift(),obj={};if("[]"===root)obj=[],obj=obj.concat(internals.parseObject(chain,val,options));else{var cleanRoot="["===root[0]&&"]"===root[root.length-1]?root.slice(1,root.length-1):root,index=parseInt(cleanRoot,10);!isNaN(index)&&root!==cleanRoot&&index<=options.arrayLimit?(obj=[],obj[index]=internals.parseObject(chain,val,options)):obj[cleanRoot]=internals.parseObject(chain,val,options)}return obj},internals.parseKeys=function(key,val,options){if(key){var parent=/^([^\[\]]*)/,child=/(\[[^\[\]]*\])/g,segment=parent.exec(key);if(!Object.prototype.hasOwnProperty(segment[1])){var keys=[];segment[1]&&keys.push(segment[1]);for(var i=0;null!==(segment=child.exec(key))&&i<options.depth;)++i,Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g,""))||keys.push(segment[1]);return segment&&keys.push("["+key.slice(segment.index)+"]"),internals.parseObject(keys,val,options)}}},module.exports=function(str,options){if(""===str||null===str||"undefined"==typeof str)return{};options=options||{},options.delimiter="string"==typeof options.delimiter||Utils.isRegExp(options.delimiter)?options.delimiter:internals.delimiter,options.depth="number"==typeof options.depth?options.depth:internals.depth,options.arrayLimit="number"==typeof options.arrayLimit?options.arrayLimit:internals.arrayLimit,options.parameterLimit="number"==typeof options.parameterLimit?options.parameterLimit:internals.parameterLimit;for(var tempObj="string"==typeof str?internals.parseValues(str,options):str,obj={},keys=Object.keys(tempObj),i=0,il=keys.length;il>i;++i){var key=keys[i],newObj=internals.parseKeys(key,tempObj[key],options);obj=Utils.merge(obj,newObj)}return Utils.compact(obj)}},{"./utils":38}],37:[function(_dereq_,module){var Utils=_dereq_("./utils"),internals={delimiter:"&"};internals.stringify=function(obj,prefix){if(Utils.isBuffer(obj)?obj=obj.toString():obj instanceof Date?obj=obj.toISOString():null===obj&&(obj=""),"string"==typeof obj||"number"==typeof obj||"boolean"==typeof obj)return[encodeURIComponent(prefix)+"="+encodeURIComponent(obj)];var values=[];for(var key in obj)obj.hasOwnProperty(key)&&(values=values.concat(internals.stringify(obj[key],prefix+"["+key+"]")));return values},module.exports=function(obj,options){options=options||{};var delimiter="undefined"==typeof options.delimiter?internals.delimiter:options.delimiter,keys=[];for(var key in obj)obj.hasOwnProperty(key)&&(keys=keys.concat(internals.stringify(obj[key],key)));return keys.join(delimiter)}},{"./utils":38}],38:[function(_dereq_,module,exports){exports.arrayToObject=function(source){for(var obj={},i=0,il=source.length;il>i;++i)"undefined"!=typeof source[i]&&(obj[i]=source[i]);return obj},exports.merge=function(target,source){if(!source)return target;if(Array.isArray(source)){for(var i=0,il=source.length;il>i;++i)"undefined"!=typeof source[i]&&(target[i]="object"==typeof target[i]?exports.merge(target[i],source[i]):source[i]);return target}if(Array.isArray(target)){if("object"!=typeof source)return target.push(source),target;target=exports.arrayToObject(target)}for(var keys=Object.keys(source),k=0,kl=keys.length;kl>k;++k){var key=keys[k],value=source[key];target[key]=value&&"object"==typeof value&&target[key]?exports.merge(target[key],value):value}return target},exports.decode=function(str){try{return decodeURIComponent(str.replace(/\+/g," "))}catch(e){return str}},exports.compact=function(obj,refs){if("object"!=typeof obj||null===obj)return obj;refs=refs||[];var lookup=refs.indexOf(obj);if(-1!==lookup)return refs[lookup];if(refs.push(obj),Array.isArray(obj)){for(var compacted=[],i=0,l=obj.length;l>i;++i)"undefined"!=typeof obj[i]&&compacted.push(obj[i]);return compacted}for(var keys=Object.keys(obj),i=0,il=keys.length;il>i;++i){var key=keys[i];obj[key]=exports.compact(obj[key],refs)}return obj},exports.isRegExp=function(obj){return"[object RegExp]"===Object.prototype.toString.call(obj)},exports.isBuffer=function(obj){return"undefined"!=typeof Buffer?Buffer.isBuffer(obj):!1}},{}],39:[function(_dereq_,module){"use strict";var canUseDOM=!("undefined"==typeof window||!window.document||!window.document.createElement),ExecutionEnvironment={canUseDOM:canUseDOM,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:canUseDOM&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:canUseDOM&&!!window.screen,isInWorker:!canUseDOM};module.exports=ExecutionEnvironment},{}],40:[function(_dereq_,module){function copyProperties(obj,a,b,c,d,e,f){obj=obj||{};for(var v,args=[a,b,c,d,e],ii=0;args[ii];){v=args[ii++];for(var k in v)obj[k]=v[k];v.hasOwnProperty&&v.hasOwnProperty("toString")&&"undefined"!=typeof v.toString&&obj.toString!==v.toString&&(obj.toString=v.toString)}return obj}module.exports=copyProperties},{}],41:[function(_dereq_,module){function makeEmptyFunction(arg){return function(){return arg}}function emptyFunction(){}var copyProperties=_dereq_("./copyProperties");copyProperties(emptyFunction,{thatReturns:makeEmptyFunction,thatReturnsFalse:makeEmptyFunction(!1),thatReturnsTrue:makeEmptyFunction(!0),thatReturnsNull:makeEmptyFunction(null),thatReturnsThis:function(){return this},thatReturnsArgument:function(arg){return arg}}),module.exports=emptyFunction},{"./copyProperties":40}],42:[function(_dereq_,module){"use strict";var invariant=function(condition,format,a,b,c,d,e,f){if(!condition){var error;if(void 0===format)error=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var args=[a,b,c,d,e,f],argIndex=0;error=new Error("Invariant Violation: "+format.replace(/%s/g,function(){return args[argIndex++]}))}throw error.framesToPop=1,error}};module.exports=invariant},{}],43:[function(_dereq_,module){"use strict";var invariant=_dereq_("./invariant"),keyMirror=function(obj){var key,ret={};invariant(obj instanceof Object&&!Array.isArray(obj));for(key in obj)obj.hasOwnProperty(key)&&(ret[key]=key);return ret};module.exports=keyMirror},{"./invariant":42}],44:[function(_dereq_,module){"use strict";var mergeInto=_dereq_("./mergeInto"),merge=function(one,two){var result={};return mergeInto(result,one),mergeInto(result,two),result};module.exports=merge},{"./mergeInto":46}],45:[function(_dereq_,module){"use strict";var invariant=_dereq_("./invariant"),keyMirror=_dereq_("./keyMirror"),MAX_MERGE_DEPTH=36,isTerminal=function(o){return"object"!=typeof o||null===o},mergeHelpers={MAX_MERGE_DEPTH:MAX_MERGE_DEPTH,isTerminal:isTerminal,normalizeMergeArg:function(arg){return void 0===arg||null===arg?{}:arg},checkMergeArrayArgs:function(one,two){invariant(Array.isArray(one)&&Array.isArray(two))},checkMergeObjectArgs:function(one,two){mergeHelpers.checkMergeObjectArg(one),mergeHelpers.checkMergeObjectArg(two)},checkMergeObjectArg:function(arg){invariant(!isTerminal(arg)&&!Array.isArray(arg))},checkMergeIntoObjectArg:function(arg){invariant(!(isTerminal(arg)&&"function"!=typeof arg||Array.isArray(arg)))},checkMergeLevel:function(level){invariant(MAX_MERGE_DEPTH>level)},checkArrayStrategy:function(strategy){invariant(void 0===strategy||strategy in mergeHelpers.ArrayStrategies)},ArrayStrategies:keyMirror({Clobber:!0,IndexByIndex:!0})};module.exports=mergeHelpers},{"./invariant":42,"./keyMirror":43}],46:[function(_dereq_,module){"use strict";function mergeInto(one,two){if(checkMergeIntoObjectArg(one),null!=two){checkMergeObjectArg(two);for(var key in two)two.hasOwnProperty(key)&&(one[key]=two[key])}}var mergeHelpers=_dereq_("./mergeHelpers"),checkMergeObjectArg=mergeHelpers.checkMergeObjectArg,checkMergeIntoObjectArg=mergeHelpers.checkMergeIntoObjectArg;module.exports=mergeInto},{"./mergeHelpers":45}],47:[function(_dereq_,module){"use strict";var mixInto=function(constructor,methodBag){var methodName;for(methodName in methodBag)methodBag.hasOwnProperty(methodName)&&(constructor.prototype[methodName]=methodBag[methodName])};module.exports=mixInto},{}],48:[function(_dereq_,module){"use strict";var emptyFunction=_dereq_("./emptyFunction"),warning=emptyFunction;module.exports=warning},{"./emptyFunction":41}],49:[function(_dereq_,module){!function(define){"use strict";define(function(_dereq_){var makePromise=_dereq_("./makePromise"),Scheduler=_dereq_("./Scheduler"),async=_dereq_("./async");return makePromise({scheduler:new Scheduler(async)})})}("function"==typeof define&&define.amd?define:function(factory){module.exports=factory(_dereq_)})},{"./Scheduler":51,"./async":52,"./makePromise":53}],50:[function(_dereq_,module){!function(define){"use strict";define(function(){function Queue(capacityPow2){this.head=this.tail=this.length=0,this.buffer=new Array(1<<capacityPow2)}return Queue.prototype.push=function(x){return this.length===this.buffer.length&&this._ensureCapacity(2*this.length),this.buffer[this.tail]=x,this.tail=this.tail+1&this.buffer.length-1,++this.length,this.length},Queue.prototype.shift=function(){var x=this.buffer[this.head];return this.buffer[this.head]=void 0,this.head=this.head+1&this.buffer.length-1,--this.length,x},Queue.prototype._ensureCapacity=function(capacity){var len,head=this.head,buffer=this.buffer,newBuffer=new Array(capacity),i=0;if(0===head)for(len=this.length;len>i;++i)newBuffer[i]=buffer[i];else{for(capacity=buffer.length,len=this.tail;capacity>head;++i,++head)newBuffer[i]=buffer[head];for(head=0;len>head;++i,++head)newBuffer[i]=buffer[head]}this.buffer=newBuffer,this.head=0,this.tail=this.length},Queue})}("function"==typeof define&&define.amd?define:function(factory){module.exports=factory()})},{}],51:[function(_dereq_,module){!function(define){"use strict";define(function(_dereq_){function Scheduler(async){this._async=async,this._queue=new Queue(15),this._afterQueue=new Queue(5),this._running=!1;var self=this;this.drain=function(){self._drain()}}function runQueue(queue){for(;queue.length>0;)queue.shift().run()}var Queue=_dereq_("./Queue");return Scheduler.prototype.enqueue=function(task){this._add(this._queue,task)},Scheduler.prototype.afterQueue=function(task){this._add(this._afterQueue,task)},Scheduler.prototype._drain=function(){runQueue(this._queue),this._running=!1,runQueue(this._afterQueue)},Scheduler.prototype._add=function(queue,task){queue.push(task),this._running||(this._running=!0,this._async(this.drain))},Scheduler})}("function"==typeof define&&define.amd?define:function(factory){module.exports=factory(_dereq_)})},{"./Queue":50}],52:[function(_dereq_,module){!function(define){"use strict";define(function(_dereq_){var nextTick,MutationObs;return nextTick="undefined"!=typeof process&&null!==process&&"function"==typeof process.nextTick?function(f){process.nextTick(f)}:(MutationObs="function"==typeof MutationObserver&&MutationObserver||"function"==typeof WebKitMutationObserver&&WebKitMutationObserver)?function(document,MutationObserver){function run(){var f=scheduled;scheduled=void 0,f()}var scheduled,el=document.createElement("div"),o=new MutationObserver(run);return o.observe(el,{attributes:!0}),function(f){scheduled=f,el.setAttribute("class","x")}}(document,MutationObs):function(cjsRequire){try{return cjsRequire("vertx").runOnLoop||cjsRequire("vertx").runOnContext}catch(ignore){}var capturedSetTimeout=setTimeout;return function(t){capturedSetTimeout(t,0)}}(_dereq_)})}("function"==typeof define&&define.amd?define:function(factory){module.exports=factory(_dereq_)})},{}],53:[function(_dereq_,module){!function(define){"use strict";define(function(){return function(environment){function Promise(resolver,handler){this._handler=resolver===Handler?handler:init(resolver)}function init(resolver){function promiseResolve(x){handler.resolve(x)}function promiseReject(reason){handler.reject(reason)}function promiseNotify(x){handler.notify(x)}var handler=new Pending;try{resolver(promiseResolve,promiseReject,promiseNotify)}catch(e){promiseReject(e)}return handler}function resolve(x){return isPromise(x)?x:new Promise(Handler,new Async(getHandler(x)))}function reject(x){return new Promise(Handler,new Async(new Rejected(x)))}function never(){return foreverPendingPromise}function defer(){return new Promise(Handler,new Pending)}function all(promises){function settleAt(i,x,resolver){this[i]=x,0===--pending&&resolver.become(new Fulfilled(this))}var i,h,x,s,resolver=new Pending,pending=promises.length>>>0,results=new Array(pending);for(i=0;i<promises.length;++i)if(x=promises[i],void 0!==x||i in promises)if(maybeThenable(x))if(h=isPromise(x)?x._handler.join():getHandlerUntrusted(x),s=h.state(),0===s)h.fold(settleAt,i,results,resolver);else{if(!(s>0)){resolver.become(h);break}results[i]=h.value,--pending}else results[i]=x,--pending;else--pending;return 0===pending&&resolver.become(new Fulfilled(results)),new Promise(Handler,resolver)}function race(promises){if(Object(promises)===promises&&0===promises.length)return never();var i,x,h=new Pending;for(i=0;i<promises.length;++i)x=promises[i],void 0!==x&&i in promises&&getHandler(x).visit(h,h.resolve,h.reject);return new Promise(Handler,h)}function getHandler(x){return isPromise(x)?x._handler.join():maybeThenable(x)?getHandlerUntrusted(x):new Fulfilled(x)}function getHandlerUntrusted(x){try{var untrustedThen=x.then;return"function"==typeof untrustedThen?new Thenable(untrustedThen,x):new Fulfilled(x)}catch(e){return new Rejected(e)}}function Handler(){}function FailIfRejected(){}function Pending(receiver,inheritedContext){Promise.createContext(this,inheritedContext),this.consumers=void 0,this.receiver=receiver,this.handler=void 0,this.resolved=!1}function Async(handler){this.handler=handler}function Thenable(then,thenable){Pending.call(this),tasks.enqueue(new AssimilateTask(then,thenable,this))}function Fulfilled(x){Promise.createContext(this),this.value=x}function Rejected(x){Promise.createContext(this),this.id=++errorId,this.value=x,this.handled=!1,this.reported=!1,this._report()}function ReportTask(rejection,context){this.rejection=rejection,this.context=context}function UnreportTask(rejection){this.rejection=rejection}function cycle(){return new Rejected(new TypeError("Promise cycle"))}function ContinuationTask(continuation,handler){this.continuation=continuation,this.handler=handler}function ProgressTask(value,handler){this.handler=handler,this.value=value}function AssimilateTask(then,thenable,resolver){this._then=then,this.thenable=thenable,this.resolver=resolver}function tryAssimilate(then,thenable,resolve,reject,notify){try{then.call(thenable,resolve,reject,notify)}catch(e){reject(e)}}function isPromise(x){return x instanceof Promise}function maybeThenable(x){return("object"==typeof x||"function"==typeof x)&&null!==x}function runContinuation1(f,h,receiver,next){return"function"!=typeof f?next.become(h):(Promise.enterContext(h),tryCatchReject(f,h.value,receiver,next),void Promise.exitContext())}function runContinuation3(f,x,h,receiver,next){return"function"!=typeof f?next.become(h):(Promise.enterContext(h),tryCatchReject3(f,x,h.value,receiver,next),void Promise.exitContext())}function runNotify(f,x,h,receiver,next){return"function"!=typeof f?next.notify(x):(Promise.enterContext(h),tryCatchReturn(f,x,receiver,next),void Promise.exitContext())}function tryCatchReject(f,x,thisArg,next){try{next.become(getHandler(f.call(thisArg,x)))}catch(e){next.become(new Rejected(e))}}function tryCatchReject3(f,x,y,thisArg,next){try{f.call(thisArg,x,y,next)}catch(e){next.become(new Rejected(e))}}function tryCatchReturn(f,x,thisArg,next){try{next.notify(f.call(thisArg,x))}catch(e){next.notify(e)}}function inherit(Parent,Child){Child.prototype=objectCreate(Parent.prototype),Child.prototype.constructor=Child}function noop(){}var tasks=environment.scheduler,objectCreate=Object.create||function(proto){function Child(){}return Child.prototype=proto,new Child};Promise.resolve=resolve,Promise.reject=reject,Promise.never=never,Promise._defer=defer,Promise._handler=getHandler,Promise.prototype.then=function(onFulfilled,onRejected){var parent=this._handler;if("function"!=typeof onFulfilled&&parent.join().state()>0)return new Promise(Handler,parent);var p=this._beget(),child=p._handler;return parent.chain(child,parent.receiver,onFulfilled,onRejected,arguments.length>2?arguments[2]:void 0),p},Promise.prototype["catch"]=function(onRejected){return this.then(void 0,onRejected)},Promise.prototype._beget=function(){var parent=this._handler,child=new Pending(parent.receiver,parent.join().context);return new this.constructor(Handler,child)},Promise.all=all,Promise.race=race,Handler.prototype.when=Handler.prototype.become=Handler.prototype.notify=Handler.prototype.fail=Handler.prototype._unreport=Handler.prototype._report=noop,Handler.prototype._state=0,Handler.prototype.state=function(){return this._state},Handler.prototype.join=function(){for(var h=this;void 0!==h.handler;)h=h.handler;return h},Handler.prototype.chain=function(to,receiver,fulfilled,rejected,progress){this.when({resolver:to,receiver:receiver,fulfilled:fulfilled,rejected:rejected,progress:progress})},Handler.prototype.visit=function(receiver,fulfilled,rejected,progress){this.chain(failIfRejected,receiver,fulfilled,rejected,progress)},Handler.prototype.fold=function(f,z,c,to){this.visit(to,function(x){f.call(c,z,x,this)},to.reject,to.notify)},inherit(Handler,FailIfRejected),FailIfRejected.prototype.become=function(h){h.fail()};var failIfRejected=new FailIfRejected;inherit(Handler,Pending),Pending.prototype._state=0,Pending.prototype.resolve=function(x){this.become(getHandler(x))},Pending.prototype.reject=function(x){this.resolved||this.become(new Rejected(x))},Pending.prototype.join=function(){if(!this.resolved)return this;for(var h=this;void 0!==h.handler;)if(h=h.handler,h===this)return this.handler=cycle();return h},Pending.prototype.run=function(){var q=this.consumers,handler=this.join();this.consumers=void 0;for(var i=0;i<q.length;++i)handler.when(q[i])},Pending.prototype.become=function(handler){this.resolved||(this.resolved=!0,this.handler=handler,void 0!==this.consumers&&tasks.enqueue(this),void 0!==this.context&&handler._report(this.context))},Pending.prototype.when=function(continuation){this.resolved?tasks.enqueue(new ContinuationTask(continuation,this.handler)):void 0===this.consumers?this.consumers=[continuation]:this.consumers.push(continuation)},Pending.prototype.notify=function(x){this.resolved||tasks.enqueue(new ProgressTask(x,this))},Pending.prototype.fail=function(context){var c="undefined"==typeof context?this.context:context;this.resolved&&this.handler.join().fail(c)},Pending.prototype._report=function(context){this.resolved&&this.handler.join()._report(context)},Pending.prototype._unreport=function(){this.resolved&&this.handler.join()._unreport()},inherit(Handler,Async),Async.prototype.when=function(continuation){tasks.enqueue(new ContinuationTask(continuation,this))},Async.prototype._report=function(context){this.join()._report(context)},Async.prototype._unreport=function(){this.join()._unreport()},inherit(Pending,Thenable),inherit(Handler,Fulfilled),Fulfilled.prototype._state=1,Fulfilled.prototype.fold=function(f,z,c,to){runContinuation3(f,z,this,c,to)},Fulfilled.prototype.when=function(cont){runContinuation1(cont.fulfilled,this,cont.receiver,cont.resolver)};var errorId=0;inherit(Handler,Rejected),Rejected.prototype._state=-1,Rejected.prototype.fold=function(f,z,c,to){to.become(this)},Rejected.prototype.when=function(cont){"function"==typeof cont.rejected&&this._unreport(),runContinuation1(cont.rejected,this,cont.receiver,cont.resolver)},Rejected.prototype._report=function(context){tasks.afterQueue(new ReportTask(this,context))},Rejected.prototype._unreport=function(){this.handled=!0,tasks.afterQueue(new UnreportTask(this))},Rejected.prototype.fail=function(context){Promise.onFatalRejection(this,void 0===context?this.context:context)},ReportTask.prototype.run=function(){this.rejection.handled||(this.rejection.reported=!0,Promise.onPotentiallyUnhandledRejection(this.rejection,this.context))},UnreportTask.prototype.run=function(){this.rejection.reported&&Promise.onPotentiallyUnhandledRejectionHandled(this.rejection)},Promise.createContext=Promise.enterContext=Promise.exitContext=Promise.onPotentiallyUnhandledRejection=Promise.onPotentiallyUnhandledRejectionHandled=Promise.onFatalRejection=noop;var foreverPendingHandler=new Handler,foreverPendingPromise=new Promise(Handler,foreverPendingHandler);return ContinuationTask.prototype.run=function(){this.handler.join().when(this.continuation)},ProgressTask.prototype.run=function(){var q=this.handler.consumers;if(void 0!==q)for(var c,i=0;i<q.length;++i)c=q[i],runNotify(c.progress,this.value,this.handler,c.receiver,c.resolver)},AssimilateTask.prototype.run=function(){function _resolve(x){h.resolve(x)}function _reject(x){h.reject(x)}function _notify(x){h.notify(x)}var h=this.resolver;tryAssimilate(this._then,this.thenable,_resolve,_reject,_notify)},Promise}})}("function"==typeof define&&define.amd?define:function(factory){module.exports=factory()})},{}]},{},[9])(9)}); \ No newline at end of file
diff --git a/web/src/vendor/react-router/docs/api/README.md b/web/src/vendor/react-router/docs/api/README.md
new file mode 100644
index 00000000..83c33fba
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/README.md
@@ -0,0 +1,32 @@
+React Router API
+================
+
+- [`Router`](/docs/api/Router.md)
+
+- Components
+ - [`DefaultRoute`](/docs/api/components/DefaultRoute.md)
+ - [`Link`](/docs/api/components/Link.md)
+ - [`NotFoundRoute`](/docs/api/components/NotFoundRoute.md)
+ - [`Redirect`](/docs/api/components/Redirect.md)
+ - [`Route`](/docs/api/components/Route.md)
+ - [`RouteHandler`](/docs/api/components/RouteHandler.md)
+ - [`Routes`](/docs/api/components/Routes.md)
+
+- Misc
+ - [`transition`](/docs/api/misc/transition.md)
+
+- Mixins
+ - [`ActiveState`](/docs/api/mixins/ActiveState.md)
+ - [`AsyncState`](/docs/api/mixins/AsyncState.md)
+
+
+Public Modules
+--------------
+
+All modules found at the repository root are considered public. You can
+require them conveniently with `var Route = require('react-router/Route');` etc.
+
+Note that we do not support requiring modules from our `modules`
+directory. (No notes in the changelog, no changes to the versioning of
+the lib, etc.)
+
diff --git a/web/src/vendor/react-router/docs/api/Router.md b/web/src/vendor/react-router/docs/api/Router.md
new file mode 100644
index 00000000..ff0a32f7
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/Router.md
@@ -0,0 +1,65 @@
+API: `Router`
+=============
+
+The main export, `Router`, contains several methods that may be used to
+navigate around the application.
+
+```js
+// cjs modules
+var Router = require('react-router')
+
+// or global build
+window.ReactRouter
+```
+
+Methods
+-------
+
+### `transitionTo(routeNameOrPath, [params[, query]])`
+
+Programmatically transition to a new route.
+
+#### Examples
+
+```js
+Router.transitionTo('user', {id: 10}, {showAge: true});
+Router.transitionTo('about');
+Router.transitionTo('/users/10?showAge=true');
+```
+
+### `replaceWith(routeNameOrPath, [params[, query]])`
+
+Programmatically replace current route with a new route. Does not add an
+entry into the browser history.
+
+#### Examples
+
+```js
+Router.replaceWith('user', {id: 10}, {showAge: true});
+Router.replaceWith('about');
+Router.replaceWith('/users/10?showAge=true');
+```
+
+### `goBack()`
+
+Programmatically go back to the last route and remove the most recent
+entry from the browser history.
+
+#### Example
+
+```js
+Router.goBack();
+```
+
+### `makeHref(routeName, params, query)`
+
+Creates an `href` to a route. Use this along with `ActiveState` when you
+need to build components similar to `Link`.
+
+#### Example
+
+```js
+// given a route like this:
+<Route name="user" path="users/:userId"/>
+Router.makeHref('user', {userId: 123}); // "users/123"
+```
diff --git a/web/src/vendor/react-router/docs/api/components/DefaultRoute.md b/web/src/vendor/react-router/docs/api/components/DefaultRoute.md
new file mode 100644
index 00000000..6607832b
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/components/DefaultRoute.md
@@ -0,0 +1,55 @@
+API: `DefaultRoute` (component)
+===============================
+
+A route that is active when the parent route's path matches exactly. Or,
+in other words, the default child route for a parent.
+
+Note, this is not a `NotFoundRoute`. It is only active when the parent's
+route path is matched exactly.
+
+Props
+-----
+
+See [Route::props][routeProps]
+
+Example
+-------
+
+```xml
+<Routes>
+ <Route path="/" handler={App}>
+
+ <!--
+ when the url is `/`, this handler will be active, or in other
+ words, will be `this.props.activeRouteHandler in the `App` handler
+ -->
+ <DefaultRoute handler={Home}/>
+
+ <Route name="about" handler={About}/>
+ <Route name="users" handler={Users}>
+ <Route name="user" handler={User} path="/user/:id"/>
+
+ <!-- when the url is `/users`, this will be active -->
+ <DefaultRoute handler={UsersIndex}/>
+
+ </Route>
+ </Route>
+</Routes>
+```
+
+This is all really just a shortcut for the less intuitive version of the
+same functionality:
+
+```xml
+<!-- no path or name on what was previously the "users" route -->
+<Route handler={Users}>
+ <!-- the path moved down to the child -->
+ <Route name="users-index" path="/users" handler={UsersIndex}/>
+ <Route name="user" handler={User} path="/user/:id"/>
+</Route>
+```
+
+`DefaultRoute` feels more natural, so you can name and transition to the
+parent route.
+
+ [routeProps]:/docs/api/components/Route.md#props
diff --git a/web/src/vendor/react-router/docs/api/components/Link.md b/web/src/vendor/react-router/docs/api/components/Link.md
new file mode 100644
index 00000000..9c5bfd12
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/components/Link.md
@@ -0,0 +1,71 @@
+API: `Link` (component)
+=========================
+
+Creates an anchor tag that links to a route in the application. Also
+gets the `active` class automatically when the route matches. If you
+change the path of your route, you don't have to change your links.
+
+Props
+-----
+
+### `to`
+
+The name of the route to link to, or a full URL.
+
+### `params`
+
+Object, the parameters to fill in the dynamic segments of your route.
+
+#### Example
+
+```js
+// given a route config like this
+<Route name="user" path="/user/:userId"/>
+
+// create a link with this
+<Link to="user" params={{userId: "123"}}/>
+
+// though, if your user properties match up to the dynamic segements:
+<Link to="user" params={user}/>
+```
+
+### `query`
+
+Object, Query parameters to add to the link. Access query parameters in
+your route handler with `this.props.query`.
+
+### `activeClassName`
+
+The className a `Link` receives when it's route is active. Defaults to
+`active`.
+
+### `onClick`
+
+A custom handler for the click event. Works just like a handler on an `<a>`
+tag - calling `e.preventDefault()` or returning `false` will prevent the
+transition from firing, while `e.stopPropagation()` will prevent the event
+from bubbling.
+
+### *others*
+
+You can also pass props you'd like to be on the `<a>` such as a title, id, or className.
+
+Example
+-------
+
+Given a route like `<Route name="user" path="/users/:userId"/>`:
+
+```xml
+<Link to="user" params={{userId: user.id}} query={{foo: bar}}>{user.name}</Link>
+<!-- becomes one of these depending on your router and if the route is
+active -->
+<a href="/users/123?foo=bar" class="active">Michael</a>
+<a href="#/users/123?foo=bar">Michael</a>
+
+<!-- or if you have the full url already, you can just pass that in -->
+<Link to="/users/123?foo=bar">{user.name}</Link>
+
+<!-- change the activeClassName -->
+<Link activeClassName="current" to="user" params={{userId: user.id}}>{user.name}</Link>
+```
+
diff --git a/web/src/vendor/react-router/docs/api/components/NotFoundRoute.md b/web/src/vendor/react-router/docs/api/components/NotFoundRoute.md
new file mode 100644
index 00000000..366c78b4
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/components/NotFoundRoute.md
@@ -0,0 +1,36 @@
+API: `NotFoundRoute` (component)
+===============================
+
+When a parent's URL partially matches, but none of the children do, a
+`NotFoundRoute` will be matched and its handler rendered at any level of
+your route/view hierarchy.
+
+Props
+-----
+
+See [Route::props][routeProps]
+
+Example
+-------
+
+```xml
+<Routes>
+ <Route path="/" handler={App}>
+ <Route name="course" path="course/:courseId" handler={Course}>
+ <Route name="course-dashboard" path="dashboard" />
+
+ <!-- ie: `/course/123/foo` -->
+ <NotFoundRoute handler={CourseRouteNotFound} />
+ </Route>
+
+ <!-- ie: `/flkjasdf` -->
+ <NotFoundRoute handler={NotFound} />
+ </Route>
+</Routes>
+```
+
+The last `NotFoundRoute` will render inside the `App`, the first will
+rendering inside of `Course`.
+
+ [routeProps]:/docs/api/components/Route.md#props
+
diff --git a/web/src/vendor/react-router/docs/api/components/Redirect.md b/web/src/vendor/react-router/docs/api/components/Redirect.md
new file mode 100644
index 00000000..a31222a0
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/components/Redirect.md
@@ -0,0 +1,59 @@
+API: `Redirect` (component)
+===========================
+
+Configures a redirect for a path in your route declarations.
+
+Props
+-----
+
+### `from`
+
+The path you want to redirect from, including dynamic segments. Defaults
+to `*` so you can redirect anything not found to somewhere else.
+
+### `to`
+
+The `name` of the route you want to redirect to.
+
+Example
+-------
+
+```xml
+<!--
+ lets say we want to change from `/profile/123` to `/about/123`
+ and redirect `/get-in-touch` to `/contact`
+-->
+<Routes>
+ <Route handler={App}>
+ <Route name="contact" handler={Contact}/>
+ <Route name="about-user" path="about/:userId" handler={UserProfile}/>
+ <Route name="course" path="course/:courseId">
+ <Route name="course-dashboard" path="dashboard" handler={Dashboard}/>
+ <Route name="course-assignments" path="assignments" handler={Assignments}/>
+ <!--
+ anything like `/course/123/invalid` redirects to
+ `/course/123/dashboard`
+ -->
+ <Redirect to="course-dashboard" />
+ </Route>
+ </Route>
+
+ <!-- `/get-in-touch` -> `/contact` -->
+ <Redirect from="get-in-touch" to="contact" />
+ <!-- `/profile/123` -> `/about/123` -->
+ <Redirect from="profile/:userId" to="about-user" />
+</Routes>
+```
+
+Note that the `<Redirect/>` can be placed anywhere in the route
+hierarchy, if you'd prefer the redirects to be next to their respective
+routes.
+
+```xml
+<Routes>
+ <Route handler={App}>
+ <Route name="contact" handler={Contact}/>
+ <Redirect from="get-in-touch" to="contact" />
+ </Route>
+</Routes>
+```
diff --git a/web/src/vendor/react-router/docs/api/components/Route.md b/web/src/vendor/react-router/docs/api/components/Route.md
new file mode 100644
index 00000000..b1f3ba9b
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/components/Route.md
@@ -0,0 +1,105 @@
+API: `Route` (component)
+=========================
+
+Configuration component to declare your application's routes and view hierarchy.
+
+Props
+-----
+
+### `name`
+
+The name of the route, used in the `Link` component and the router's
+transition methods.
+
+### `path`
+
+The path used in the URL. If left undefined, the path will be defined by
+the `name`, and if there is no name, will default to `/`.
+
+Please refer to the [Path Matching Guide][path-matching] to learn more
+about supported path matching syntax.
+
+### `handler`
+
+The component to be rendered when the route is active.
+
+### `addHandlerKey`
+
+Defaults to `false`.
+
+If you have dynamic segments in your URL, a transition from `/users/123`
+to `/users/456` does not call `getInitialState`, `componentWillMount` or
+`componentWillUnmount`. If you are using those lifecycle hooks to fetch
+data and set state, you will also need to implement
+`componentWillReceiveProps` on your handler, just like any other
+component with changing props. This way, you can leverage the
+performance of the React DOM diff algorithm. Look at the `Contact`
+handler in the `master-detail` example.
+
+If you'd rather be lazy, set this to `true` and the router will add a
+key to your route, causing all new DOM to be built, and then the life
+cycle hooks will all be called.
+
+You will want this to be `true` if you're doing animations with React's
+TransitionGroup component.
+
+### `preserveScrollPosition`
+
+If `true`, the router will not scroll the window up when the route is
+transitioned to. Defaults to `false`. Ignored if the parent `<Routes/>`
+has been set to `true`.
+
+### `children`
+
+Routes can be nested. When a child route matches, the parent route's
+handler will have the child route's handler available as
+`this.props.activeRouteHandler`. You can then render it in the parent
+passing in any additional props as needed.
+
+### `[prop]`
+
+Any additional, user-defined, properties will be become properties of
+the rendered handler.
+
+#### Example:
+
+```js
+var App;
+var foo = "hello";
+
+var routes = (
+ <Routes>
+ // pass `foo` to `something`
+ <Route handler={App} something={foo}/>
+ </Routes>
+);
+
+App = React.createClass({
+ render: function() {
+ // access `something` on props
+ return <div>{this.props.something}</div>
+ }
+});
+
+React.renderComponent(routes, document.body);
+document.body.innerHTML // -> <div>hello</div>
+```
+
+Example
+-------
+
+```xml
+<Routes>
+ <!-- path defaults to '/' since no name or path provided -->
+ <Route handler={App}>
+ <!-- path is automatically assigned to the name since it is omitted -->
+ <Route name="about" handler={About}/>
+ <Route name="users" handler={Users}>
+ <!-- note the dynamic segment in the path -->
+ <Route name="user" handler={User} path="/user/:id"/>
+ </Route>
+ </Route>
+</Routes>
+```
+
+ [path-matching]:/docs/guides/path-matching.md
diff --git a/web/src/vendor/react-router/docs/api/components/RouteHandler.md b/web/src/vendor/react-router/docs/api/components/RouteHandler.md
new file mode 100644
index 00000000..e39fad94
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/components/RouteHandler.md
@@ -0,0 +1,108 @@
+API: `RouteHandler` (component)
+===============================
+
+The component supplied to a route is called a "Route Handler". They are
+rendered when their route is active. There are some special props and
+static methods available to these components.
+
+Props
+-----
+
+### `activeRouteHandler(extraProps)`
+
+Render the active nested route handler with this property, passing in
+additional properties as needed. This is the mechanism by which you get
+effortless nested UI.
+
+#### Example
+
+```js
+var App = React.createClass({
+ render: function() {
+ <div>
+ <h1>Address Book</h1>
+ {/* the active child route handler will be rendered here */}
+ {/* you can "trickle down" props to the active child */}
+ <this.props.activeRouteHandler someProp="foo" />
+ </div>
+ }
+});
+
+var Contact = React.createClass({
+ render: function() {
+ return <h1>{this.props.params.id}</h1>
+ }
+});
+
+var routes = (
+ <Routes>
+ <Route handler={App}>
+ <Route name="contact" path="/contact/:id" handler={Contact}>
+ </Route>
+ </Routes>
+);
+
+React.renderComponent(routes, document.body);
+```
+
+### `params`
+
+When a route has dynamic segments like `<Route path="users/:userId"/>`,
+the dynamic values from the url are available at
+`this.props.params.userId`, etc.
+
+### `query`
+
+The query parameters from the url.
+
+Static Lifecycle Methods
+------------------------
+
+You can define static methods on your route handlers that will be called
+during route transitions.
+
+### `willTransitionTo(transition, params, query)`
+
+Called when a route is about to render, giving you the opportunity to
+abort or redirect the transition. You can return a promise and the whole
+route hierarchy will wait for the promises to resolve before proceeding.
+
+See also: [transition](/docs/api/misc/transition.md)
+
+### `willTransitionFrom(transition, component)`
+
+Called when an active route is being transitioned out giving you an
+opportunity to abort the transition. The `component` is the current
+component, you'll probably need it to check its state to decide if you
+want to allow the transition.
+
+See also: [transition](/docs/api/misc/transition.md)
+
+#### Example
+
+```js
+var Settings = React.createClass({
+ statics: {
+ willTransitionTo: function(transition, params) {
+ return auth.isLoggedIn().then(function(loggedIn) {
+ if (!loggedIn)
+ return;
+ transition.abort();
+ return auth.logIn({transition: transition});
+ // in auth module call `transition.retry()` after being logged in
+ });
+ },
+
+ willTransitionFrom: function(transition, component) {
+ if (component.formHasUnsavedData())) {
+ if (!confirm('You have unsaved information, are you sure you want to leave this page?')) {
+ transition.abort();
+ }
+ }
+ }
+ }
+
+ //...
+});
+```
+
diff --git a/web/src/vendor/react-router/docs/api/components/Routes.md b/web/src/vendor/react-router/docs/api/components/Routes.md
new file mode 100644
index 00000000..2d9396aa
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/components/Routes.md
@@ -0,0 +1,69 @@
+API: `Routes` (component)
+=========================
+
+Configuration component for your router, all `<Route/>`s must be
+children of a `<Routes/>`. It is the component you provide to
+`React.renderComponent(routes, el)`.
+
+Props
+-----
+
+### `location`
+
+One of `"hash"`, `"history"` or a user defined location implementation,
+defaults to `"hash"`.
+
+`"hash"` includes `#/` in the url and works without a server, if you use
+`history` your server will need to support it.
+
+For browsers that don't support the HTML5 history API the router will
+fall back to `window.location` if you choose `history`, in other words,
+the router will simply cause a full page reload. This way all users get
+the same urls and can share them.
+
+See also: [user supplied locations][Location].
+
+### `preserveScrollPosition`
+
+If `true`, the router will not scroll the window up globally when any
+route is transitioned to. Defaults to `false`. When `false`, the
+`<Route/>` gets to decide whether or not to scroll on transition.
+
+### `onAbortedTransition`
+
+A function called when any transition is aborted.
+
+### `onActiveStateChange`
+
+A function called when the active routes change.
+
+#### signature
+
+`function(nextState)`
+
+### `onTransitionError`
+
+A function called when a transition has an error.
+
+#### signature
+
+`function(error)`
+
+Example
+-------
+
+```jsx
+function onError(error) {
+ handleError(error);
+}
+
+var routes = (
+ <Routes location="history" onTransitionError={onError}>
+ <Route handler={App}/>
+ </Routes>
+);
+React.renderComponent(routes, document.body);
+```
+
+ [Location]:../misc/Location.md
+
diff --git a/web/src/vendor/react-router/docs/api/misc/Location.md b/web/src/vendor/react-router/docs/api/misc/Location.md
new file mode 100644
index 00000000..f0b2077b
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/misc/Location.md
@@ -0,0 +1,66 @@
+API: `Location` (object)
+==========================
+
+You can supply the router with your own location implementation. The
+following methods must be implemented:
+
+Methods
+-------
+
+### `setup(onChange)`
+
+Called when the router is first setup. Whenever an external actor should
+cause the router to react, call `onChange` (for example, on
+`window.hashchange`).
+
+### `teardown`
+
+Called when the router is torn down.
+
+### `push`
+
+Called when the router is transitioning from one path to another.
+
+### `replace`
+
+Called when ther router is replacing (not transitioning) one url with
+another.
+
+### `pop`
+
+Called when the router attempts to go back one entry in the history.
+
+### `getCurrentPath`
+
+Should return the current path as a string.
+
+### `toString`
+
+Should return a useful string for logging and debugging.
+
+Example
+-------
+
+This is a terrible example, you're probably better off looking at the
+implementations in this repository.
+
+```js
+var MyLocation = {
+
+ setup: function (onChange) {},
+
+ teardown: function () {},
+
+ push: function (path) {},
+
+ replace: function (path) {},
+
+ pop: function () {},
+
+ getCurrentPath: function () {},
+
+ toString: function () {}
+
+};
+```
+
diff --git a/web/src/vendor/react-router/docs/api/misc/transition.md b/web/src/vendor/react-router/docs/api/misc/transition.md
new file mode 100644
index 00000000..fc039572
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/misc/transition.md
@@ -0,0 +1,24 @@
+API: `transition` (object)
+==========================
+
+This object is sent to the [transition hooks][transition-hooks] as the
+first argument.
+
+Methods
+-------
+
+### `abort()`
+
+Aborts a transition.
+
+### `redirect(to, params, query)`
+
+Redirect to another route.
+
+### `retry()`
+
+Retrys a transition. Typically you save off a transition you care to
+return to, finish the workflow, then retry.
+
+ [transition-hooks]:/docs/api/components/RouteHandler.md#static-lifecycle-methods
+
diff --git a/web/src/vendor/react-router/docs/api/mixins/ActiveState.md b/web/src/vendor/react-router/docs/api/mixins/ActiveState.md
new file mode 100644
index 00000000..f251bd35
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/mixins/ActiveState.md
@@ -0,0 +1,58 @@
+API: `ActiveState` (mixin)
+==========================
+
+A mixin for components that need to know about the routes, params, and
+query that are currently active (like links).
+
+Static Methods
+--------------
+
+### `isActive(routeName, params, query)`
+
+Returns `true` if a route, params, and query are active, `false`
+otherwise.
+
+Lifecycle Methods
+-----------------
+
+### `updateActiveState`
+
+Called when the active state changes.
+
+Example
+-------
+
+Let's say you are using bootstrap and want to get `active` on those `li`
+tags for the Tabs:
+
+```js
+var Link = require('react-router/Link');
+var ActiveState = require('react-router/ActiveState');
+
+var Tab = React.createClass({
+
+ mixins: [ ActiveState ],
+
+ getInitialState: function () {
+ return { isActive: false };
+ },
+
+ updateActiveState: function () {
+ this.setState({
+ isActive: Tab.isActive(this.props.to, this.props.params, this.props.query)
+ })
+ },
+
+ render: function() {
+ var className = this.state.isActive ? 'active' : '';
+ var link = Link(this.props);
+ return <li className={className}>{link}</li>;
+ }
+
+});
+
+// use it just like <Link/>, and you'll get an anchor wrapped in an `li`
+// with an automatic `active` class on both.
+<Tab to="foo">Foo</Tab>
+```
+
diff --git a/web/src/vendor/react-router/docs/api/mixins/AsyncState.md b/web/src/vendor/react-router/docs/api/mixins/AsyncState.md
new file mode 100644
index 00000000..e3a40c8c
--- /dev/null
+++ b/web/src/vendor/react-router/docs/api/mixins/AsyncState.md
@@ -0,0 +1,115 @@
+API: `AsyncState` (mixin)
+=========================
+
+A mixin for route handlers that fetch at least part of their state
+asynchronously.
+
+Static Lifecycle Methods
+------------------------
+
+### `getInitialAsyncState(params, query, setState)`
+
+Fetches state for a component after it mounts. Much like the familiar
+`getInitialState` method, `getInitialAsyncState` should return a hash of
+key/value pairs to use in the component's state. The difference is that
+the values may be promises. As these values resolve, the component's
+state is updated.
+
+#### Parameters
+
+##### params (object)
+
+The url parameters.
+
+##### query (object)
+
+The url query parameters
+
+##### setState (function)
+
+A function that can be used to `setState` as it is received, useful for
+things like `xhr` progress and streamed data. Typically you won't use
+this.
+
+Props
+-----
+
+### `initialAsyncState`
+
+When testing, use the `initialAsyncState` prop to simulate asynchronous
+data fetching. When this prop is present, no attempt is made to retrieve
+additional state via `getInitialAsyncState`.
+
+Examples
+--------
+
+In it simplest form, just return a hash of promises, they become state:
+
+```js
+var User = React.createClass({
+ mixins: [ Router.AsyncState ],
+
+ statics: {
+ getInitialAsyncState: function (params, query, setState) {
+ return {
+ user: fetchUser(params.userId),
+ activity: fetchActivityForUser(params.userId)
+ }
+ }
+ },
+
+ render: function() {
+ return this.state.user ?
+ <LoadingUserProfile/> :
+ <UserProfile user={this.state.user} activity={this.state.activity} />;
+ }
+});
+```
+
+But you can get fancier...
+
+```js
+var User = React.createClass({
+ mixins: [ Router.AsyncState ],
+
+ statics: {
+ getInitialAsyncState: function (params, query, setState) {
+ var buffer = '';
+
+ return {
+ user: getUserByID(params.userID) // may be a promise
+ activity: {}, // an immediate value (not a promise)
+ stream: getStreamingData(params.userID, function (chunk) {
+ // `getStreamingData` returns a promise, but also calls back as
+ // data is received, giving us a chance to update the UI with
+ // progress using the `AsyncState` specific `setState`
+ // function
+ buffer += chunk;
+ setState({ streamBuffer: buffer });
+ })
+ };
+ }
+ },
+
+ getInitialState: function () {
+ return {
+ user: null, // Receives a value when getUserByID resolves.
+ stream: null, // Receives a value when getStreamingData resolves.
+ streamBuffer: '' // Used to track data as it loads.
+ };
+ },
+
+ render: function () {
+ if (!this.state.user)
+ return <LoadingUser/>;
+
+ return (
+ <div>
+ <p>Welcome {this.state.user.name}!</p>
+ <p>So far, you've received {this.state.streamBuffer.length} data!</p>
+ </div>
+ );
+ }
+});
+```
+
diff --git a/web/src/vendor/react-router/docs/guides/overview.md b/web/src/vendor/react-router/docs/guides/overview.md
new file mode 100644
index 00000000..9acd8115
--- /dev/null
+++ b/web/src/vendor/react-router/docs/guides/overview.md
@@ -0,0 +1,373 @@
+React Router Guide
+==================
+
+Nesting UI is at the core of React Router. Think about any user
+interface you're accustomed to, there is likely some shared UI as you
+navigate around the application.
+
+Let's imagine a little app with a dashboard, inbox, and calendar.
+
+```
++---------------------------------------------------------+
+| +---------+ +-------+ +--------+ |
+| |Dashboard| | Inbox | |Calendar| Logged in as Joe |
+| +---------+ +-------+ +--------+ |
++---------------------------------------------------------+
+| |
+| Dashboard |
+| |
+| |
+| +---------------------+ +----------------------+ |
+| | | | | |
+| | + + | +---------> | |
+| | | | | | | |
+| | | + | | +-------------> | |
+| | | | + | | | | |
+| | | | | | | | | |
+| +-+---+----+-----+----+ +----------------------+ |
+| |
++---------------------------------------------------------+
+```
+
+We have three main screens here with the top section of UI being
+persistent.
+
+Without React Router
+--------------------
+
+Without this router, you'd share that UI by repeating render code across
+your views, probably with a `<Header/>` component:
+
+```js
+var Header = React.createClass({
+ render: function() {
+ return (
+ <header>
+ <ul>
+ <li><a href="/">Dashboard</a></li>
+ <li><a href="/inbox">Inbox</a></li>
+ <li><a href="/calendar">Calendar</a></li>
+ </ul>
+ Logged in as Joe
+ </header>
+ );
+ }
+});
+
+var DashboardRoute = React.createClass({
+ render: function() {
+ return (
+ <div>
+ <Header/>
+ <Dashboard/>
+ </div>
+ );
+ }
+});
+
+var InboxRoute = React.createClass({
+ render: function() {
+ return (
+ <div>
+ <Header/>
+ <Inbox/>
+ </div>
+ );
+ }
+});
+
+var CalendarRoute = React.createClass({
+ render: function() {
+ return (
+ <div>
+ <Header/>
+ <Calendar/>
+ </div>
+ );
+ }
+});
+
+// Not React Router API
+otherRouter.route('/', function() {
+ React.renderComponent(<DashboardRoute/>, document.body);
+});
+
+otherRouter.route('/inbox', function() {
+ React.renderComponent(<InboxRoute/>, document.body);
+});
+
+otherRouter.route('/calendar', function() {
+ React.renderComponent(<CalendarRoute/>, document.body);
+});
+
+```
+
+The three main view's render methods are nearly identical. While one
+level of shared UI like this is pretty easy to handle, getting deeper
+and deeper adds more complexity, along with lots of `switch` branching,
+etc.
+
+React Router embraces this common pattern among user interfaces by
+nesting the views for you.
+
+With React Router
+-----------------
+
+Here's how it works:
+
+1. You declare your view hierarchy with nested `<Route/>`s and provide
+ them with a React component to handle the route when its active.
+
+2. React Router will match the deepest route against the URL, and then
+ activate the entire tree of routes on that branch, nesting all the
+ UI.
+
+3. You access the active route handler in the props of the parent route.
+
+```js
+var App = React.createClass({
+ render: function() {
+ return (
+ <div>
+ <header>
+ <ul>
+ <li><Link to="app">Dashboard</Link></li>
+ <li><Link to="inbox">Inbox</Link></li>
+ <li><Link to="calendar">Calendar</Link></li>
+ </ul>
+ Logged in as Joe
+ </header>
+
+ {/* this is the important part */}
+ <this.props.activeRouteHandler/>
+ </div>
+ );
+ }
+});
+
+var routes = (
+ <Routes location="history">
+ <Route name="app" path="/" handler={App}>
+ <Route name="inbox" handler={Inbox}/>
+ <Route name="calendar" handler={Calendar}/>
+ <DefaultRoute handler={Dashboard}/>
+ </Route>
+ </Routes>
+);
+
+React.renderComponent(routes, document.body);
+```
+
+When the user lands at `/inbox`, the route named `inbox` gets matched so
+its parent route will render the `App` component, and since `inbox` is
+active, you get `Inbox` as `this.props.activeRouteHandler`. This is
+nearly identical to `{{outlet}}` from Ember or `<div ng-view/>` from
+angular.
+
+When the user navigates to `/calendar`, the same thing happens except
+now `Calendar` is the `activeRouteHandler` in `App`'s render method.
+
+Finally, when the user navigates to the path `/`, `App` is active, and
+notices that it has a `DefaultRoute`, so it receives `Dashboard` as the
+`activeRouteHandler`. If a `DefaultRoute` is defined, it will be active
+when the parent's route is matched exactly.
+
+Note that we don't need the `<Header/>` component since we don't have to
+repeat it anymore. React Router shares that UI for us from one place.
+
+More Nesting
+------------
+
+Nesting arbitarily deep UI is not a problem. Consider the `Inbox`
+screen: it has a master list of messages on the left, a detail view of
+the message on the right, and a toolbar over the top. The toolbar and
+list are persistent, meanwhile the message view changes as the user
+navigates through the messages.
+
+```
++---------------------------------------------------------------------+
+| +---------+ +-------+ +--------+ |
+| |Dashboard| | Inbox | |Calendar| Logged in as Joe |
+| +---------+ +-------+ +--------+ |
++---------------------------------------------------------------------+
+| +---------+ +-------+ +--------------+ |
+| | Compose | | Reply | |Inbox Settings| |
+| +---------+ +-------+ +--------------+ |
++-------------------+-------------------------------------------------+
+| David Brown | |
+| Hey, we need to...| |
+| | |
+| 12:30pm | |
++-------------------+ 32 Unread Messages |
+| Mary Sweeney | |
+| I followed up w...| 456 Total Messages |
+| | |
+| 12:10pm | 3 Draft Messages |
++-------------------+ |
+| DeMarcus Jones | |
+| check this out ...| |
+| | |
+| 11:25am | |
++-------------------+-------------------------------------------------+
+```
+
+Let's see how React Router handles this:
+
+```js
+var Inbox = React.createClass({
+ render: function() {
+ return (
+ <div>
+ <Toolbar/>
+ <Messages/>
+ <this.props.activeRouteHandler/>
+ </div>
+ );
+ }
+});
+
+var routes = (
+ <Routes location="history">
+ <Route handler={App}>
+
+ <Route name="inbox" handler={Inbox}>
+ <Route name="message" path=":messageId" handler={Message}/>
+ <DefaultRoute handler={InboxStats}/>
+ </Route>
+
+ <Route name="calendar" handler={Calendar}/>
+ <DefaultRoute handler={Dashboard}/>
+
+ </Route>
+ </Routes>
+);
+```
+
+- Inbox now has `this.props.activeRouteHandler` in its render method,
+ exactly like its parent.
+- We added a child routes to `inbox`; messages or the stats page can now
+ render into it.
+
+Nesting a new level of UI does not increase the complexity of your code.
+You simply nest some routes and render them with `activeRouteHandler`.
+
+Dynamic Segments
+----------------
+
+When we added the `message` route, we introduced a "dynamic segment" to
+the URL. These segements get parsed from the url and passed into your
+route handler on `this.props.params`.
+
+Remember our message route looks like this:
+
+```xml
+<Route name="message" path=":messageId" handler={Message}/>
+```
+
+Lets look at accessing the `messageId` in `Message`.
+
+```js
+var Message = React.createClass({
+ render: function() {
+ return (
+ <div>{this.props.params.messageId}</div>
+ );
+ }
+});
+```
+
+Assuming the user navigates to `/inbox/123`, `this.props.params.messageId` is
+going to be `'123'`. Check out the [AsyncState][AsyncState] mixin to see
+how you can turn this parameter into state on your component. Or for a
+more basic approach, make an ajax call in `componentDidMount` with the
+value.
+
+Important Note About Dynamic Segments
+-------------------------------------
+
+If you have dynamic segments in your URL, a transition from `/users/123`
+to `/users/456` does not call `getInitialState`, `componentWillMount` or
+`componentWillUnmount`. If you are using those lifecycle hooks to fetch
+data and set state, you will also need to implement
+`componentWillReceiveProps` on your handler, just like any other
+component whose props are changing. This way you can leverage the
+performance of the React DOM diff algorithm. Look at the `Contact`
+handler in the `master-detail` example.
+
+If you'd rather be lazy, you can use the `addHandlerKey` option and set
+it to `true` on your route to opt-out of the performance. See also
+[Route][Route].
+
+Scrolling
+---------
+
+By default, the router will manage the scroll position between route
+transitions. When a user clicks "back" or "forward", it will restore
+their scroll position. If they visit a new route, it will automatically
+scroll the window to the top. You can opt out of this with the
+`preserverScrollPosition` option on [Routes][Routes] or [Route][Route].
+
+Bells and Whistles
+------------------
+
+### `<Link/>`
+
+The `<Link/>` component allows you to conveniently navigate users around
+the application with accessible anchor tags that don't break normal link
+functionality like control/command clicking to open in a new tab. Also,
+when the route a link references is active, you get the `active` css
+class to easily style your UI.
+
+### `<NotFoundRoute/>`
+
+At any level of your UI nesting, you can render a handler if the url
+beyond what was matched isn't recognized.
+
+```xml
+<Routes location="history">
+ <Route path="/" handler={App}>
+ <Route name="inbox" path="/inbox" handler={Inbox}>
+ <!--
+ will render inside the `Inbox` UI for any paths not recognized
+ after the parent route's path `/inbox/*`
+ -->
+ <NotFoundRoute handler={InboxNotFound}
+ <Route name="message" path="/inbox/:messageId" handler={Message}/>
+ <DefaultRoute handler={InboxStats}/>
+ </Route>
+ <Route name="calendar" path="/calendar" handler={Calendar}/>
+ <DefaultRoute handler={Dashboard}/>
+ </Route>
+ <!-- will catch any route that isn't recognized at all -->
+ <NotFoundRoute handler={NotFound}
+</Routes>
+```
+
+### `<Redirect/>`
+
+URLs in an app change, so we made it easy to not break the old ones.
+
+```xml
+<Route name="message" path="/inbox/:messageId" handler={Message} />
+<Redirect path="/messages/:messageId" to="message" />
+```
+
+Path Matching
+-------------
+
+There's a lot more to be said about path matching, check out the [Path
+Matching Guide][path-matching].
+
+API Documentation
+-----------------
+
+That's the gist of what this router is all about, but there's a lot more
+it has to offer. Check out the [API Docs][API] to learn about
+redirecting transitions, query parameters and more.
+
+ [AsyncState]:../api/mixins/AsyncState.md
+ [Route]:../api/components/Route.md
+ [Routes]:../api/components/Routes.md
+ [API]:../api/
+ [path-matching]:./path-matching.md
+
diff --git a/web/src/vendor/react-router/docs/guides/path-matching.md b/web/src/vendor/react-router/docs/guides/path-matching.md
new file mode 100644
index 00000000..67eadce9
--- /dev/null
+++ b/web/src/vendor/react-router/docs/guides/path-matching.md
@@ -0,0 +1,83 @@
+Path Matching
+=============
+
+Relative v. Absolute Paths
+--------------------------
+
+Paths that start with `/` are absolute, paths that don't are relative,
+meaning they extend their parent's path.
+
+```xml
+<Route path="/">
+ <!-- /courses/123 -->
+ <Route path="courses/:courseId">
+ <!-- /courses/123/anouncements -->
+ <Route path="announcements" />
+ <!-- /courses/123/dashboard -->
+ <Route path="dashboard" />
+ </Route>
+ <!-- /inbox -->
+ <Route path="inbox">
+ <!-- /messages/123 -->
+ <Route path="/messages/:messageId"/>
+ </Route>
+</Route>
+```
+
+Absolute paths allow you to use any URL you want while maintaining the
+automatic view nesting of the router.
+
+Dynamic Segments
+----------------
+
+Dynamic segements are defined with a `:`, like `:userId`. They will be
+parsed and available by name in your route handler on
+`this.props.params`. They match most characters except `. / ? #`.
+
+Splats
+------
+
+Splats are defined with `*` and will non-greedily match anything. The
+value will be available in your route handler as
+`this.props.params.splat`. If there are multiple, you'll get an array of
+values.
+
+Question Mark
+-------------
+
+Question marks will optionally match the preceeding segment.
+
+Examples
+--------
+
+```
+path: /file/:name.?:ext?
+matches:
+ /file/foo.js
+ this.props.params: {name: 'foo', ext: 'js'}
+ /file/foo
+ this.props.params: {name: 'foo'}
+does not match:
+ /file/foo.bar.js
+ /file/quux/baz.js
+
+path: /file/*
+matches:
+ /file/foo.bar.js
+ this.props.params: {splat: 'foo.bar.js'}
+ /file/quux/baz.js
+ this.props.params: {splat: 'quux/baz.js'}
+
+path: /foo/*/:bar/?*?
+matches:
+ /foo/a.b.c/taco/def
+ this.props.params: {bar: 'taco', splat: ['a.b.c', 'def']}
+ /foo/a.b.c/taco
+ this.props.params: {bar: 'taco', splat: 'a.b.c'}
+does not match:
+ /foo/a.b.c
+
+path: *
+matches everything, but you probably want `<NotFoundRoute/>`
+```
+
diff --git a/web/src/vendor/react-router/eslint.json b/web/src/vendor/react-router/eslint.json
new file mode 100644
index 00000000..2035fb08
--- /dev/null
+++ b/web/src/vendor/react-router/eslint.json
@@ -0,0 +1,18 @@
+{
+ "env": {
+ "browser": true,
+ "node": true
+ },
+ "rules": {
+ "quotes": 0,
+ "no-comma-dangle": 2,
+ "no-underscore-dangle": 0,
+ "curly": 0,
+ "strict": 0,
+ "no-use-before-define": 0,
+ "no-cond-assign": 0,
+ "consistent-return": 0,
+ "new-cap": 0,
+ "no-unused-vars": 0
+ }
+}
diff --git a/web/src/vendor/react-router/scripts/build b/web/src/vendor/react-router/scripts/build
new file mode 100755
index 00000000..6ab34e2b
--- /dev/null
+++ b/web/src/vendor/react-router/scripts/build
@@ -0,0 +1,4 @@
+#!/bin/sh
+mkdir -p dist
+NODE_ENV=production node_modules/.bin/browserify modules/index.js -t browserify-shim -t envify --detect-globals false -s ReactRouter > dist/react-router.js
+node_modules/.bin/uglifyjs dist/react-router.js --compress warnings=false > dist/react-router.min.js
diff --git a/web/src/vendor/react-router/scripts/build-examples b/web/src/vendor/react-router/scripts/build-examples
new file mode 100755
index 00000000..122b5471
--- /dev/null
+++ b/web/src/vendor/react-router/scripts/build-examples
@@ -0,0 +1,18 @@
+#!/bin/sh
+BROWSERIFY="node_modules/.bin/browserify --debug --detect-globals false"
+BUNDLE_EXAMPLE="$BROWSERIFY -t reactify -x react -x react/lib/ReactCSSTransitionGroup -x when -x react-router"
+
+NODE_ENV=development $BROWSERIFY -t envify -r react -r react/lib/ReactCSSTransitionGroup -r when -r ./modules:react-router > examples/global-bundle.js
+
+$BUNDLE_EXAMPLE examples/animations/app.js > examples/animations/app-bundle.js
+$BUNDLE_EXAMPLE examples/auth-flow/app.js > examples/auth-flow/app-bundle.js
+$BUNDLE_EXAMPLE examples/data-flow/app.js > examples/data-flow/app-bundle.js
+$BUNDLE_EXAMPLE examples/dynamic-segments/app.js > examples/dynamic-segments/app-bundle.js
+$BUNDLE_EXAMPLE examples/master-detail/app.js > examples/master-detail/app-bundle.js
+# $BUNDLE_EXAMPLE examples/partial-app-loading/app.js > examples/partial-app-loading/app-bundle.js
+# $BUNDLE_EXAMPLE examples/partial-app-loading/dashboard.js > examples/partial-app-loading/dashboard-bundle.js
+# $BUNDLE_EXAMPLE examples/partial-app-loading/inbox.js > examples/partial-app-loading/inbox-bundle.js
+$BUNDLE_EXAMPLE examples/query-params/app.js > examples/query-params/app-bundle.js
+$BUNDLE_EXAMPLE examples/shared-root/app.js > examples/shared-root/app-bundle.js
+$BUNDLE_EXAMPLE examples/simple-master-detail/app.js > examples/simple-master-detail/app-bundle.js
+$BUNDLE_EXAMPLE examples/transitions/app.js > examples/transitions/app-bundle.js
diff --git a/web/src/vendor/react-router/scripts/preview-release b/web/src/vendor/react-router/scripts/preview-release
new file mode 100755
index 00000000..40ac20e2
--- /dev/null
+++ b/web/src/vendor/react-router/scripts/preview-release
@@ -0,0 +1,2 @@
+#!/bin/sh
+node_modules/rf-release/node_modules/.bin/changelog -t preview -s
diff --git a/web/src/vendor/react-router/scripts/release b/web/src/vendor/react-router/scripts/release
new file mode 100755
index 00000000..b839eb36
--- /dev/null
+++ b/web/src/vendor/react-router/scripts/release
@@ -0,0 +1,3 @@
+#!/bin/sh
+scripts/build
+node_modules/.bin/release
diff --git a/web/src/vendor/react-router/scripts/test b/web/src/vendor/react-router/scripts/test
new file mode 100755
index 00000000..61133350
--- /dev/null
+++ b/web/src/vendor/react-router/scripts/test
@@ -0,0 +1,2 @@
+#!/bin/sh
+NODE_ENV=test node_modules/.bin/karma start "$@"