react-router-rails 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a68409d4877d9e9a1fbd0c91f318a273721b4edb
4
+ data.tar.gz: 6adc1694dad4a5d3b1a252928b3a675718d57eda
5
+ SHA512:
6
+ metadata.gz: 8a73f7cc3f58d6d6a969eff52b0062ea29e3dc64eac9b9198c6b186906358125b8fb92f0e41c765e929ec08ff541b87055244e74b9d037596525768b518ea597
7
+ data.tar.gz: 004890fee3d875a49989ffa640df4530e2aa12e00a7192d4666c24695e75b7a6e0c633a568ad9d3e22a97cfd9d46ed7431a9918f59f993ad23c1c46b26b68f07
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Mario Peixoto
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # react-router-rails
2
+
3
+ [React Router](https://github.com/rackt/react-router/) for Rails asset pipeline
4
+
5
+ - React Router version: [0.11.6](https://github.com/rackt/react-router/tree/v0.11.6)
6
+
7
+ ## Installation
8
+
9
+ 1. Add to your `Gemfile` and install with bundler:
10
+
11
+ ```ruby
12
+ gem 'react-router-rails', '~>0.11.6'
13
+ ```
14
+
15
+ ```bash
16
+ bundle install
17
+
18
+ 2. Require the modified React-Router javascript file in `app/assets/javascripts/application.js`:
19
+
20
+ ```js
21
+ //= require react_router
22
+ ```
23
+
24
+ Or in `app/assets/javascripts/application.js.coffee`:
25
+
26
+ ```coffeescript
27
+ #= require react_router
28
+ ```
29
+
30
+ ## Acknowledgements
31
+
32
+ [React Router](https://github.com/rackt/react-router/) licensed under the [MIT license](https://github.com/rackt/react-router/blob/master/LICENSE)
33
+
34
+ Copyright [Mario Peixoto](https://github.com/mariopeixoto), released under the [MIT license](https://github.com/mariopeixoto/react-router-rails/LICENSE).
@@ -0,0 +1,2 @@
1
+ require "react/router/rails/version"
2
+ require "react/router/rails/engine"
@@ -0,0 +1,8 @@
1
+ module React
2
+ module Router
3
+ module Rails
4
+ class Engine < ::Rails::Engine
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module React
2
+ module Router
3
+ module Rails
4
+ VERSION = "0.0.1"#"0.11.6"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3891 @@
1
+ !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){
2
+ /**
3
+ * Actions that modify the URL.
4
+ */
5
+ var LocationActions = {
6
+
7
+ /**
8
+ * Indicates a new location is being pushed to the history stack.
9
+ */
10
+ PUSH: 'push',
11
+
12
+ /**
13
+ * Indicates the current location should be replaced.
14
+ */
15
+ REPLACE: 'replace',
16
+
17
+ /**
18
+ * Indicates the most recent entry should be removed from the history stack.
19
+ */
20
+ POP: 'pop'
21
+
22
+ };
23
+
24
+ module.exports = LocationActions;
25
+
26
+ },{}],2:[function(_dereq_,module,exports){
27
+ var LocationActions = _dereq_('../actions/LocationActions');
28
+
29
+ /**
30
+ * A scroll behavior that attempts to imitate the default behavior
31
+ * of modern browsers.
32
+ */
33
+ var ImitateBrowserBehavior = {
34
+
35
+ updateScrollPosition: function (position, actionType) {
36
+ switch (actionType) {
37
+ case LocationActions.PUSH:
38
+ case LocationActions.REPLACE:
39
+ window.scrollTo(0, 0);
40
+ break;
41
+ case LocationActions.POP:
42
+ if (position) {
43
+ window.scrollTo(position.x, position.y);
44
+ } else {
45
+ window.scrollTo(0, 0);
46
+ }
47
+ break;
48
+ }
49
+ }
50
+
51
+ };
52
+
53
+ module.exports = ImitateBrowserBehavior;
54
+
55
+ },{"../actions/LocationActions":1}],3:[function(_dereq_,module,exports){
56
+ /**
57
+ * A scroll behavior that always scrolls to the top of the page
58
+ * after a transition.
59
+ */
60
+ var ScrollToTopBehavior = {
61
+
62
+ updateScrollPosition: function () {
63
+ window.scrollTo(0, 0);
64
+ }
65
+
66
+ };
67
+
68
+ module.exports = ScrollToTopBehavior;
69
+
70
+ },{}],4:[function(_dereq_,module,exports){
71
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
72
+ var FakeNode = _dereq_('../mixins/FakeNode');
73
+ var PropTypes = _dereq_('../utils/PropTypes');
74
+
75
+ /**
76
+ * A <DefaultRoute> component is a special kind of <Route> that
77
+ * renders when its parent matches but none of its siblings do.
78
+ * Only one such route may be used at any given level in the
79
+ * route hierarchy.
80
+ */
81
+ var DefaultRoute = React.createClass({
82
+
83
+ displayName: 'DefaultRoute',
84
+
85
+ mixins: [ FakeNode ],
86
+
87
+ propTypes: {
88
+ name: React.PropTypes.string,
89
+ path: PropTypes.falsy,
90
+ handler: React.PropTypes.func.isRequired
91
+ }
92
+
93
+ });
94
+
95
+ module.exports = DefaultRoute;
96
+
97
+ },{"../mixins/FakeNode":14,"../utils/PropTypes":25}],5:[function(_dereq_,module,exports){
98
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
99
+ var classSet = _dereq_('react/lib/cx');
100
+ var assign = _dereq_('react/lib/Object.assign');
101
+ var Navigation = _dereq_('../mixins/Navigation');
102
+ var State = _dereq_('../mixins/State');
103
+
104
+ function isLeftClickEvent(event) {
105
+ return event.button === 0;
106
+ }
107
+
108
+ function isModifiedEvent(event) {
109
+ return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
110
+ }
111
+
112
+ /**
113
+ * <Link> components are used to create an <a> element that links to a route.
114
+ * When that route is active, the link gets an "active" class name (or the
115
+ * value of its `activeClassName` prop).
116
+ *
117
+ * For example, assuming you have the following route:
118
+ *
119
+ * <Route name="showPost" path="/posts/:postID" handler={Post}/>
120
+ *
121
+ * You could use the following component to link to that route:
122
+ *
123
+ * <Link to="showPost" params={{ postID: "123" }} />
124
+ *
125
+ * In addition to params, links may pass along query string parameters
126
+ * using the `query` prop.
127
+ *
128
+ * <Link to="showPost" params={{ postID: "123" }} query={{ show:true }}/>
129
+ */
130
+ var Link = React.createClass({
131
+
132
+ displayName: 'Link',
133
+
134
+ mixins: [ Navigation, State ],
135
+
136
+ propTypes: {
137
+ activeClassName: React.PropTypes.string.isRequired,
138
+ to: React.PropTypes.string.isRequired,
139
+ params: React.PropTypes.object,
140
+ query: React.PropTypes.object,
141
+ onClick: React.PropTypes.func
142
+ },
143
+
144
+ getDefaultProps: function () {
145
+ return {
146
+ activeClassName: 'active'
147
+ };
148
+ },
149
+
150
+ handleClick: function (event) {
151
+ var allowTransition = true;
152
+ var clickResult;
153
+
154
+ if (this.props.onClick)
155
+ clickResult = this.props.onClick(event);
156
+
157
+ if (isModifiedEvent(event) || !isLeftClickEvent(event))
158
+ return;
159
+
160
+ if (clickResult === false || event.defaultPrevented === true)
161
+ allowTransition = false;
162
+
163
+ event.preventDefault();
164
+
165
+ if (allowTransition)
166
+ this.transitionTo(this.props.to, this.props.params, this.props.query);
167
+ },
168
+
169
+ /**
170
+ * Returns the value of the "href" attribute to use on the DOM element.
171
+ */
172
+ getHref: function () {
173
+ return this.makeHref(this.props.to, this.props.params, this.props.query);
174
+ },
175
+
176
+ /**
177
+ * Returns the value of the "class" attribute to use on the DOM element, which contains
178
+ * the value of the activeClassName property when this <Link> is active.
179
+ */
180
+ getClassName: function () {
181
+ var classNames = {};
182
+
183
+ if (this.props.className)
184
+ classNames[this.props.className] = true;
185
+
186
+ if (this.isActive(this.props.to, this.props.params, this.props.query))
187
+ classNames[this.props.activeClassName] = true;
188
+
189
+ return classSet(classNames);
190
+ },
191
+
192
+ render: function () {
193
+ var props = assign({}, this.props, {
194
+ href: this.getHref(),
195
+ className: this.getClassName(),
196
+ onClick: this.handleClick
197
+ });
198
+
199
+ return React.DOM.a(props, this.props.children);
200
+ }
201
+
202
+ });
203
+
204
+ module.exports = Link;
205
+
206
+ },{"../mixins/Navigation":15,"../mixins/State":19,"react/lib/Object.assign":40,"react/lib/cx":41}],6:[function(_dereq_,module,exports){
207
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
208
+ var FakeNode = _dereq_('../mixins/FakeNode');
209
+ var PropTypes = _dereq_('../utils/PropTypes');
210
+
211
+ /**
212
+ * A <NotFoundRoute> is a special kind of <Route> that
213
+ * renders when the beginning of its parent's path matches
214
+ * but none of its siblings do, including any <DefaultRoute>.
215
+ * Only one such route may be used at any given level in the
216
+ * route hierarchy.
217
+ */
218
+ var NotFoundRoute = React.createClass({
219
+
220
+ displayName: 'NotFoundRoute',
221
+
222
+ mixins: [ FakeNode ],
223
+
224
+ propTypes: {
225
+ name: React.PropTypes.string,
226
+ path: PropTypes.falsy,
227
+ handler: React.PropTypes.func.isRequired
228
+ }
229
+
230
+ });
231
+
232
+ module.exports = NotFoundRoute;
233
+
234
+ },{"../mixins/FakeNode":14,"../utils/PropTypes":25}],7:[function(_dereq_,module,exports){
235
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
236
+ var FakeNode = _dereq_('../mixins/FakeNode');
237
+ var PropTypes = _dereq_('../utils/PropTypes');
238
+
239
+ /**
240
+ * A <Redirect> component is a special kind of <Route> that always
241
+ * redirects to another route when it matches.
242
+ */
243
+ var Redirect = React.createClass({
244
+
245
+ displayName: 'Redirect',
246
+
247
+ mixins: [ FakeNode ],
248
+
249
+ propTypes: {
250
+ path: React.PropTypes.string,
251
+ from: React.PropTypes.string, // Alias for path.
252
+ to: React.PropTypes.string,
253
+ handler: PropTypes.falsy
254
+ }
255
+
256
+ });
257
+
258
+ module.exports = Redirect;
259
+
260
+ },{"../mixins/FakeNode":14,"../utils/PropTypes":25}],8:[function(_dereq_,module,exports){
261
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
262
+ var FakeNode = _dereq_('../mixins/FakeNode');
263
+
264
+ /**
265
+ * <Route> components specify components that are rendered to the page when the
266
+ * URL matches a given pattern.
267
+ *
268
+ * Routes are arranged in a nested tree structure. When a new URL is requested,
269
+ * the tree is searched depth-first to find a route whose path matches the URL.
270
+ * When one is found, all routes in the tree that lead to it are considered
271
+ * "active" and their components are rendered into the DOM, nested in the same
272
+ * order as they are in the tree.
273
+ *
274
+ * The preferred way to configure a router is using JSX. The XML-like syntax is
275
+ * a great way to visualize how routes are laid out in an application.
276
+ *
277
+ * var routes = [
278
+ * <Route handler={App}>
279
+ * <Route name="login" handler={Login}/>
280
+ * <Route name="logout" handler={Logout}/>
281
+ * <Route name="about" handler={About}/>
282
+ * </Route>
283
+ * ];
284
+ *
285
+ * Router.run(routes, function (Handler) {
286
+ * React.render(<Handler/>, document.body);
287
+ * });
288
+ *
289
+ * Handlers for Route components that contain children can render their active
290
+ * child route using a <RouteHandler> element.
291
+ *
292
+ * var App = React.createClass({
293
+ * render: function () {
294
+ * return (
295
+ * <div class="application">
296
+ * <RouteHandler/>
297
+ * </div>
298
+ * );
299
+ * }
300
+ * });
301
+ */
302
+ var Route = React.createClass({
303
+
304
+ displayName: 'Route',
305
+
306
+ mixins: [ FakeNode ],
307
+
308
+ propTypes: {
309
+ name: React.PropTypes.string,
310
+ path: React.PropTypes.string,
311
+ handler: React.PropTypes.func.isRequired,
312
+ ignoreScrollBehavior: React.PropTypes.bool
313
+ }
314
+
315
+ });
316
+
317
+ module.exports = Route;
318
+
319
+ },{"../mixins/FakeNode":14}],9:[function(_dereq_,module,exports){
320
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
321
+ var RouteHandlerMixin = _dereq_('../mixins/RouteHandler');
322
+
323
+ /**
324
+ * A <RouteHandler> component renders the active child route handler
325
+ * when routes are nested.
326
+ */
327
+ var RouteHandler = React.createClass({
328
+
329
+ displayName: 'RouteHandler',
330
+
331
+ mixins: [RouteHandlerMixin],
332
+
333
+ getDefaultProps: function () {
334
+ return {
335
+ ref: '__routeHandler__'
336
+ };
337
+ },
338
+
339
+ render: function () {
340
+ return this.getRouteHandler();
341
+ }
342
+
343
+ });
344
+
345
+ module.exports = RouteHandler;
346
+
347
+ },{"../mixins/RouteHandler":17}],10:[function(_dereq_,module,exports){
348
+ exports.DefaultRoute = _dereq_('./components/DefaultRoute');
349
+ exports.Link = _dereq_('./components/Link');
350
+ exports.NotFoundRoute = _dereq_('./components/NotFoundRoute');
351
+ exports.Redirect = _dereq_('./components/Redirect');
352
+ exports.Route = _dereq_('./components/Route');
353
+ exports.RouteHandler = _dereq_('./components/RouteHandler');
354
+
355
+ exports.HashLocation = _dereq_('./locations/HashLocation');
356
+ exports.HistoryLocation = _dereq_('./locations/HistoryLocation');
357
+ exports.RefreshLocation = _dereq_('./locations/RefreshLocation');
358
+
359
+ exports.ImitateBrowserBehavior = _dereq_('./behaviors/ImitateBrowserBehavior');
360
+ exports.ScrollToTopBehavior = _dereq_('./behaviors/ScrollToTopBehavior');
361
+
362
+ exports.Navigation = _dereq_('./mixins/Navigation');
363
+ exports.State = _dereq_('./mixins/State');
364
+
365
+ exports.create = _dereq_('./utils/createRouter');
366
+ exports.run = _dereq_('./utils/runRouter');
367
+
368
+ exports.History = _dereq_('./utils/History');
369
+
370
+ },{"./behaviors/ImitateBrowserBehavior":2,"./behaviors/ScrollToTopBehavior":3,"./components/DefaultRoute":4,"./components/Link":5,"./components/NotFoundRoute":6,"./components/Redirect":7,"./components/Route":8,"./components/RouteHandler":9,"./locations/HashLocation":11,"./locations/HistoryLocation":12,"./locations/RefreshLocation":13,"./mixins/Navigation":15,"./mixins/State":19,"./utils/History":22,"./utils/createRouter":28,"./utils/runRouter":32}],11:[function(_dereq_,module,exports){
371
+ var LocationActions = _dereq_('../actions/LocationActions');
372
+ var History = _dereq_('../utils/History');
373
+ var Path = _dereq_('../utils/Path');
374
+
375
+ /**
376
+ * Returns the current URL path from the `hash` portion of the URL, including
377
+ * query string.
378
+ */
379
+ function getHashPath() {
380
+ return Path.decode(
381
+ // We can't use window.location.hash here because it's not
382
+ // consistent across browsers - Firefox will pre-decode it!
383
+ window.location.href.split('#')[1] || ''
384
+ );
385
+ }
386
+
387
+ var _actionType;
388
+
389
+ function ensureSlash() {
390
+ var path = getHashPath();
391
+
392
+ if (path.charAt(0) === '/')
393
+ return true;
394
+
395
+ HashLocation.replace('/' + path);
396
+
397
+ return false;
398
+ }
399
+
400
+ var _changeListeners = [];
401
+
402
+ function notifyChange(type) {
403
+ if (type === LocationActions.PUSH)
404
+ History.length += 1;
405
+
406
+ var change = {
407
+ path: getHashPath(),
408
+ type: type
409
+ };
410
+
411
+ _changeListeners.forEach(function (listener) {
412
+ listener(change);
413
+ });
414
+ }
415
+
416
+ var _isListening = false;
417
+
418
+ function onHashChange() {
419
+ if (ensureSlash()) {
420
+ // If we don't have an _actionType then all we know is the hash
421
+ // changed. It was probably caused by the user clicking the Back
422
+ // button, but may have also been the Forward button or manual
423
+ // manipulation. So just guess 'pop'.
424
+ notifyChange(_actionType || LocationActions.POP);
425
+ _actionType = null;
426
+ }
427
+ }
428
+
429
+ /**
430
+ * A Location that uses `window.location.hash`.
431
+ */
432
+ var HashLocation = {
433
+
434
+ addChangeListener: function (listener) {
435
+ _changeListeners.push(listener);
436
+
437
+ // Do this BEFORE listening for hashchange.
438
+ ensureSlash();
439
+
440
+ if (_isListening)
441
+ return;
442
+
443
+ if (window.addEventListener) {
444
+ window.addEventListener('hashchange', onHashChange, false);
445
+ } else {
446
+ window.attachEvent('onhashchange', onHashChange);
447
+ }
448
+
449
+ _isListening = true;
450
+ },
451
+
452
+ removeChangeListener: function(listener) {
453
+ for (var i = 0, l = _changeListeners.length; i < l; i ++) {
454
+ if (_changeListeners[i] === listener) {
455
+ _changeListeners.splice(i, 1);
456
+ break;
457
+ }
458
+ }
459
+
460
+ if (window.removeEventListener) {
461
+ window.removeEventListener('hashchange', onHashChange, false);
462
+ } else {
463
+ window.removeEvent('onhashchange', onHashChange);
464
+ }
465
+
466
+ if (_changeListeners.length === 0)
467
+ _isListening = false;
468
+ },
469
+
470
+
471
+
472
+ push: function (path) {
473
+ _actionType = LocationActions.PUSH;
474
+ window.location.hash = Path.encode(path);
475
+ },
476
+
477
+ replace: function (path) {
478
+ _actionType = LocationActions.REPLACE;
479
+ window.location.replace(window.location.pathname + '#' + Path.encode(path));
480
+ },
481
+
482
+ pop: function () {
483
+ _actionType = LocationActions.POP;
484
+ History.back();
485
+ },
486
+
487
+ getCurrentPath: getHashPath,
488
+
489
+ toString: function () {
490
+ return '<HashLocation>';
491
+ }
492
+
493
+ };
494
+
495
+ module.exports = HashLocation;
496
+
497
+ },{"../actions/LocationActions":1,"../utils/History":22,"../utils/Path":23}],12:[function(_dereq_,module,exports){
498
+ var LocationActions = _dereq_('../actions/LocationActions');
499
+ var History = _dereq_('../utils/History');
500
+ var Path = _dereq_('../utils/Path');
501
+
502
+ /**
503
+ * Returns the current URL path from `window.location`, including query string.
504
+ */
505
+ function getWindowPath() {
506
+ return Path.decode(
507
+ window.location.pathname + window.location.search
508
+ );
509
+ }
510
+
511
+ var _changeListeners = [];
512
+
513
+ function notifyChange(type) {
514
+ var change = {
515
+ path: getWindowPath(),
516
+ type: type
517
+ };
518
+
519
+ _changeListeners.forEach(function (listener) {
520
+ listener(change);
521
+ });
522
+ }
523
+
524
+ var _isListening = false;
525
+
526
+ function onPopState() {
527
+ notifyChange(LocationActions.POP);
528
+ }
529
+
530
+ /**
531
+ * A Location that uses HTML5 history.
532
+ */
533
+ var HistoryLocation = {
534
+
535
+ addChangeListener: function (listener) {
536
+ _changeListeners.push(listener);
537
+
538
+ if (_isListening)
539
+ return;
540
+
541
+ if (window.addEventListener) {
542
+ window.addEventListener('popstate', onPopState, false);
543
+ } else {
544
+ window.attachEvent('popstate', onPopState);
545
+ }
546
+
547
+ _isListening = true;
548
+ },
549
+
550
+ removeChangeListener: function(listener) {
551
+ for (var i = 0, l = _changeListeners.length; i < l; i ++) {
552
+ if (_changeListeners[i] === listener) {
553
+ _changeListeners.splice(i, 1);
554
+ break;
555
+ }
556
+ }
557
+
558
+ if (window.addEventListener) {
559
+ window.removeEventListener('popstate', onPopState);
560
+ } else {
561
+ window.removeEvent('popstate', onPopState);
562
+ }
563
+
564
+ if (_changeListeners.length === 0)
565
+ _isListening = false;
566
+ },
567
+
568
+
569
+
570
+ push: function (path) {
571
+ window.history.pushState({ path: path }, '', Path.encode(path));
572
+ History.length += 1;
573
+ notifyChange(LocationActions.PUSH);
574
+ },
575
+
576
+ replace: function (path) {
577
+ window.history.replaceState({ path: path }, '', Path.encode(path));
578
+ notifyChange(LocationActions.REPLACE);
579
+ },
580
+
581
+ pop: History.back,
582
+
583
+ getCurrentPath: getWindowPath,
584
+
585
+ toString: function () {
586
+ return '<HistoryLocation>';
587
+ }
588
+
589
+ };
590
+
591
+ module.exports = HistoryLocation;
592
+
593
+ },{"../actions/LocationActions":1,"../utils/History":22,"../utils/Path":23}],13:[function(_dereq_,module,exports){
594
+ var HistoryLocation = _dereq_('./HistoryLocation');
595
+ var History = _dereq_('../utils/History');
596
+ var Path = _dereq_('../utils/Path');
597
+
598
+ /**
599
+ * A Location that uses full page refreshes. This is used as
600
+ * the fallback for HistoryLocation in browsers that do not
601
+ * support the HTML5 history API.
602
+ */
603
+ var RefreshLocation = {
604
+
605
+ push: function (path) {
606
+ window.location = Path.encode(path);
607
+ },
608
+
609
+ replace: function (path) {
610
+ window.location.replace(Path.encode(path));
611
+ },
612
+
613
+ pop: History.back,
614
+
615
+ getCurrentPath: HistoryLocation.getCurrentPath,
616
+
617
+ toString: function () {
618
+ return '<RefreshLocation>';
619
+ }
620
+
621
+ };
622
+
623
+ module.exports = RefreshLocation;
624
+
625
+ },{"../utils/History":22,"../utils/Path":23,"./HistoryLocation":12}],14:[function(_dereq_,module,exports){
626
+ var invariant = _dereq_('react/lib/invariant');
627
+
628
+ var FakeNode = {
629
+
630
+ render: function () {
631
+ invariant(
632
+ false,
633
+ '%s elements should not be rendered',
634
+ this.constructor.displayName
635
+ );
636
+ }
637
+
638
+ };
639
+
640
+ module.exports = FakeNode;
641
+
642
+ },{"react/lib/invariant":43}],15:[function(_dereq_,module,exports){
643
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
644
+
645
+ /**
646
+ * A mixin for components that modify the URL.
647
+ *
648
+ * Example:
649
+ *
650
+ * var MyLink = React.createClass({
651
+ * mixins: [ Router.Navigation ],
652
+ * handleClick: function (event) {
653
+ * event.preventDefault();
654
+ * this.transitionTo('aRoute', { the: 'params' }, { the: 'query' });
655
+ * },
656
+ * render: function () {
657
+ * return (
658
+ * <a onClick={this.handleClick}>Click me!</a>
659
+ * );
660
+ * }
661
+ * });
662
+ */
663
+ var Navigation = {
664
+
665
+ contextTypes: {
666
+ makePath: React.PropTypes.func.isRequired,
667
+ makeHref: React.PropTypes.func.isRequired,
668
+ transitionTo: React.PropTypes.func.isRequired,
669
+ replaceWith: React.PropTypes.func.isRequired,
670
+ goBack: React.PropTypes.func.isRequired
671
+ },
672
+
673
+ /**
674
+ * Returns an absolute URL path created from the given route
675
+ * name, URL parameters, and query values.
676
+ */
677
+ makePath: function (to, params, query) {
678
+ return this.context.makePath(to, params, query);
679
+ },
680
+
681
+ /**
682
+ * Returns a string that may safely be used as the href of a
683
+ * link to the route with the given name.
684
+ */
685
+ makeHref: function (to, params, query) {
686
+ return this.context.makeHref(to, params, query);
687
+ },
688
+
689
+ /**
690
+ * Transitions to the URL specified in the arguments by pushing
691
+ * a new URL onto the history stack.
692
+ */
693
+ transitionTo: function (to, params, query) {
694
+ this.context.transitionTo(to, params, query);
695
+ },
696
+
697
+ /**
698
+ * Transitions to the URL specified in the arguments by replacing
699
+ * the current URL in the history stack.
700
+ */
701
+ replaceWith: function (to, params, query) {
702
+ this.context.replaceWith(to, params, query);
703
+ },
704
+
705
+ /**
706
+ * Transitions to the previous URL.
707
+ */
708
+ goBack: function () {
709
+ this.context.goBack();
710
+ }
711
+
712
+ };
713
+
714
+ module.exports = Navigation;
715
+
716
+ },{}],16:[function(_dereq_,module,exports){
717
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
718
+
719
+ /**
720
+ * Provides the router with context for Router.Navigation.
721
+ */
722
+ var NavigationContext = {
723
+
724
+ childContextTypes: {
725
+ makePath: React.PropTypes.func.isRequired,
726
+ makeHref: React.PropTypes.func.isRequired,
727
+ transitionTo: React.PropTypes.func.isRequired,
728
+ replaceWith: React.PropTypes.func.isRequired,
729
+ goBack: React.PropTypes.func.isRequired
730
+ },
731
+
732
+ getChildContext: function () {
733
+ return {
734
+ makePath: this.constructor.makePath,
735
+ makeHref: this.constructor.makeHref,
736
+ transitionTo: this.constructor.transitionTo,
737
+ replaceWith: this.constructor.replaceWith,
738
+ goBack: this.constructor.goBack
739
+ };
740
+ }
741
+
742
+ };
743
+
744
+ module.exports = NavigationContext;
745
+
746
+ },{}],17:[function(_dereq_,module,exports){
747
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
748
+
749
+ module.exports = {
750
+ contextTypes: {
751
+ getRouteAtDepth: React.PropTypes.func.isRequired,
752
+ getRouteComponents: React.PropTypes.func.isRequired,
753
+ routeHandlers: React.PropTypes.array.isRequired
754
+ },
755
+
756
+ childContextTypes: {
757
+ routeHandlers: React.PropTypes.array.isRequired
758
+ },
759
+
760
+ getChildContext: function () {
761
+ return {
762
+ routeHandlers: this.context.routeHandlers.concat([ this ])
763
+ };
764
+ },
765
+
766
+ getRouteDepth: function () {
767
+ return this.context.routeHandlers.length - 1;
768
+ },
769
+
770
+ componentDidMount: function () {
771
+ this._updateRouteComponent();
772
+ },
773
+
774
+ componentDidUpdate: function () {
775
+ this._updateRouteComponent();
776
+ },
777
+
778
+ _updateRouteComponent: function () {
779
+ var depth = this.getRouteDepth();
780
+ var components = this.context.getRouteComponents();
781
+ components[depth] = this.refs[this.props.ref || '__routeHandler__'];
782
+ },
783
+
784
+ getRouteHandler: function (props) {
785
+ var route = this.context.getRouteAtDepth(this.getRouteDepth());
786
+ return route ? React.createElement(route.handler, props || this.props) : null;
787
+ }
788
+ };
789
+ },{}],18:[function(_dereq_,module,exports){
790
+ var invariant = _dereq_('react/lib/invariant');
791
+ var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM;
792
+ var getWindowScrollPosition = _dereq_('../utils/getWindowScrollPosition');
793
+
794
+ function shouldUpdateScroll(state, prevState) {
795
+ if (!prevState)
796
+ return true;
797
+
798
+ // Don't update scroll position when only the query has changed.
799
+ if (state.pathname === prevState.pathname)
800
+ return false;
801
+
802
+ var routes = state.routes;
803
+ var prevRoutes = prevState.routes;
804
+
805
+ var sharedAncestorRoutes = routes.filter(function (route) {
806
+ return prevRoutes.indexOf(route) !== -1;
807
+ });
808
+
809
+ return !sharedAncestorRoutes.some(function (route) {
810
+ return route.ignoreScrollBehavior;
811
+ });
812
+ }
813
+
814
+ /**
815
+ * Provides the router with the ability to manage window scroll position
816
+ * according to its scroll behavior.
817
+ */
818
+ var Scrolling = {
819
+
820
+ statics: {
821
+ /**
822
+ * Records curent scroll position as the last known position for the given URL path.
823
+ */
824
+ recordScrollPosition: function (path) {
825
+ if (!this.scrollHistory)
826
+ this.scrollHistory = {};
827
+
828
+ this.scrollHistory[path] = getWindowScrollPosition();
829
+ },
830
+
831
+ /**
832
+ * Returns the last known scroll position for the given URL path.
833
+ */
834
+ getScrollPosition: function (path) {
835
+ if (!this.scrollHistory)
836
+ this.scrollHistory = {};
837
+
838
+ return this.scrollHistory[path] || null;
839
+ }
840
+ },
841
+
842
+ componentWillMount: function () {
843
+ invariant(
844
+ this.getScrollBehavior() == null || canUseDOM,
845
+ 'Cannot use scroll behavior without a DOM'
846
+ );
847
+ },
848
+
849
+ componentDidMount: function () {
850
+ this._updateScroll();
851
+ },
852
+
853
+ componentDidUpdate: function (prevProps, prevState) {
854
+ this._updateScroll(prevState);
855
+ },
856
+
857
+ _updateScroll: function (prevState) {
858
+ if (!shouldUpdateScroll(this.state, prevState))
859
+ return;
860
+
861
+ var scrollBehavior = this.getScrollBehavior();
862
+
863
+ if (scrollBehavior)
864
+ scrollBehavior.updateScrollPosition(
865
+ this.constructor.getScrollPosition(this.state.path),
866
+ this.state.action
867
+ );
868
+ }
869
+
870
+ };
871
+
872
+ module.exports = Scrolling;
873
+
874
+ },{"../utils/getWindowScrollPosition":30,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":43}],19:[function(_dereq_,module,exports){
875
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
876
+
877
+ /**
878
+ * A mixin for components that need to know the path, routes, URL
879
+ * params and query that are currently active.
880
+ *
881
+ * Example:
882
+ *
883
+ * var AboutLink = React.createClass({
884
+ * mixins: [ Router.State ],
885
+ * render: function () {
886
+ * var className = this.props.className;
887
+ *
888
+ * if (this.isActive('about'))
889
+ * className += ' is-active';
890
+ *
891
+ * return React.DOM.a({ className: className }, this.props.children);
892
+ * }
893
+ * });
894
+ */
895
+ var State = {
896
+
897
+ contextTypes: {
898
+ getCurrentPath: React.PropTypes.func.isRequired,
899
+ getCurrentRoutes: React.PropTypes.func.isRequired,
900
+ getCurrentPathname: React.PropTypes.func.isRequired,
901
+ getCurrentParams: React.PropTypes.func.isRequired,
902
+ getCurrentQuery: React.PropTypes.func.isRequired,
903
+ isActive: React.PropTypes.func.isRequired
904
+ },
905
+
906
+ /**
907
+ * Returns the current URL path.
908
+ */
909
+ getPath: function () {
910
+ return this.context.getCurrentPath();
911
+ },
912
+
913
+ /**
914
+ * Returns an array of the routes that are currently active.
915
+ */
916
+ getRoutes: function () {
917
+ return this.context.getCurrentRoutes();
918
+ },
919
+
920
+ /**
921
+ * Returns the current URL path without the query string.
922
+ */
923
+ getPathname: function () {
924
+ return this.context.getCurrentPathname();
925
+ },
926
+
927
+ /**
928
+ * Returns an object of the URL params that are currently active.
929
+ */
930
+ getParams: function () {
931
+ return this.context.getCurrentParams();
932
+ },
933
+
934
+ /**
935
+ * Returns an object of the query params that are currently active.
936
+ */
937
+ getQuery: function () {
938
+ return this.context.getCurrentQuery();
939
+ },
940
+
941
+ /**
942
+ * A helper method to determine if a given route, params, and query
943
+ * are active.
944
+ */
945
+ isActive: function (to, params, query) {
946
+ return this.context.isActive(to, params, query);
947
+ }
948
+
949
+ };
950
+
951
+ module.exports = State;
952
+
953
+ },{}],20:[function(_dereq_,module,exports){
954
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
955
+ var assign = _dereq_('react/lib/Object.assign');
956
+ var Path = _dereq_('../utils/Path');
957
+
958
+ function routeIsActive(activeRoutes, routeName) {
959
+ return activeRoutes.some(function (route) {
960
+ return route.name === routeName;
961
+ });
962
+ }
963
+
964
+ function paramsAreActive(activeParams, params) {
965
+ for (var property in params)
966
+ if (String(activeParams[property]) !== String(params[property]))
967
+ return false;
968
+
969
+ return true;
970
+ }
971
+
972
+ function queryIsActive(activeQuery, query) {
973
+ for (var property in query)
974
+ if (String(activeQuery[property]) !== String(query[property]))
975
+ return false;
976
+
977
+ return true;
978
+ }
979
+
980
+ /**
981
+ * Provides the router with context for Router.State.
982
+ */
983
+ var StateContext = {
984
+
985
+ /**
986
+ * Returns the current URL path + query string.
987
+ */
988
+ getCurrentPath: function () {
989
+ return this.state.path;
990
+ },
991
+
992
+ /**
993
+ * Returns a read-only array of the currently active routes.
994
+ */
995
+ getCurrentRoutes: function () {
996
+ return this.state.routes.slice(0);
997
+ },
998
+
999
+ /**
1000
+ * Returns the current URL path without the query string.
1001
+ */
1002
+ getCurrentPathname: function () {
1003
+ return this.state.pathname;
1004
+ },
1005
+
1006
+ /**
1007
+ * Returns a read-only object of the currently active URL parameters.
1008
+ */
1009
+ getCurrentParams: function () {
1010
+ return assign({}, this.state.params);
1011
+ },
1012
+
1013
+ /**
1014
+ * Returns a read-only object of the currently active query parameters.
1015
+ */
1016
+ getCurrentQuery: function () {
1017
+ return assign({}, this.state.query);
1018
+ },
1019
+
1020
+ /**
1021
+ * Returns true if the given route, params, and query are active.
1022
+ */
1023
+ isActive: function (to, params, query) {
1024
+ if (Path.isAbsolute(to))
1025
+ return to === this.state.path;
1026
+
1027
+ return routeIsActive(this.state.routes, to) &&
1028
+ paramsAreActive(this.state.params, params) &&
1029
+ (query == null || queryIsActive(this.state.query, query));
1030
+ },
1031
+
1032
+ childContextTypes: {
1033
+ getCurrentPath: React.PropTypes.func.isRequired,
1034
+ getCurrentRoutes: React.PropTypes.func.isRequired,
1035
+ getCurrentPathname: React.PropTypes.func.isRequired,
1036
+ getCurrentParams: React.PropTypes.func.isRequired,
1037
+ getCurrentQuery: React.PropTypes.func.isRequired,
1038
+ isActive: React.PropTypes.func.isRequired
1039
+ },
1040
+
1041
+ getChildContext: function () {
1042
+ return {
1043
+ getCurrentPath: this.getCurrentPath,
1044
+ getCurrentRoutes: this.getCurrentRoutes,
1045
+ getCurrentPathname: this.getCurrentPathname,
1046
+ getCurrentParams: this.getCurrentParams,
1047
+ getCurrentQuery: this.getCurrentQuery,
1048
+ isActive: this.isActive
1049
+ };
1050
+ }
1051
+
1052
+ };
1053
+
1054
+ module.exports = StateContext;
1055
+
1056
+ },{"../utils/Path":23,"react/lib/Object.assign":40}],21:[function(_dereq_,module,exports){
1057
+ /**
1058
+ * Represents a cancellation caused by navigating away
1059
+ * before the previous transition has fully resolved.
1060
+ */
1061
+ function Cancellation() { }
1062
+
1063
+ module.exports = Cancellation;
1064
+
1065
+ },{}],22:[function(_dereq_,module,exports){
1066
+ var invariant = _dereq_('react/lib/invariant');
1067
+ var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM;
1068
+
1069
+ var History = {
1070
+
1071
+ /**
1072
+ * Sends the browser back one entry in the history.
1073
+ */
1074
+ back: function () {
1075
+ invariant(
1076
+ canUseDOM,
1077
+ 'Cannot use History.back without a DOM'
1078
+ );
1079
+
1080
+ // Do this first so that History.length will
1081
+ // be accurate in location change listeners.
1082
+ History.length -= 1;
1083
+
1084
+ window.history.back();
1085
+ },
1086
+
1087
+ /**
1088
+ * The current number of entries in the history.
1089
+ */
1090
+ length: 1
1091
+
1092
+ };
1093
+
1094
+ module.exports = History;
1095
+
1096
+ },{"react/lib/ExecutionEnvironment":39,"react/lib/invariant":43}],23:[function(_dereq_,module,exports){
1097
+ var invariant = _dereq_('react/lib/invariant');
1098
+ var merge = _dereq_('qs/lib/utils').merge;
1099
+ var qs = _dereq_('qs');
1100
+
1101
+ var paramCompileMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$]*)|[*.()\[\]\\+|{}^$]/g;
1102
+ var paramInjectMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$?]*[?]?)|[*]/g;
1103
+ var paramInjectTrailingSlashMatcher = /\/\/\?|\/\?/g;
1104
+ var queryMatcher = /\?(.+)/;
1105
+
1106
+ var _compiledPatterns = {};
1107
+
1108
+ function compilePattern(pattern) {
1109
+ if (!(pattern in _compiledPatterns)) {
1110
+ var paramNames = [];
1111
+ var source = pattern.replace(paramCompileMatcher, function (match, paramName) {
1112
+ if (paramName) {
1113
+ paramNames.push(paramName);
1114
+ return '([^/?#]+)';
1115
+ } else if (match === '*') {
1116
+ paramNames.push('splat');
1117
+ return '(.*?)';
1118
+ } else {
1119
+ return '\\' + match;
1120
+ }
1121
+ });
1122
+
1123
+ _compiledPatterns[pattern] = {
1124
+ matcher: new RegExp('^' + source + '$', 'i'),
1125
+ paramNames: paramNames
1126
+ };
1127
+ }
1128
+
1129
+ return _compiledPatterns[pattern];
1130
+ }
1131
+
1132
+ var Path = {
1133
+
1134
+ /**
1135
+ * Safely decodes special characters in the given URL path.
1136
+ */
1137
+ decode: function (path) {
1138
+ return decodeURI(path.replace(/\+/g, ' '));
1139
+ },
1140
+
1141
+ /**
1142
+ * Safely encodes special characters in the given URL path.
1143
+ */
1144
+ encode: function (path) {
1145
+ return encodeURI(path).replace(/%20/g, '+');
1146
+ },
1147
+
1148
+ /**
1149
+ * Returns an array of the names of all parameters in the given pattern.
1150
+ */
1151
+ extractParamNames: function (pattern) {
1152
+ return compilePattern(pattern).paramNames;
1153
+ },
1154
+
1155
+ /**
1156
+ * Extracts the portions of the given URL path that match the given pattern
1157
+ * and returns an object of param name => value pairs. Returns null if the
1158
+ * pattern does not match the given path.
1159
+ */
1160
+ extractParams: function (pattern, path) {
1161
+ var object = compilePattern(pattern);
1162
+ var match = path.match(object.matcher);
1163
+
1164
+ if (!match)
1165
+ return null;
1166
+
1167
+ var params = {};
1168
+
1169
+ object.paramNames.forEach(function (paramName, index) {
1170
+ params[paramName] = match[index + 1];
1171
+ });
1172
+
1173
+ return params;
1174
+ },
1175
+
1176
+ /**
1177
+ * Returns a version of the given route path with params interpolated. Throws
1178
+ * if there is a dynamic segment of the route path for which there is no param.
1179
+ */
1180
+ injectParams: function (pattern, params) {
1181
+ params = params || {};
1182
+
1183
+ var splatIndex = 0;
1184
+
1185
+ return pattern.replace(paramInjectMatcher, function (match, paramName) {
1186
+ paramName = paramName || 'splat';
1187
+
1188
+ // If param is optional don't check for existence
1189
+ if (paramName.slice(-1) !== '?') {
1190
+ invariant(
1191
+ params[paramName] != null,
1192
+ 'Missing "' + paramName + '" parameter for path "' + pattern + '"'
1193
+ );
1194
+ } else {
1195
+ paramName = paramName.slice(0, -1);
1196
+
1197
+ if (params[paramName] == null)
1198
+ return '';
1199
+ }
1200
+
1201
+ var segment;
1202
+ if (paramName === 'splat' && Array.isArray(params[paramName])) {
1203
+ segment = params[paramName][splatIndex++];
1204
+
1205
+ invariant(
1206
+ segment != null,
1207
+ 'Missing splat # ' + splatIndex + ' for path "' + pattern + '"'
1208
+ );
1209
+ } else {
1210
+ segment = params[paramName];
1211
+ }
1212
+
1213
+ return segment;
1214
+ }).replace(paramInjectTrailingSlashMatcher, '/');
1215
+ },
1216
+
1217
+ /**
1218
+ * Returns an object that is the result of parsing any query string contained
1219
+ * in the given path, null if the path contains no query string.
1220
+ */
1221
+ extractQuery: function (path) {
1222
+ var match = path.match(queryMatcher);
1223
+ return match && qs.parse(match[1]);
1224
+ },
1225
+
1226
+ /**
1227
+ * Returns a version of the given path without the query string.
1228
+ */
1229
+ withoutQuery: function (path) {
1230
+ return path.replace(queryMatcher, '');
1231
+ },
1232
+
1233
+ /**
1234
+ * Returns a version of the given path with the parameters in the given
1235
+ * query merged into the query string.
1236
+ */
1237
+ withQuery: function (path, query) {
1238
+ var existingQuery = Path.extractQuery(path);
1239
+
1240
+ if (existingQuery)
1241
+ query = query ? merge(existingQuery, query) : existingQuery;
1242
+
1243
+ var queryString = query && qs.stringify(query);
1244
+
1245
+ if (queryString)
1246
+ return Path.withoutQuery(path) + '?' + queryString;
1247
+
1248
+ return path;
1249
+ },
1250
+
1251
+ /**
1252
+ * Returns true if the given path is absolute.
1253
+ */
1254
+ isAbsolute: function (path) {
1255
+ return path.charAt(0) === '/';
1256
+ },
1257
+
1258
+ /**
1259
+ * Returns a normalized version of the given path.
1260
+ */
1261
+ normalize: function (path, parentRoute) {
1262
+ return path.replace(/^\/*/, '/');
1263
+ },
1264
+
1265
+ /**
1266
+ * Joins two URL paths together.
1267
+ */
1268
+ join: function (a, b) {
1269
+ return a.replace(/\/*$/, '/') + b;
1270
+ }
1271
+
1272
+ };
1273
+
1274
+ module.exports = Path;
1275
+
1276
+ },{"qs":34,"qs/lib/utils":38,"react/lib/invariant":43}],24:[function(_dereq_,module,exports){
1277
+ var Promise = _dereq_('when/lib/Promise');
1278
+
1279
+ // TODO: Use process.env.NODE_ENV check + envify to enable
1280
+ // when's promise monitor here when in dev.
1281
+
1282
+ module.exports = Promise;
1283
+
1284
+ },{"when/lib/Promise":45}],25:[function(_dereq_,module,exports){
1285
+ var PropTypes = {
1286
+
1287
+ /**
1288
+ * Requires that the value of a prop be falsy.
1289
+ */
1290
+ falsy: function (props, propName, componentName) {
1291
+ if (props[propName])
1292
+ return new Error('<' + componentName + '> may not have a "' + propName + '" prop');
1293
+ }
1294
+
1295
+ };
1296
+
1297
+ module.exports = PropTypes;
1298
+
1299
+ },{}],26:[function(_dereq_,module,exports){
1300
+ /**
1301
+ * Encapsulates a redirect to the given route.
1302
+ */
1303
+ function Redirect(to, params, query) {
1304
+ this.to = to;
1305
+ this.params = params;
1306
+ this.query = query;
1307
+ }
1308
+
1309
+ module.exports = Redirect;
1310
+
1311
+ },{}],27:[function(_dereq_,module,exports){
1312
+ var assign = _dereq_('react/lib/Object.assign');
1313
+ var reversedArray = _dereq_('./reversedArray');
1314
+ var Redirect = _dereq_('./Redirect');
1315
+ var Promise = _dereq_('./Promise');
1316
+
1317
+ /**
1318
+ * Runs all hook functions serially and calls callback(error) when finished.
1319
+ * A hook may return a promise if it needs to execute asynchronously.
1320
+ */
1321
+ function runHooks(hooks, callback) {
1322
+ var promise;
1323
+ try {
1324
+ promise = hooks.reduce(function (promise, hook) {
1325
+ // The first hook to use transition.wait makes the rest
1326
+ // of the transition async from that point forward.
1327
+ return promise ? promise.then(hook) : hook();
1328
+ }, null);
1329
+ } catch (error) {
1330
+ return callback(error); // Sync error.
1331
+ }
1332
+
1333
+ if (promise) {
1334
+ // Use setTimeout to break the promise chain.
1335
+ promise.then(function () {
1336
+ setTimeout(callback);
1337
+ }, function (error) {
1338
+ setTimeout(function () {
1339
+ callback(error);
1340
+ });
1341
+ });
1342
+ } else {
1343
+ callback();
1344
+ }
1345
+ }
1346
+
1347
+ /**
1348
+ * Calls the willTransitionFrom hook of all handlers in the given matches
1349
+ * serially in reverse with the transition object and the current instance of
1350
+ * the route's handler, so that the deepest nested handlers are called first.
1351
+ * Calls callback(error) when finished.
1352
+ */
1353
+ function runTransitionFromHooks(transition, routes, components, callback) {
1354
+ components = reversedArray(components);
1355
+
1356
+ var hooks = reversedArray(routes).map(function (route, index) {
1357
+ return function () {
1358
+ var handler = route.handler;
1359
+
1360
+ if (!transition.isAborted && handler.willTransitionFrom)
1361
+ return handler.willTransitionFrom(transition, components[index]);
1362
+
1363
+ var promise = transition._promise;
1364
+ transition._promise = null;
1365
+
1366
+ return promise;
1367
+ };
1368
+ });
1369
+
1370
+ runHooks(hooks, callback);
1371
+ }
1372
+
1373
+ /**
1374
+ * Calls the willTransitionTo hook of all handlers in the given matches
1375
+ * serially with the transition object and any params that apply to that
1376
+ * handler. Calls callback(error) when finished.
1377
+ */
1378
+ function runTransitionToHooks(transition, routes, params, query, callback) {
1379
+ var hooks = routes.map(function (route) {
1380
+ return function () {
1381
+ var handler = route.handler;
1382
+
1383
+ if (!transition.isAborted && handler.willTransitionTo)
1384
+ handler.willTransitionTo(transition, params, query);
1385
+
1386
+ var promise = transition._promise;
1387
+ transition._promise = null;
1388
+
1389
+ return promise;
1390
+ };
1391
+ });
1392
+
1393
+ runHooks(hooks, callback);
1394
+ }
1395
+
1396
+ /**
1397
+ * Encapsulates a transition to a given path.
1398
+ *
1399
+ * The willTransitionTo and willTransitionFrom handlers receive
1400
+ * an instance of this class as their first argument.
1401
+ */
1402
+ function Transition(path, retry) {
1403
+ this.path = path;
1404
+ this.abortReason = null;
1405
+ this.isAborted = false;
1406
+ this.retry = retry.bind(this);
1407
+ this._promise = null;
1408
+ }
1409
+
1410
+ assign(Transition.prototype, {
1411
+
1412
+ abort: function (reason) {
1413
+ if (this.isAborted) {
1414
+ // First abort wins.
1415
+ return;
1416
+ }
1417
+
1418
+ this.abortReason = reason;
1419
+ this.isAborted = true;
1420
+ },
1421
+
1422
+ redirect: function (to, params, query) {
1423
+ this.abort(new Redirect(to, params, query));
1424
+ },
1425
+
1426
+ wait: function (value) {
1427
+ this._promise = Promise.resolve(value);
1428
+ },
1429
+
1430
+ from: function (routes, components, callback) {
1431
+ return runTransitionFromHooks(this, routes, components, callback);
1432
+ },
1433
+
1434
+ to: function (routes, params, query, callback) {
1435
+ return runTransitionToHooks(this, routes, params, query, callback);
1436
+ }
1437
+
1438
+ });
1439
+
1440
+ module.exports = Transition;
1441
+
1442
+ },{"./Promise":24,"./Redirect":26,"./reversedArray":31,"react/lib/Object.assign":40}],28:[function(_dereq_,module,exports){
1443
+ /* jshint -W058 */
1444
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
1445
+ var warning = _dereq_('react/lib/warning');
1446
+ var invariant = _dereq_('react/lib/invariant');
1447
+ var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM;
1448
+ var ImitateBrowserBehavior = _dereq_('../behaviors/ImitateBrowserBehavior');
1449
+ var RouteHandler = _dereq_('../components/RouteHandler');
1450
+ var LocationActions = _dereq_('../actions/LocationActions');
1451
+ var HashLocation = _dereq_('../locations/HashLocation');
1452
+ var HistoryLocation = _dereq_('../locations/HistoryLocation');
1453
+ var RefreshLocation = _dereq_('../locations/RefreshLocation');
1454
+ var NavigationContext = _dereq_('../mixins/NavigationContext');
1455
+ var StateContext = _dereq_('../mixins/StateContext');
1456
+ var Scrolling = _dereq_('../mixins/Scrolling');
1457
+ var createRoutesFromChildren = _dereq_('./createRoutesFromChildren');
1458
+ var supportsHistory = _dereq_('./supportsHistory');
1459
+ var Transition = _dereq_('./Transition');
1460
+ var PropTypes = _dereq_('./PropTypes');
1461
+ var Redirect = _dereq_('./Redirect');
1462
+ var History = _dereq_('./History');
1463
+ var Cancellation = _dereq_('./Cancellation');
1464
+ var Path = _dereq_('./Path');
1465
+
1466
+ /**
1467
+ * The default location for new routers.
1468
+ */
1469
+ var DEFAULT_LOCATION = canUseDOM ? HashLocation : '/';
1470
+
1471
+ /**
1472
+ * The default scroll behavior for new routers.
1473
+ */
1474
+ var DEFAULT_SCROLL_BEHAVIOR = canUseDOM ? ImitateBrowserBehavior : null;
1475
+
1476
+ /**
1477
+ * The default error handler for new routers.
1478
+ */
1479
+ function defaultErrorHandler(error) {
1480
+ // Throw so we don't silently swallow async errors.
1481
+ throw error; // This error probably originated in a transition hook.
1482
+ }
1483
+
1484
+ /**
1485
+ * The default aborted transition handler for new routers.
1486
+ */
1487
+ function defaultAbortHandler(abortReason, location) {
1488
+ if (typeof location === 'string')
1489
+ throw new Error('Unhandled aborted transition! Reason: ' + abortReason);
1490
+
1491
+ if (abortReason instanceof Cancellation) {
1492
+ return;
1493
+ } else if (abortReason instanceof Redirect) {
1494
+ location.replace(this.makePath(abortReason.to, abortReason.params, abortReason.query));
1495
+ } else {
1496
+ location.pop();
1497
+ }
1498
+ }
1499
+
1500
+ function findMatch(pathname, routes, defaultRoute, notFoundRoute) {
1501
+ var match, route, params;
1502
+
1503
+ for (var i = 0, len = routes.length; i < len; ++i) {
1504
+ route = routes[i];
1505
+
1506
+ // Check the subtree first to find the most deeply-nested match.
1507
+ match = findMatch(pathname, route.childRoutes, route.defaultRoute, route.notFoundRoute);
1508
+
1509
+ if (match != null) {
1510
+ match.routes.unshift(route);
1511
+ return match;
1512
+ }
1513
+
1514
+ // No routes in the subtree matched, so check this route.
1515
+ params = Path.extractParams(route.path, pathname);
1516
+
1517
+ if (params)
1518
+ return createMatch(route, params);
1519
+ }
1520
+
1521
+ // No routes matched, so try the default route if there is one.
1522
+ if (defaultRoute && (params = Path.extractParams(defaultRoute.path, pathname)))
1523
+ return createMatch(defaultRoute, params);
1524
+
1525
+ // Last attempt: does the "not found" route match?
1526
+ if (notFoundRoute && (params = Path.extractParams(notFoundRoute.path, pathname)))
1527
+ return createMatch(notFoundRoute, params);
1528
+
1529
+ return match;
1530
+ }
1531
+
1532
+ function createMatch(route, params) {
1533
+ return { routes: [ route ], params: params };
1534
+ }
1535
+
1536
+ function hasProperties(object, properties) {
1537
+ for (var propertyName in properties)
1538
+ if (properties.hasOwnProperty(propertyName) && object[propertyName] !== properties[propertyName])
1539
+ return false;
1540
+
1541
+ return true;
1542
+ }
1543
+
1544
+ function hasMatch(routes, route, prevParams, nextParams, prevQuery, nextQuery) {
1545
+ return routes.some(function (r) {
1546
+ if (r !== route)
1547
+ return false;
1548
+
1549
+ var paramNames = route.paramNames;
1550
+ var paramName;
1551
+
1552
+ // Ensure that all params the route cares about did not change.
1553
+ for (var i = 0, len = paramNames.length; i < len; ++i) {
1554
+ paramName = paramNames[i];
1555
+
1556
+ if (nextParams[paramName] !== prevParams[paramName])
1557
+ return false;
1558
+ }
1559
+
1560
+ // Ensure the query hasn't changed.
1561
+ return hasProperties(prevQuery, nextQuery) && hasProperties(nextQuery, prevQuery);
1562
+ });
1563
+ }
1564
+
1565
+ /**
1566
+ * Creates and returns a new router using the given options. A router
1567
+ * is a ReactComponent class that knows how to react to changes in the
1568
+ * URL and keep the contents of the page in sync.
1569
+ *
1570
+ * Options may be any of the following:
1571
+ *
1572
+ * - routes (required) The route config
1573
+ * - location The location to use. Defaults to HashLocation when
1574
+ * the DOM is available, "/" otherwise
1575
+ * - scrollBehavior The scroll behavior to use. Defaults to ImitateBrowserBehavior
1576
+ * when the DOM is available, null otherwise
1577
+ * - onError A function that is used to handle errors
1578
+ * - onAbort A function that is used to handle aborted transitions
1579
+ *
1580
+ * When rendering in a server-side environment, the location should simply
1581
+ * be the URL path that was used in the request, including the query string.
1582
+ */
1583
+ function createRouter(options) {
1584
+ options = options || {};
1585
+
1586
+ if (typeof options === 'function') {
1587
+ options = { routes: options }; // Router.create(<Route>)
1588
+ } else if (Array.isArray(options)) {
1589
+ options = { routes: options }; // Router.create([ <Route>, <Route> ])
1590
+ }
1591
+
1592
+ var routes = [];
1593
+ var namedRoutes = {};
1594
+ var components = [];
1595
+ var location = options.location || DEFAULT_LOCATION;
1596
+ var scrollBehavior = options.scrollBehavior || DEFAULT_SCROLL_BEHAVIOR;
1597
+ var onError = options.onError || defaultErrorHandler;
1598
+ var onAbort = options.onAbort || defaultAbortHandler;
1599
+ var state = {};
1600
+ var nextState = {};
1601
+ var pendingTransition = null;
1602
+
1603
+ function updateState() {
1604
+ state = nextState;
1605
+ nextState = {};
1606
+ }
1607
+
1608
+ if (typeof location === 'string') {
1609
+ warning(
1610
+ !canUseDOM || "production" === 'test',
1611
+ 'You should not use a static location in a DOM environment because ' +
1612
+ 'the router will not be kept in sync with the current URL'
1613
+ );
1614
+ } else {
1615
+ invariant(
1616
+ canUseDOM,
1617
+ 'You cannot use %s without a DOM',
1618
+ location
1619
+ );
1620
+ }
1621
+
1622
+ // Automatically fall back to full page refreshes in
1623
+ // browsers that don't support the HTML history API.
1624
+ if (location === HistoryLocation && !supportsHistory())
1625
+ location = RefreshLocation;
1626
+
1627
+ var router = React.createClass({
1628
+
1629
+ displayName: 'Router',
1630
+
1631
+ mixins: [ NavigationContext, StateContext, Scrolling ],
1632
+
1633
+ statics: {
1634
+
1635
+ defaultRoute: null,
1636
+ notFoundRoute: null,
1637
+
1638
+ /**
1639
+ * Adds routes to this router from the given children object (see ReactChildren).
1640
+ */
1641
+ addRoutes: function (children) {
1642
+ routes.push.apply(routes, createRoutesFromChildren(children, this, namedRoutes));
1643
+ },
1644
+
1645
+ /**
1646
+ * Returns an absolute URL path created from the given route
1647
+ * name, URL parameters, and query.
1648
+ */
1649
+ makePath: function (to, params, query) {
1650
+ var path;
1651
+ if (Path.isAbsolute(to)) {
1652
+ path = Path.normalize(to);
1653
+ } else {
1654
+ var route = namedRoutes[to];
1655
+
1656
+ invariant(
1657
+ route,
1658
+ 'Unable to find <Route name="%s">',
1659
+ to
1660
+ );
1661
+
1662
+ path = route.path;
1663
+ }
1664
+
1665
+ return Path.withQuery(Path.injectParams(path, params), query);
1666
+ },
1667
+
1668
+ /**
1669
+ * Returns a string that may safely be used as the href of a link
1670
+ * to the route with the given name, URL parameters, and query.
1671
+ */
1672
+ makeHref: function (to, params, query) {
1673
+ var path = this.makePath(to, params, query);
1674
+ return (location === HashLocation) ? '#' + path : path;
1675
+ },
1676
+
1677
+ /**
1678
+ * Transitions to the URL specified in the arguments by pushing
1679
+ * a new URL onto the history stack.
1680
+ */
1681
+ transitionTo: function (to, params, query) {
1682
+ invariant(
1683
+ typeof location !== 'string',
1684
+ 'You cannot use transitionTo with a static location'
1685
+ );
1686
+
1687
+ var path = this.makePath(to, params, query);
1688
+
1689
+ if (pendingTransition) {
1690
+ // Replace so pending location does not stay in history.
1691
+ location.replace(path);
1692
+ } else {
1693
+ location.push(path);
1694
+ }
1695
+ },
1696
+
1697
+ /**
1698
+ * Transitions to the URL specified in the arguments by replacing
1699
+ * the current URL in the history stack.
1700
+ */
1701
+ replaceWith: function (to, params, query) {
1702
+ invariant(
1703
+ typeof location !== 'string',
1704
+ 'You cannot use replaceWith with a static location'
1705
+ );
1706
+
1707
+ location.replace(this.makePath(to, params, query));
1708
+ },
1709
+
1710
+ /**
1711
+ * Transitions to the previous URL if one is available. Returns true if the
1712
+ * router was able to go back, false otherwise.
1713
+ *
1714
+ * Note: The router only tracks history entries in your application, not the
1715
+ * current browser session, so you can safely call this function without guarding
1716
+ * against sending the user back to some other site. However, when using
1717
+ * RefreshLocation (which is the fallback for HistoryLocation in browsers that
1718
+ * don't support HTML5 history) this method will *always* send the client back
1719
+ * because we cannot reliably track history length.
1720
+ */
1721
+ goBack: function () {
1722
+ invariant(
1723
+ typeof location !== 'string',
1724
+ 'You cannot use goBack with a static location'
1725
+ );
1726
+
1727
+ if (History.length > 1 || location === RefreshLocation) {
1728
+ location.pop();
1729
+ return true;
1730
+ }
1731
+
1732
+ warning(false, 'goBack() was ignored because there is no router history');
1733
+
1734
+ return false;
1735
+ },
1736
+
1737
+ /**
1738
+ * Performs a match of the given pathname against this router and returns an object
1739
+ * with the { routes, params } that match. Returns null if no match can be made.
1740
+ */
1741
+ match: function (pathname) {
1742
+ return findMatch(pathname, routes, this.defaultRoute, this.notFoundRoute) || null;
1743
+ },
1744
+
1745
+ /**
1746
+ * Performs a transition to the given path and calls callback(error, abortReason)
1747
+ * when the transition is finished. If both arguments are null the router's state
1748
+ * was updated. Otherwise the transition did not complete.
1749
+ *
1750
+ * In a transition, a router first determines which routes are involved by beginning
1751
+ * with the current route, up the route tree to the first parent route that is shared
1752
+ * with the destination route, and back down the tree to the destination route. The
1753
+ * willTransitionFrom hook is invoked on all route handlers we're transitioning away
1754
+ * from, in reverse nesting order. Likewise, the willTransitionTo hook is invoked on
1755
+ * all route handlers we're transitioning to.
1756
+ *
1757
+ * Both willTransitionFrom and willTransitionTo hooks may either abort or redirect the
1758
+ * transition. To resolve asynchronously, they may use transition.wait(promise). If no
1759
+ * hooks wait, the transition is fully synchronous.
1760
+ */
1761
+ dispatch: function (path, action, callback) {
1762
+ if (pendingTransition) {
1763
+ pendingTransition.abort(new Cancellation);
1764
+ pendingTransition = null;
1765
+ }
1766
+
1767
+ var prevPath = state.path;
1768
+ if (prevPath === path)
1769
+ return; // Nothing to do!
1770
+
1771
+ // Record the scroll position as early as possible to
1772
+ // get it before browsers try update it automatically.
1773
+ if (prevPath && action !== LocationActions.REPLACE)
1774
+ this.recordScrollPosition(prevPath);
1775
+
1776
+ var pathname = Path.withoutQuery(path);
1777
+ var match = this.match(pathname);
1778
+
1779
+ warning(
1780
+ match != null,
1781
+ 'No route matches path "%s". Make sure you have <Route path="%s"> somewhere in your routes',
1782
+ path, path
1783
+ );
1784
+
1785
+ if (match == null)
1786
+ match = {};
1787
+
1788
+ var prevRoutes = state.routes || [];
1789
+ var prevParams = state.params || {};
1790
+ var prevQuery = state.query || {};
1791
+
1792
+ var nextRoutes = match.routes || [];
1793
+ var nextParams = match.params || {};
1794
+ var nextQuery = Path.extractQuery(path) || {};
1795
+
1796
+ var fromRoutes, toRoutes;
1797
+ if (prevRoutes.length) {
1798
+ fromRoutes = prevRoutes.filter(function (route) {
1799
+ return !hasMatch(nextRoutes, route, prevParams, nextParams, prevQuery, nextQuery);
1800
+ });
1801
+
1802
+ toRoutes = nextRoutes.filter(function (route) {
1803
+ return !hasMatch(prevRoutes, route, prevParams, nextParams, prevQuery, nextQuery);
1804
+ });
1805
+ } else {
1806
+ fromRoutes = [];
1807
+ toRoutes = nextRoutes;
1808
+ }
1809
+
1810
+ var transition = new Transition(path, this.replaceWith.bind(this, path));
1811
+ pendingTransition = transition;
1812
+
1813
+ transition.from(fromRoutes, components, function (error) {
1814
+ if (error || transition.isAborted)
1815
+ return callback.call(router, error, transition);
1816
+
1817
+ transition.to(toRoutes, nextParams, nextQuery, function (error) {
1818
+ if (error || transition.isAborted)
1819
+ return callback.call(router, error, transition);
1820
+
1821
+ nextState.path = path;
1822
+ nextState.action = action;
1823
+ nextState.pathname = pathname;
1824
+ nextState.routes = nextRoutes;
1825
+ nextState.params = nextParams;
1826
+ nextState.query = nextQuery;
1827
+
1828
+ callback.call(router, null, transition);
1829
+ });
1830
+ });
1831
+ },
1832
+
1833
+ /**
1834
+ * Starts this router and calls callback(router, state) when the route changes.
1835
+ *
1836
+ * If the router's location is static (i.e. a URL path in a server environment)
1837
+ * the callback is called only once. Otherwise, the location should be one of the
1838
+ * Router.*Location objects (e.g. Router.HashLocation or Router.HistoryLocation).
1839
+ */
1840
+ run: function (callback) {
1841
+ var dispatchHandler = function (error, transition) {
1842
+ pendingTransition = null;
1843
+
1844
+ if (error) {
1845
+ onError.call(router, error);
1846
+ } else if (transition.isAborted) {
1847
+ onAbort.call(router, transition.abortReason, location);
1848
+ } else {
1849
+ callback.call(router, router, nextState);
1850
+ }
1851
+ };
1852
+
1853
+ if (typeof location === 'string') {
1854
+ router.dispatch(location, null, dispatchHandler);
1855
+ } else {
1856
+ // Listen for changes to the location.
1857
+ var changeListener = function (change) {
1858
+ router.dispatch(change.path, change.type, dispatchHandler);
1859
+ };
1860
+
1861
+ if (location.addChangeListener)
1862
+ location.addChangeListener(changeListener);
1863
+
1864
+ // Bootstrap using the current path.
1865
+ router.dispatch(location.getCurrentPath(), null, dispatchHandler);
1866
+ }
1867
+ },
1868
+
1869
+ teardown: function() {
1870
+ location.removeChangeListener(this.changeListener);
1871
+ }
1872
+
1873
+ },
1874
+
1875
+ propTypes: {
1876
+ children: PropTypes.falsy
1877
+ },
1878
+
1879
+ getLocation: function () {
1880
+ return location;
1881
+ },
1882
+
1883
+ getScrollBehavior: function () {
1884
+ return scrollBehavior;
1885
+ },
1886
+
1887
+ getRouteAtDepth: function (depth) {
1888
+ var routes = this.state.routes;
1889
+ return routes && routes[depth];
1890
+ },
1891
+
1892
+ getRouteComponents: function () {
1893
+ return components;
1894
+ },
1895
+
1896
+ getInitialState: function () {
1897
+ updateState();
1898
+ return state;
1899
+ },
1900
+
1901
+ componentWillReceiveProps: function () {
1902
+ updateState();
1903
+ this.setState(state);
1904
+ },
1905
+
1906
+ componentWillUnmount: function() {
1907
+ router.teardown();
1908
+ },
1909
+
1910
+ render: function () {
1911
+ return this.getRouteAtDepth(0) ? React.createElement(RouteHandler, this.props) : null;
1912
+ },
1913
+
1914
+ childContextTypes: {
1915
+ getRouteAtDepth: React.PropTypes.func.isRequired,
1916
+ getRouteComponents: React.PropTypes.func.isRequired,
1917
+ routeHandlers: React.PropTypes.array.isRequired
1918
+ },
1919
+
1920
+ getChildContext: function () {
1921
+ return {
1922
+ getRouteComponents: this.getRouteComponents,
1923
+ getRouteAtDepth: this.getRouteAtDepth,
1924
+ routeHandlers: [ this ]
1925
+ };
1926
+ }
1927
+
1928
+ });
1929
+
1930
+ if (options.routes)
1931
+ router.addRoutes(options.routes);
1932
+
1933
+ return router;
1934
+ }
1935
+
1936
+ module.exports = createRouter;
1937
+
1938
+ },{"../actions/LocationActions":1,"../behaviors/ImitateBrowserBehavior":2,"../components/RouteHandler":9,"../locations/HashLocation":11,"../locations/HistoryLocation":12,"../locations/RefreshLocation":13,"../mixins/NavigationContext":16,"../mixins/Scrolling":18,"../mixins/StateContext":20,"./Cancellation":21,"./History":22,"./Path":23,"./PropTypes":25,"./Redirect":26,"./Transition":27,"./createRoutesFromChildren":29,"./supportsHistory":33,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":43,"react/lib/warning":44}],29:[function(_dereq_,module,exports){
1939
+ /* jshint -W084 */
1940
+ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
1941
+ var warning = _dereq_('react/lib/warning');
1942
+ var invariant = _dereq_('react/lib/invariant');
1943
+ var DefaultRoute = _dereq_('../components/DefaultRoute');
1944
+ var NotFoundRoute = _dereq_('../components/NotFoundRoute');
1945
+ var Redirect = _dereq_('../components/Redirect');
1946
+ var Route = _dereq_('../components/Route');
1947
+ var Path = _dereq_('./Path');
1948
+
1949
+ var CONFIG_ELEMENT_TYPES = [
1950
+ DefaultRoute.type,
1951
+ NotFoundRoute.type,
1952
+ Redirect.type,
1953
+ Route.type
1954
+ ];
1955
+
1956
+ function createRedirectHandler(to, _params, _query) {
1957
+ return React.createClass({
1958
+ statics: {
1959
+ willTransitionTo: function (transition, params, query) {
1960
+ transition.redirect(to, _params || params, _query || query);
1961
+ }
1962
+ },
1963
+
1964
+ render: function () {
1965
+ return null;
1966
+ }
1967
+ });
1968
+ }
1969
+
1970
+ function checkPropTypes(componentName, propTypes, props) {
1971
+ for (var propName in propTypes) {
1972
+ if (propTypes.hasOwnProperty(propName)) {
1973
+ var error = propTypes[propName](props, propName, componentName);
1974
+
1975
+ if (error instanceof Error)
1976
+ warning(false, error.message);
1977
+ }
1978
+ }
1979
+ }
1980
+
1981
+ function createRoute(element, parentRoute, namedRoutes) {
1982
+ var type = element.type;
1983
+ var props = element.props;
1984
+ var componentName = (type && type.displayName) || 'UnknownComponent';
1985
+
1986
+ invariant(
1987
+ CONFIG_ELEMENT_TYPES.indexOf(type) !== -1,
1988
+ 'Unrecognized route configuration element "<%s>"',
1989
+ componentName
1990
+ );
1991
+
1992
+ if (type.propTypes)
1993
+ checkPropTypes(componentName, type.propTypes, props);
1994
+
1995
+ var route = { name: props.name };
1996
+
1997
+ if (props.ignoreScrollBehavior) {
1998
+ route.ignoreScrollBehavior = true;
1999
+ }
2000
+
2001
+ if (type === Redirect.type) {
2002
+ route.handler = createRedirectHandler(props.to, props.params, props.query);
2003
+ props.path = props.path || props.from || '*';
2004
+ } else {
2005
+ route.handler = props.handler;
2006
+ }
2007
+
2008
+ var parentPath = (parentRoute && parentRoute.path) || '/';
2009
+
2010
+ if ((props.path || props.name) && type !== DefaultRoute.type && type !== NotFoundRoute.type) {
2011
+ var path = props.path || props.name;
2012
+
2013
+ // Relative paths extend their parent.
2014
+ if (!Path.isAbsolute(path))
2015
+ path = Path.join(parentPath, path);
2016
+
2017
+ route.path = Path.normalize(path);
2018
+ } else {
2019
+ route.path = parentPath;
2020
+
2021
+ if (type === NotFoundRoute.type)
2022
+ route.path += '*';
2023
+ }
2024
+
2025
+ route.paramNames = Path.extractParamNames(route.path);
2026
+
2027
+ // Make sure the route's path has all params its parent needs.
2028
+ if (parentRoute && Array.isArray(parentRoute.paramNames)) {
2029
+ parentRoute.paramNames.forEach(function (paramName) {
2030
+ invariant(
2031
+ route.paramNames.indexOf(paramName) !== -1,
2032
+ 'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"',
2033
+ route.path, paramName, parentRoute.path
2034
+ );
2035
+ });
2036
+ }
2037
+
2038
+ // Make sure the route can be looked up by <Link>s.
2039
+ if (props.name) {
2040
+ invariant(
2041
+ namedRoutes[props.name] == null,
2042
+ 'You cannot use the name "%s" for more than one route',
2043
+ props.name
2044
+ );
2045
+
2046
+ namedRoutes[props.name] = route;
2047
+ }
2048
+
2049
+ // Handle <NotFoundRoute>.
2050
+ if (type === NotFoundRoute.type) {
2051
+ invariant(
2052
+ parentRoute,
2053
+ '<NotFoundRoute> must have a parent <Route>'
2054
+ );
2055
+
2056
+ invariant(
2057
+ parentRoute.notFoundRoute == null,
2058
+ 'You may not have more than one <NotFoundRoute> per <Route>'
2059
+ );
2060
+
2061
+ parentRoute.notFoundRoute = route;
2062
+
2063
+ return null;
2064
+ }
2065
+
2066
+ // Handle <DefaultRoute>.
2067
+ if (type === DefaultRoute.type) {
2068
+ invariant(
2069
+ parentRoute,
2070
+ '<DefaultRoute> must have a parent <Route>'
2071
+ );
2072
+
2073
+ invariant(
2074
+ parentRoute.defaultRoute == null,
2075
+ 'You may not have more than one <DefaultRoute> per <Route>'
2076
+ );
2077
+
2078
+ parentRoute.defaultRoute = route;
2079
+
2080
+ return null;
2081
+ }
2082
+
2083
+ route.childRoutes = createRoutesFromChildren(props.children, route, namedRoutes);
2084
+
2085
+ return route;
2086
+ }
2087
+
2088
+ /**
2089
+ * Creates and returns an array of route objects from the given ReactChildren.
2090
+ */
2091
+ function createRoutesFromChildren(children, parentRoute, namedRoutes) {
2092
+ var routes = [];
2093
+
2094
+ React.Children.forEach(children, function (child) {
2095
+ // Exclude <DefaultRoute>s and <NotFoundRoute>s.
2096
+ if (child = createRoute(child, parentRoute, namedRoutes))
2097
+ routes.push(child);
2098
+ });
2099
+
2100
+ return routes;
2101
+ }
2102
+
2103
+ module.exports = createRoutesFromChildren;
2104
+
2105
+ },{"../components/DefaultRoute":4,"../components/NotFoundRoute":6,"../components/Redirect":7,"../components/Route":8,"./Path":23,"react/lib/invariant":43,"react/lib/warning":44}],30:[function(_dereq_,module,exports){
2106
+ var invariant = _dereq_('react/lib/invariant');
2107
+ var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM;
2108
+
2109
+ /**
2110
+ * Returns the current scroll position of the window as { x, y }.
2111
+ */
2112
+ function getWindowScrollPosition() {
2113
+ invariant(
2114
+ canUseDOM,
2115
+ 'Cannot get current scroll position without a DOM'
2116
+ );
2117
+
2118
+ return {
2119
+ x: window.pageXOffset || document.documentElement.scrollLeft,
2120
+ y: window.pageYOffset || document.documentElement.scrollTop
2121
+ };
2122
+ }
2123
+
2124
+ module.exports = getWindowScrollPosition;
2125
+
2126
+ },{"react/lib/ExecutionEnvironment":39,"react/lib/invariant":43}],31:[function(_dereq_,module,exports){
2127
+ function reversedArray(array) {
2128
+ return array.slice(0).reverse();
2129
+ }
2130
+
2131
+ module.exports = reversedArray;
2132
+
2133
+ },{}],32:[function(_dereq_,module,exports){
2134
+ var createRouter = _dereq_('./createRouter');
2135
+
2136
+ /**
2137
+ * A high-level convenience method that creates, configures, and
2138
+ * runs a router in one shot. The method signature is:
2139
+ *
2140
+ * Router.run(routes[, location ], callback);
2141
+ *
2142
+ * Using `window.location.hash` to manage the URL, you could do:
2143
+ *
2144
+ * Router.run(routes, function (Handler) {
2145
+ * React.render(<Handler/>, document.body);
2146
+ * });
2147
+ *
2148
+ * Using HTML5 history and a custom "cursor" prop:
2149
+ *
2150
+ * Router.run(routes, Router.HistoryLocation, function (Handler) {
2151
+ * React.render(<Handler cursor={cursor}/>, document.body);
2152
+ * });
2153
+ *
2154
+ * Returns the newly created router.
2155
+ *
2156
+ * Note: If you need to specify further options for your router such
2157
+ * as error/abort handling or custom scroll behavior, use Router.create
2158
+ * instead.
2159
+ *
2160
+ * var router = Router.create(options);
2161
+ * router.run(function (Handler) {
2162
+ * // ...
2163
+ * });
2164
+ */
2165
+ function runRouter(routes, location, callback) {
2166
+ if (typeof location === 'function') {
2167
+ callback = location;
2168
+ location = null;
2169
+ }
2170
+
2171
+ var router = createRouter({
2172
+ routes: routes,
2173
+ location: location
2174
+ });
2175
+
2176
+ router.run(callback);
2177
+
2178
+ return router;
2179
+ }
2180
+
2181
+ module.exports = runRouter;
2182
+
2183
+ },{"./createRouter":28}],33:[function(_dereq_,module,exports){
2184
+ function supportsHistory() {
2185
+ /*! taken from modernizr
2186
+ * https://github.com/Modernizr/Modernizr/blob/master/LICENSE
2187
+ * https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js
2188
+ * changed to avoid false negatives for Windows Phones: https://github.com/rackt/react-router/issues/586
2189
+ */
2190
+ var ua = navigator.userAgent;
2191
+ if ((ua.indexOf('Android 2.') !== -1 ||
2192
+ (ua.indexOf('Android 4.0') !== -1)) &&
2193
+ ua.indexOf('Mobile Safari') !== -1 &&
2194
+ ua.indexOf('Chrome') === -1 &&
2195
+ ua.indexOf('Windows Phone') === -1) {
2196
+ return false;
2197
+ }
2198
+ return (window.history && 'pushState' in window.history);
2199
+ }
2200
+
2201
+ module.exports = supportsHistory;
2202
+
2203
+ },{}],34:[function(_dereq_,module,exports){
2204
+ module.exports = _dereq_('./lib');
2205
+
2206
+ },{"./lib":35}],35:[function(_dereq_,module,exports){
2207
+ // Load modules
2208
+
2209
+ var Stringify = _dereq_('./stringify');
2210
+ var Parse = _dereq_('./parse');
2211
+
2212
+
2213
+ // Declare internals
2214
+
2215
+ var internals = {};
2216
+
2217
+
2218
+ module.exports = {
2219
+ stringify: Stringify,
2220
+ parse: Parse
2221
+ };
2222
+
2223
+ },{"./parse":36,"./stringify":37}],36:[function(_dereq_,module,exports){
2224
+ // Load modules
2225
+
2226
+ var Utils = _dereq_('./utils');
2227
+
2228
+
2229
+ // Declare internals
2230
+
2231
+ var internals = {
2232
+ delimiter: '&',
2233
+ depth: 5,
2234
+ arrayLimit: 20,
2235
+ parameterLimit: 1000
2236
+ };
2237
+
2238
+
2239
+ internals.parseValues = function (str, options) {
2240
+
2241
+ var obj = {};
2242
+ var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
2243
+
2244
+ for (var i = 0, il = parts.length; i < il; ++i) {
2245
+ var part = parts[i];
2246
+ var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
2247
+
2248
+ if (pos === -1) {
2249
+ obj[Utils.decode(part)] = '';
2250
+ }
2251
+ else {
2252
+ var key = Utils.decode(part.slice(0, pos));
2253
+ var val = Utils.decode(part.slice(pos + 1));
2254
+
2255
+ if (!obj[key]) {
2256
+ obj[key] = val;
2257
+ }
2258
+ else {
2259
+ obj[key] = [].concat(obj[key]).concat(val);
2260
+ }
2261
+ }
2262
+ }
2263
+
2264
+ return obj;
2265
+ };
2266
+
2267
+
2268
+ internals.parseObject = function (chain, val, options) {
2269
+
2270
+ if (!chain.length) {
2271
+ return val;
2272
+ }
2273
+
2274
+ var root = chain.shift();
2275
+
2276
+ var obj = {};
2277
+ if (root === '[]') {
2278
+ obj = [];
2279
+ obj = obj.concat(internals.parseObject(chain, val, options));
2280
+ }
2281
+ else {
2282
+ var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
2283
+ var index = parseInt(cleanRoot, 10);
2284
+ if (!isNaN(index) &&
2285
+ root !== cleanRoot &&
2286
+ index <= options.arrayLimit) {
2287
+
2288
+ obj = [];
2289
+ obj[index] = internals.parseObject(chain, val, options);
2290
+ }
2291
+ else {
2292
+ obj[cleanRoot] = internals.parseObject(chain, val, options);
2293
+ }
2294
+ }
2295
+
2296
+ return obj;
2297
+ };
2298
+
2299
+
2300
+ internals.parseKeys = function (key, val, options) {
2301
+
2302
+ if (!key) {
2303
+ return;
2304
+ }
2305
+
2306
+ // The regex chunks
2307
+
2308
+ var parent = /^([^\[\]]*)/;
2309
+ var child = /(\[[^\[\]]*\])/g;
2310
+
2311
+ // Get the parent
2312
+
2313
+ var segment = parent.exec(key);
2314
+
2315
+ // Don't allow them to overwrite object prototype properties
2316
+
2317
+ if (Object.prototype.hasOwnProperty(segment[1])) {
2318
+ return;
2319
+ }
2320
+
2321
+ // Stash the parent if it exists
2322
+
2323
+ var keys = [];
2324
+ if (segment[1]) {
2325
+ keys.push(segment[1]);
2326
+ }
2327
+
2328
+ // Loop through children appending to the array until we hit depth
2329
+
2330
+ var i = 0;
2331
+ while ((segment = child.exec(key)) !== null && i < options.depth) {
2332
+
2333
+ ++i;
2334
+ if (!Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) {
2335
+ keys.push(segment[1]);
2336
+ }
2337
+ }
2338
+
2339
+ // If there's a remainder, just add whatever is left
2340
+
2341
+ if (segment) {
2342
+ keys.push('[' + key.slice(segment.index) + ']');
2343
+ }
2344
+
2345
+ return internals.parseObject(keys, val, options);
2346
+ };
2347
+
2348
+
2349
+ module.exports = function (str, options) {
2350
+
2351
+ if (str === '' ||
2352
+ str === null ||
2353
+ typeof str === 'undefined') {
2354
+
2355
+ return {};
2356
+ }
2357
+
2358
+ options = options || {};
2359
+ options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter;
2360
+ options.depth = typeof options.depth === 'number' ? options.depth : internals.depth;
2361
+ options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit;
2362
+ options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit;
2363
+
2364
+ var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str;
2365
+ var obj = {};
2366
+
2367
+ // Iterate over the keys and setup the new object
2368
+
2369
+ var keys = Object.keys(tempObj);
2370
+ for (var i = 0, il = keys.length; i < il; ++i) {
2371
+ var key = keys[i];
2372
+ var newObj = internals.parseKeys(key, tempObj[key], options);
2373
+ obj = Utils.merge(obj, newObj);
2374
+ }
2375
+
2376
+ return Utils.compact(obj);
2377
+ };
2378
+
2379
+ },{"./utils":38}],37:[function(_dereq_,module,exports){
2380
+ // Load modules
2381
+
2382
+ var Utils = _dereq_('./utils');
2383
+
2384
+
2385
+ // Declare internals
2386
+
2387
+ var internals = {
2388
+ delimiter: '&'
2389
+ };
2390
+
2391
+
2392
+ internals.stringify = function (obj, prefix) {
2393
+
2394
+ if (Utils.isBuffer(obj)) {
2395
+ obj = obj.toString();
2396
+ }
2397
+ else if (obj instanceof Date) {
2398
+ obj = obj.toISOString();
2399
+ }
2400
+ else if (obj === null) {
2401
+ obj = '';
2402
+ }
2403
+
2404
+ if (typeof obj === 'string' ||
2405
+ typeof obj === 'number' ||
2406
+ typeof obj === 'boolean') {
2407
+
2408
+ return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)];
2409
+ }
2410
+
2411
+ var values = [];
2412
+
2413
+ for (var key in obj) {
2414
+ if (obj.hasOwnProperty(key)) {
2415
+ values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']'));
2416
+ }
2417
+ }
2418
+
2419
+ return values;
2420
+ };
2421
+
2422
+
2423
+ module.exports = function (obj, options) {
2424
+
2425
+ options = options || {};
2426
+ var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
2427
+
2428
+ var keys = [];
2429
+
2430
+ for (var key in obj) {
2431
+ if (obj.hasOwnProperty(key)) {
2432
+ keys = keys.concat(internals.stringify(obj[key], key));
2433
+ }
2434
+ }
2435
+
2436
+ return keys.join(delimiter);
2437
+ };
2438
+
2439
+ },{"./utils":38}],38:[function(_dereq_,module,exports){
2440
+ // Load modules
2441
+
2442
+
2443
+ // Declare internals
2444
+
2445
+ var internals = {};
2446
+
2447
+
2448
+ exports.arrayToObject = function (source) {
2449
+
2450
+ var obj = {};
2451
+ for (var i = 0, il = source.length; i < il; ++i) {
2452
+ if (typeof source[i] !== 'undefined') {
2453
+
2454
+ obj[i] = source[i];
2455
+ }
2456
+ }
2457
+
2458
+ return obj;
2459
+ };
2460
+
2461
+
2462
+ exports.merge = function (target, source) {
2463
+
2464
+ if (!source) {
2465
+ return target;
2466
+ }
2467
+
2468
+ if (Array.isArray(source)) {
2469
+ for (var i = 0, il = source.length; i < il; ++i) {
2470
+ if (typeof source[i] !== 'undefined') {
2471
+ if (typeof target[i] === 'object') {
2472
+ target[i] = exports.merge(target[i], source[i]);
2473
+ }
2474
+ else {
2475
+ target[i] = source[i];
2476
+ }
2477
+ }
2478
+ }
2479
+
2480
+ return target;
2481
+ }
2482
+
2483
+ if (Array.isArray(target)) {
2484
+ if (typeof source !== 'object') {
2485
+ target.push(source);
2486
+ return target;
2487
+ }
2488
+ else {
2489
+ target = exports.arrayToObject(target);
2490
+ }
2491
+ }
2492
+
2493
+ var keys = Object.keys(source);
2494
+ for (var k = 0, kl = keys.length; k < kl; ++k) {
2495
+ var key = keys[k];
2496
+ var value = source[key];
2497
+
2498
+ if (value &&
2499
+ typeof value === 'object') {
2500
+
2501
+ if (!target[key]) {
2502
+ target[key] = value;
2503
+ }
2504
+ else {
2505
+ target[key] = exports.merge(target[key], value);
2506
+ }
2507
+ }
2508
+ else {
2509
+ target[key] = value;
2510
+ }
2511
+ }
2512
+
2513
+ return target;
2514
+ };
2515
+
2516
+
2517
+ exports.decode = function (str) {
2518
+
2519
+ try {
2520
+ return decodeURIComponent(str.replace(/\+/g, ' '));
2521
+ } catch (e) {
2522
+ return str;
2523
+ }
2524
+ };
2525
+
2526
+
2527
+ exports.compact = function (obj, refs) {
2528
+
2529
+ if (typeof obj !== 'object' ||
2530
+ obj === null) {
2531
+
2532
+ return obj;
2533
+ }
2534
+
2535
+ refs = refs || [];
2536
+ var lookup = refs.indexOf(obj);
2537
+ if (lookup !== -1) {
2538
+ return refs[lookup];
2539
+ }
2540
+
2541
+ refs.push(obj);
2542
+
2543
+ if (Array.isArray(obj)) {
2544
+ var compacted = [];
2545
+
2546
+ for (var i = 0, l = obj.length; i < l; ++i) {
2547
+ if (typeof obj[i] !== 'undefined') {
2548
+ compacted.push(obj[i]);
2549
+ }
2550
+ }
2551
+
2552
+ return compacted;
2553
+ }
2554
+
2555
+ var keys = Object.keys(obj);
2556
+ for (var i = 0, il = keys.length; i < il; ++i) {
2557
+ var key = keys[i];
2558
+ obj[key] = exports.compact(obj[key], refs);
2559
+ }
2560
+
2561
+ return obj;
2562
+ };
2563
+
2564
+
2565
+ exports.isRegExp = function (obj) {
2566
+ return Object.prototype.toString.call(obj) === '[object RegExp]';
2567
+ };
2568
+
2569
+
2570
+ exports.isBuffer = function (obj) {
2571
+
2572
+ if (typeof Buffer !== 'undefined') {
2573
+ return Buffer.isBuffer(obj);
2574
+ }
2575
+ else {
2576
+ return false;
2577
+ }
2578
+ };
2579
+
2580
+ },{}],39:[function(_dereq_,module,exports){
2581
+ /**
2582
+ * Copyright 2013-2014, Facebook, Inc.
2583
+ * All rights reserved.
2584
+ *
2585
+ * This source code is licensed under the BSD-style license found in the
2586
+ * LICENSE file in the root directory of this source tree. An additional grant
2587
+ * of patent rights can be found in the PATENTS file in the same directory.
2588
+ *
2589
+ * @providesModule ExecutionEnvironment
2590
+ */
2591
+
2592
+ /*jslint evil: true */
2593
+
2594
+ "use strict";
2595
+
2596
+ var canUseDOM = !!(
2597
+ typeof window !== 'undefined' &&
2598
+ window.document &&
2599
+ window.document.createElement
2600
+ );
2601
+
2602
+ /**
2603
+ * Simple, lightweight module assisting with the detection and context of
2604
+ * Worker. Helps avoid circular dependencies and allows code to reason about
2605
+ * whether or not they are in a Worker, even if they never include the main
2606
+ * `ReactWorker` dependency.
2607
+ */
2608
+ var ExecutionEnvironment = {
2609
+
2610
+ canUseDOM: canUseDOM,
2611
+
2612
+ canUseWorkers: typeof Worker !== 'undefined',
2613
+
2614
+ canUseEventListeners:
2615
+ canUseDOM && !!(window.addEventListener || window.attachEvent),
2616
+
2617
+ canUseViewport: canUseDOM && !!window.screen,
2618
+
2619
+ isInWorker: !canUseDOM // For now, this is true - might change in the future.
2620
+
2621
+ };
2622
+
2623
+ module.exports = ExecutionEnvironment;
2624
+
2625
+ },{}],40:[function(_dereq_,module,exports){
2626
+ /**
2627
+ * Copyright 2014, Facebook, Inc.
2628
+ * All rights reserved.
2629
+ *
2630
+ * This source code is licensed under the BSD-style license found in the
2631
+ * LICENSE file in the root directory of this source tree. An additional grant
2632
+ * of patent rights can be found in the PATENTS file in the same directory.
2633
+ *
2634
+ * @providesModule Object.assign
2635
+ */
2636
+
2637
+ // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign
2638
+
2639
+ function assign(target, sources) {
2640
+ if (target == null) {
2641
+ throw new TypeError('Object.assign target cannot be null or undefined');
2642
+ }
2643
+
2644
+ var to = Object(target);
2645
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
2646
+
2647
+ for (var nextIndex = 1; nextIndex < arguments.length; nextIndex++) {
2648
+ var nextSource = arguments[nextIndex];
2649
+ if (nextSource == null) {
2650
+ continue;
2651
+ }
2652
+
2653
+ var from = Object(nextSource);
2654
+
2655
+ // We don't currently support accessors nor proxies. Therefore this
2656
+ // copy cannot throw. If we ever supported this then we must handle
2657
+ // exceptions and side-effects. We don't support symbols so they won't
2658
+ // be transferred.
2659
+
2660
+ for (var key in from) {
2661
+ if (hasOwnProperty.call(from, key)) {
2662
+ to[key] = from[key];
2663
+ }
2664
+ }
2665
+ }
2666
+
2667
+ return to;
2668
+ };
2669
+
2670
+ module.exports = assign;
2671
+
2672
+ },{}],41:[function(_dereq_,module,exports){
2673
+ /**
2674
+ * Copyright 2013-2014, Facebook, Inc.
2675
+ * All rights reserved.
2676
+ *
2677
+ * This source code is licensed under the BSD-style license found in the
2678
+ * LICENSE file in the root directory of this source tree. An additional grant
2679
+ * of patent rights can be found in the PATENTS file in the same directory.
2680
+ *
2681
+ * @providesModule cx
2682
+ */
2683
+
2684
+ /**
2685
+ * This function is used to mark string literals representing CSS class names
2686
+ * so that they can be transformed statically. This allows for modularization
2687
+ * and minification of CSS class names.
2688
+ *
2689
+ * In static_upstream, this function is actually implemented, but it should
2690
+ * eventually be replaced with something more descriptive, and the transform
2691
+ * that is used in the main stack should be ported for use elsewhere.
2692
+ *
2693
+ * @param string|object className to modularize, or an object of key/values.
2694
+ * In the object case, the values are conditions that
2695
+ * determine if the className keys should be included.
2696
+ * @param [string ...] Variable list of classNames in the string case.
2697
+ * @return string Renderable space-separated CSS className.
2698
+ */
2699
+ function cx(classNames) {
2700
+ if (typeof classNames == 'object') {
2701
+ return Object.keys(classNames).filter(function(className) {
2702
+ return classNames[className];
2703
+ }).join(' ');
2704
+ } else {
2705
+ return Array.prototype.join.call(arguments, ' ');
2706
+ }
2707
+ }
2708
+
2709
+ module.exports = cx;
2710
+
2711
+ },{}],42:[function(_dereq_,module,exports){
2712
+ /**
2713
+ * Copyright 2013-2014, Facebook, Inc.
2714
+ * All rights reserved.
2715
+ *
2716
+ * This source code is licensed under the BSD-style license found in the
2717
+ * LICENSE file in the root directory of this source tree. An additional grant
2718
+ * of patent rights can be found in the PATENTS file in the same directory.
2719
+ *
2720
+ * @providesModule emptyFunction
2721
+ */
2722
+
2723
+ function makeEmptyFunction(arg) {
2724
+ return function() {
2725
+ return arg;
2726
+ };
2727
+ }
2728
+
2729
+ /**
2730
+ * This function accepts and discards inputs; it has no side effects. This is
2731
+ * primarily useful idiomatically for overridable function endpoints which
2732
+ * always need to be callable, since JS lacks a null-call idiom ala Cocoa.
2733
+ */
2734
+ function emptyFunction() {}
2735
+
2736
+ emptyFunction.thatReturns = makeEmptyFunction;
2737
+ emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
2738
+ emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
2739
+ emptyFunction.thatReturnsNull = makeEmptyFunction(null);
2740
+ emptyFunction.thatReturnsThis = function() { return this; };
2741
+ emptyFunction.thatReturnsArgument = function(arg) { return arg; };
2742
+
2743
+ module.exports = emptyFunction;
2744
+
2745
+ },{}],43:[function(_dereq_,module,exports){
2746
+ /**
2747
+ * Copyright 2013-2014, Facebook, Inc.
2748
+ * All rights reserved.
2749
+ *
2750
+ * This source code is licensed under the BSD-style license found in the
2751
+ * LICENSE file in the root directory of this source tree. An additional grant
2752
+ * of patent rights can be found in the PATENTS file in the same directory.
2753
+ *
2754
+ * @providesModule invariant
2755
+ */
2756
+
2757
+ "use strict";
2758
+
2759
+ /**
2760
+ * Use invariant() to assert state which your program assumes to be true.
2761
+ *
2762
+ * Provide sprintf-style format (only %s is supported) and arguments
2763
+ * to provide information about what broke and what you were
2764
+ * expecting.
2765
+ *
2766
+ * The invariant message will be stripped in production, but the invariant
2767
+ * will remain to ensure logic does not differ in production.
2768
+ */
2769
+
2770
+ var invariant = function(condition, format, a, b, c, d, e, f) {
2771
+ if ("production" !== "production") {
2772
+ if (format === undefined) {
2773
+ throw new Error('invariant requires an error message argument');
2774
+ }
2775
+ }
2776
+
2777
+ if (!condition) {
2778
+ var error;
2779
+ if (format === undefined) {
2780
+ error = new Error(
2781
+ 'Minified exception occurred; use the non-minified dev environment ' +
2782
+ 'for the full error message and additional helpful warnings.'
2783
+ );
2784
+ } else {
2785
+ var args = [a, b, c, d, e, f];
2786
+ var argIndex = 0;
2787
+ error = new Error(
2788
+ 'Invariant Violation: ' +
2789
+ format.replace(/%s/g, function() { return args[argIndex++]; })
2790
+ );
2791
+ }
2792
+
2793
+ error.framesToPop = 1; // we don't care about invariant's own frame
2794
+ throw error;
2795
+ }
2796
+ };
2797
+
2798
+ module.exports = invariant;
2799
+
2800
+ },{}],44:[function(_dereq_,module,exports){
2801
+ /**
2802
+ * Copyright 2014, Facebook, Inc.
2803
+ * All rights reserved.
2804
+ *
2805
+ * This source code is licensed under the BSD-style license found in the
2806
+ * LICENSE file in the root directory of this source tree. An additional grant
2807
+ * of patent rights can be found in the PATENTS file in the same directory.
2808
+ *
2809
+ * @providesModule warning
2810
+ */
2811
+
2812
+ "use strict";
2813
+
2814
+ var emptyFunction = _dereq_("./emptyFunction");
2815
+
2816
+ /**
2817
+ * Similar to invariant but only logs a warning if the condition is not met.
2818
+ * This can be used to log issues in development environments in critical
2819
+ * paths. Removing the logging code for production environments will keep the
2820
+ * same logic and follow the same code paths.
2821
+ */
2822
+
2823
+ var warning = emptyFunction;
2824
+
2825
+ if ("production" !== "production") {
2826
+ warning = function(condition, format ) {for (var args=[],$__0=2,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]);
2827
+ if (format === undefined) {
2828
+ throw new Error(
2829
+ '`warning(condition, format, ...args)` requires a warning ' +
2830
+ 'message argument'
2831
+ );
2832
+ }
2833
+
2834
+ if (!condition) {
2835
+ var argIndex = 0;
2836
+ console.warn('Warning: ' + format.replace(/%s/g, function() {return args[argIndex++];}));
2837
+ }
2838
+ };
2839
+ }
2840
+
2841
+ module.exports = warning;
2842
+
2843
+ },{"./emptyFunction":42}],45:[function(_dereq_,module,exports){
2844
+ /** @license MIT License (c) copyright 2010-2014 original author or authors */
2845
+ /** @author Brian Cavalier */
2846
+ /** @author John Hann */
2847
+
2848
+ (function(define) { 'use strict';
2849
+ define(function (_dereq_) {
2850
+
2851
+ var makePromise = _dereq_('./makePromise');
2852
+ var Scheduler = _dereq_('./Scheduler');
2853
+ var async = _dereq_('./async');
2854
+
2855
+ return makePromise({
2856
+ scheduler: new Scheduler(async)
2857
+ });
2858
+
2859
+ });
2860
+ })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(_dereq_); });
2861
+
2862
+ },{"./Scheduler":47,"./async":48,"./makePromise":49}],46:[function(_dereq_,module,exports){
2863
+ /** @license MIT License (c) copyright 2010-2014 original author or authors */
2864
+ /** @author Brian Cavalier */
2865
+ /** @author John Hann */
2866
+
2867
+ (function(define) { 'use strict';
2868
+ define(function() {
2869
+ /**
2870
+ * Circular queue
2871
+ * @param {number} capacityPow2 power of 2 to which this queue's capacity
2872
+ * will be set initially. eg when capacityPow2 == 3, queue capacity
2873
+ * will be 8.
2874
+ * @constructor
2875
+ */
2876
+ function Queue(capacityPow2) {
2877
+ this.head = this.tail = this.length = 0;
2878
+ this.buffer = new Array(1 << capacityPow2);
2879
+ }
2880
+
2881
+ Queue.prototype.push = function(x) {
2882
+ if(this.length === this.buffer.length) {
2883
+ this._ensureCapacity(this.length * 2);
2884
+ }
2885
+
2886
+ this.buffer[this.tail] = x;
2887
+ this.tail = (this.tail + 1) & (this.buffer.length - 1);
2888
+ ++this.length;
2889
+ return this.length;
2890
+ };
2891
+
2892
+ Queue.prototype.shift = function() {
2893
+ var x = this.buffer[this.head];
2894
+ this.buffer[this.head] = void 0;
2895
+ this.head = (this.head + 1) & (this.buffer.length - 1);
2896
+ --this.length;
2897
+ return x;
2898
+ };
2899
+
2900
+ Queue.prototype._ensureCapacity = function(capacity) {
2901
+ var head = this.head;
2902
+ var buffer = this.buffer;
2903
+ var newBuffer = new Array(capacity);
2904
+ var i = 0;
2905
+ var len;
2906
+
2907
+ if(head === 0) {
2908
+ len = this.length;
2909
+ for(; i<len; ++i) {
2910
+ newBuffer[i] = buffer[i];
2911
+ }
2912
+ } else {
2913
+ capacity = buffer.length;
2914
+ len = this.tail;
2915
+ for(; head<capacity; ++i, ++head) {
2916
+ newBuffer[i] = buffer[head];
2917
+ }
2918
+
2919
+ for(head=0; head<len; ++i, ++head) {
2920
+ newBuffer[i] = buffer[head];
2921
+ }
2922
+ }
2923
+
2924
+ this.buffer = newBuffer;
2925
+ this.head = 0;
2926
+ this.tail = this.length;
2927
+ };
2928
+
2929
+ return Queue;
2930
+
2931
+ });
2932
+ }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
2933
+
2934
+ },{}],47:[function(_dereq_,module,exports){
2935
+ /** @license MIT License (c) copyright 2010-2014 original author or authors */
2936
+ /** @author Brian Cavalier */
2937
+ /** @author John Hann */
2938
+
2939
+ (function(define) { 'use strict';
2940
+ define(function(_dereq_) {
2941
+
2942
+ var Queue = _dereq_('./Queue');
2943
+
2944
+ // Credit to Twisol (https://github.com/Twisol) for suggesting
2945
+ // this type of extensible queue + trampoline approach for next-tick conflation.
2946
+
2947
+ /**
2948
+ * Async task scheduler
2949
+ * @param {function} async function to schedule a single async function
2950
+ * @constructor
2951
+ */
2952
+ function Scheduler(async) {
2953
+ this._async = async;
2954
+ this._queue = new Queue(15);
2955
+ this._afterQueue = new Queue(5);
2956
+ this._running = false;
2957
+
2958
+ var self = this;
2959
+ this.drain = function() {
2960
+ self._drain();
2961
+ };
2962
+ }
2963
+
2964
+ /**
2965
+ * Enqueue a task
2966
+ * @param {{ run:function }} task
2967
+ */
2968
+ Scheduler.prototype.enqueue = function(task) {
2969
+ this._add(this._queue, task);
2970
+ };
2971
+
2972
+ /**
2973
+ * Enqueue a task to run after the main task queue
2974
+ * @param {{ run:function }} task
2975
+ */
2976
+ Scheduler.prototype.afterQueue = function(task) {
2977
+ this._add(this._afterQueue, task);
2978
+ };
2979
+
2980
+ /**
2981
+ * Drain the handler queue entirely, and then the after queue
2982
+ */
2983
+ Scheduler.prototype._drain = function() {
2984
+ runQueue(this._queue);
2985
+ this._running = false;
2986
+ runQueue(this._afterQueue);
2987
+ };
2988
+
2989
+ /**
2990
+ * Add a task to the q, and schedule drain if not already scheduled
2991
+ * @param {Queue} queue
2992
+ * @param {{run:function}} task
2993
+ * @private
2994
+ */
2995
+ Scheduler.prototype._add = function(queue, task) {
2996
+ queue.push(task);
2997
+ if(!this._running) {
2998
+ this._running = true;
2999
+ this._async(this.drain);
3000
+ }
3001
+ };
3002
+
3003
+ /**
3004
+ * Run all the tasks in the q
3005
+ * @param queue
3006
+ */
3007
+ function runQueue(queue) {
3008
+ while(queue.length > 0) {
3009
+ queue.shift().run();
3010
+ }
3011
+ }
3012
+
3013
+ return Scheduler;
3014
+
3015
+ });
3016
+ }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); }));
3017
+
3018
+ },{"./Queue":46}],48:[function(_dereq_,module,exports){
3019
+ /** @license MIT License (c) copyright 2010-2014 original author or authors */
3020
+ /** @author Brian Cavalier */
3021
+ /** @author John Hann */
3022
+
3023
+ (function(define) { 'use strict';
3024
+ define(function(_dereq_) {
3025
+
3026
+ // Sniff "best" async scheduling option
3027
+ // Prefer process.nextTick or MutationObserver, then check for
3028
+ // vertx and finally fall back to setTimeout
3029
+
3030
+ /*jshint maxcomplexity:6*/
3031
+ /*global process,document,setTimeout,MutationObserver,WebKitMutationObserver*/
3032
+ var nextTick, MutationObs;
3033
+
3034
+ if (typeof process !== 'undefined' && process !== null &&
3035
+ typeof process.nextTick === 'function') {
3036
+ nextTick = function(f) {
3037
+ process.nextTick(f);
3038
+ };
3039
+
3040
+ } else if (MutationObs =
3041
+ (typeof MutationObserver === 'function' && MutationObserver) ||
3042
+ (typeof WebKitMutationObserver === 'function' && WebKitMutationObserver)) {
3043
+ nextTick = (function (document, MutationObserver) {
3044
+ var scheduled;
3045
+ var el = document.createElement('div');
3046
+ var o = new MutationObserver(run);
3047
+ o.observe(el, { attributes: true });
3048
+
3049
+ function run() {
3050
+ var f = scheduled;
3051
+ scheduled = void 0;
3052
+ f();
3053
+ }
3054
+
3055
+ return function (f) {
3056
+ scheduled = f;
3057
+ el.setAttribute('class', 'x');
3058
+ };
3059
+ }(document, MutationObs));
3060
+
3061
+ } else {
3062
+ nextTick = (function(cjsRequire) {
3063
+ var vertx;
3064
+ try {
3065
+ // vert.x 1.x || 2.x
3066
+ vertx = cjsRequire('vertx');
3067
+ } catch (ignore) {}
3068
+
3069
+ if (vertx) {
3070
+ if (typeof vertx.runOnLoop === 'function') {
3071
+ return vertx.runOnLoop;
3072
+ }
3073
+ if (typeof vertx.runOnContext === 'function') {
3074
+ return vertx.runOnContext;
3075
+ }
3076
+ }
3077
+
3078
+ // capture setTimeout to avoid being caught by fake timers
3079
+ // used in time based tests
3080
+ var capturedSetTimeout = setTimeout;
3081
+ return function (t) {
3082
+ capturedSetTimeout(t, 0);
3083
+ };
3084
+ }(_dereq_));
3085
+ }
3086
+
3087
+ return nextTick;
3088
+ });
3089
+ }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); }));
3090
+
3091
+ },{}],49:[function(_dereq_,module,exports){
3092
+ /** @license MIT License (c) copyright 2010-2014 original author or authors */
3093
+ /** @author Brian Cavalier */
3094
+ /** @author John Hann */
3095
+
3096
+ (function(define) { 'use strict';
3097
+ define(function() {
3098
+
3099
+ return function makePromise(environment) {
3100
+
3101
+ var tasks = environment.scheduler;
3102
+
3103
+ var objectCreate = Object.create ||
3104
+ function(proto) {
3105
+ function Child() {}
3106
+ Child.prototype = proto;
3107
+ return new Child();
3108
+ };
3109
+
3110
+ /**
3111
+ * Create a promise whose fate is determined by resolver
3112
+ * @constructor
3113
+ * @returns {Promise} promise
3114
+ * @name Promise
3115
+ */
3116
+ function Promise(resolver, handler) {
3117
+ this._handler = resolver === Handler ? handler : init(resolver);
3118
+ }
3119
+
3120
+ /**
3121
+ * Run the supplied resolver
3122
+ * @param resolver
3123
+ * @returns {Pending}
3124
+ */
3125
+ function init(resolver) {
3126
+ var handler = new Pending();
3127
+
3128
+ try {
3129
+ resolver(promiseResolve, promiseReject, promiseNotify);
3130
+ } catch (e) {
3131
+ promiseReject(e);
3132
+ }
3133
+
3134
+ return handler;
3135
+
3136
+ /**
3137
+ * Transition from pre-resolution state to post-resolution state, notifying
3138
+ * all listeners of the ultimate fulfillment or rejection
3139
+ * @param {*} x resolution value
3140
+ */
3141
+ function promiseResolve (x) {
3142
+ handler.resolve(x);
3143
+ }
3144
+ /**
3145
+ * Reject this promise with reason, which will be used verbatim
3146
+ * @param {Error|*} reason rejection reason, strongly suggested
3147
+ * to be an Error type
3148
+ */
3149
+ function promiseReject (reason) {
3150
+ handler.reject(reason);
3151
+ }
3152
+
3153
+ /**
3154
+ * Issue a progress event, notifying all progress listeners
3155
+ * @param {*} x progress event payload to pass to all listeners
3156
+ */
3157
+ function promiseNotify (x) {
3158
+ handler.notify(x);
3159
+ }
3160
+ }
3161
+
3162
+ // Creation
3163
+
3164
+ Promise.resolve = resolve;
3165
+ Promise.reject = reject;
3166
+ Promise.never = never;
3167
+
3168
+ Promise._defer = defer;
3169
+ Promise._handler = getHandler;
3170
+
3171
+ /**
3172
+ * Returns a trusted promise. If x is already a trusted promise, it is
3173
+ * returned, otherwise returns a new trusted Promise which follows x.
3174
+ * @param {*} x
3175
+ * @return {Promise} promise
3176
+ */
3177
+ function resolve(x) {
3178
+ return isPromise(x) ? x
3179
+ : new Promise(Handler, new Async(getHandler(x)));
3180
+ }
3181
+
3182
+ /**
3183
+ * Return a reject promise with x as its reason (x is used verbatim)
3184
+ * @param {*} x
3185
+ * @returns {Promise} rejected promise
3186
+ */
3187
+ function reject(x) {
3188
+ return new Promise(Handler, new Async(new Rejected(x)));
3189
+ }
3190
+
3191
+ /**
3192
+ * Return a promise that remains pending forever
3193
+ * @returns {Promise} forever-pending promise.
3194
+ */
3195
+ function never() {
3196
+ return foreverPendingPromise; // Should be frozen
3197
+ }
3198
+
3199
+ /**
3200
+ * Creates an internal {promise, resolver} pair
3201
+ * @private
3202
+ * @returns {Promise}
3203
+ */
3204
+ function defer() {
3205
+ return new Promise(Handler, new Pending());
3206
+ }
3207
+
3208
+ // Transformation and flow control
3209
+
3210
+ /**
3211
+ * Transform this promise's fulfillment value, returning a new Promise
3212
+ * for the transformed result. If the promise cannot be fulfilled, onRejected
3213
+ * is called with the reason. onProgress *may* be called with updates toward
3214
+ * this promise's fulfillment.
3215
+ * @param {function=} onFulfilled fulfillment handler
3216
+ * @param {function=} onRejected rejection handler
3217
+ * @deprecated @param {function=} onProgress progress handler
3218
+ * @return {Promise} new promise
3219
+ */
3220
+ Promise.prototype.then = function(onFulfilled, onRejected) {
3221
+ var parent = this._handler;
3222
+ var state = parent.join().state();
3223
+
3224
+ if ((typeof onFulfilled !== 'function' && state > 0) ||
3225
+ (typeof onRejected !== 'function' && state < 0)) {
3226
+ // Short circuit: value will not change, simply share handler
3227
+ return new this.constructor(Handler, parent);
3228
+ }
3229
+
3230
+ var p = this._beget();
3231
+ var child = p._handler;
3232
+
3233
+ parent.chain(child, parent.receiver, onFulfilled, onRejected,
3234
+ arguments.length > 2 ? arguments[2] : void 0);
3235
+
3236
+ return p;
3237
+ };
3238
+
3239
+ /**
3240
+ * If this promise cannot be fulfilled due to an error, call onRejected to
3241
+ * handle the error. Shortcut for .then(undefined, onRejected)
3242
+ * @param {function?} onRejected
3243
+ * @return {Promise}
3244
+ */
3245
+ Promise.prototype['catch'] = function(onRejected) {
3246
+ return this.then(void 0, onRejected);
3247
+ };
3248
+
3249
+ /**
3250
+ * Creates a new, pending promise of the same type as this promise
3251
+ * @private
3252
+ * @returns {Promise}
3253
+ */
3254
+ Promise.prototype._beget = function() {
3255
+ var parent = this._handler;
3256
+ var child = new Pending(parent.receiver, parent.join().context);
3257
+ return new this.constructor(Handler, child);
3258
+ };
3259
+
3260
+ // Array combinators
3261
+
3262
+ Promise.all = all;
3263
+ Promise.race = race;
3264
+
3265
+ /**
3266
+ * Return a promise that will fulfill when all promises in the
3267
+ * input array have fulfilled, or will reject when one of the
3268
+ * promises rejects.
3269
+ * @param {array} promises array of promises
3270
+ * @returns {Promise} promise for array of fulfillment values
3271
+ */
3272
+ function all(promises) {
3273
+ /*jshint maxcomplexity:8*/
3274
+ var resolver = new Pending();
3275
+ var pending = promises.length >>> 0;
3276
+ var results = new Array(pending);
3277
+
3278
+ var i, h, x, s;
3279
+ for (i = 0; i < promises.length; ++i) {
3280
+ x = promises[i];
3281
+
3282
+ if (x === void 0 && !(i in promises)) {
3283
+ --pending;
3284
+ continue;
3285
+ }
3286
+
3287
+ if (maybeThenable(x)) {
3288
+ h = getHandlerMaybeThenable(x);
3289
+
3290
+ s = h.state();
3291
+ if (s === 0) {
3292
+ h.fold(settleAt, i, results, resolver);
3293
+ } else if (s > 0) {
3294
+ results[i] = h.value;
3295
+ --pending;
3296
+ } else {
3297
+ unreportRemaining(promises, i+1, h);
3298
+ resolver.become(h);
3299
+ break;
3300
+ }
3301
+
3302
+ } else {
3303
+ results[i] = x;
3304
+ --pending;
3305
+ }
3306
+ }
3307
+
3308
+ if(pending === 0) {
3309
+ resolver.become(new Fulfilled(results));
3310
+ }
3311
+
3312
+ return new Promise(Handler, resolver);
3313
+
3314
+ function settleAt(i, x, resolver) {
3315
+ /*jshint validthis:true*/
3316
+ this[i] = x;
3317
+ if(--pending === 0) {
3318
+ resolver.become(new Fulfilled(this));
3319
+ }
3320
+ }
3321
+ }
3322
+
3323
+ function unreportRemaining(promises, start, rejectedHandler) {
3324
+ var i, h, x;
3325
+ for(i=start; i<promises.length; ++i) {
3326
+ x = promises[i];
3327
+ if(maybeThenable(x)) {
3328
+ h = getHandlerMaybeThenable(x);
3329
+
3330
+ if(h !== rejectedHandler) {
3331
+ h.visit(h, void 0, h._unreport);
3332
+ }
3333
+ }
3334
+ }
3335
+ }
3336
+
3337
+ /**
3338
+ * Fulfill-reject competitive race. Return a promise that will settle
3339
+ * to the same state as the earliest input promise to settle.
3340
+ *
3341
+ * WARNING: The ES6 Promise spec requires that race()ing an empty array
3342
+ * must return a promise that is pending forever. This implementation
3343
+ * returns a singleton forever-pending promise, the same singleton that is
3344
+ * returned by Promise.never(), thus can be checked with ===
3345
+ *
3346
+ * @param {array} promises array of promises to race
3347
+ * @returns {Promise} if input is non-empty, a promise that will settle
3348
+ * to the same outcome as the earliest input promise to settle. if empty
3349
+ * is empty, returns a promise that will never settle.
3350
+ */
3351
+ function race(promises) {
3352
+ // Sigh, race([]) is untestable unless we return *something*
3353
+ // that is recognizable without calling .then() on it.
3354
+ if(Object(promises) === promises && promises.length === 0) {
3355
+ return never();
3356
+ }
3357
+
3358
+ var h = new Pending();
3359
+ var i, x;
3360
+ for(i=0; i<promises.length; ++i) {
3361
+ x = promises[i];
3362
+ if (x !== void 0 && i in promises) {
3363
+ getHandler(x).visit(h, h.resolve, h.reject);
3364
+ }
3365
+ }
3366
+ return new Promise(Handler, h);
3367
+ }
3368
+
3369
+ // Promise internals
3370
+ // Below this, everything is @private
3371
+
3372
+ /**
3373
+ * Get an appropriate handler for x, without checking for cycles
3374
+ * @param {*} x
3375
+ * @returns {object} handler
3376
+ */
3377
+ function getHandler(x) {
3378
+ if(isPromise(x)) {
3379
+ return x._handler.join();
3380
+ }
3381
+ return maybeThenable(x) ? getHandlerUntrusted(x) : new Fulfilled(x);
3382
+ }
3383
+
3384
+ /**
3385
+ * Get a handler for thenable x.
3386
+ * NOTE: You must only call this if maybeThenable(x) == true
3387
+ * @param {object|function|Promise} x
3388
+ * @returns {object} handler
3389
+ */
3390
+ function getHandlerMaybeThenable(x) {
3391
+ return isPromise(x) ? x._handler.join() : getHandlerUntrusted(x);
3392
+ }
3393
+
3394
+ /**
3395
+ * Get a handler for potentially untrusted thenable x
3396
+ * @param {*} x
3397
+ * @returns {object} handler
3398
+ */
3399
+ function getHandlerUntrusted(x) {
3400
+ try {
3401
+ var untrustedThen = x.then;
3402
+ return typeof untrustedThen === 'function'
3403
+ ? new Thenable(untrustedThen, x)
3404
+ : new Fulfilled(x);
3405
+ } catch(e) {
3406
+ return new Rejected(e);
3407
+ }
3408
+ }
3409
+
3410
+ /**
3411
+ * Handler for a promise that is pending forever
3412
+ * @constructor
3413
+ */
3414
+ function Handler() {}
3415
+
3416
+ Handler.prototype.when
3417
+ = Handler.prototype.become
3418
+ = Handler.prototype.notify
3419
+ = Handler.prototype.fail
3420
+ = Handler.prototype._unreport
3421
+ = Handler.prototype._report
3422
+ = noop;
3423
+
3424
+ Handler.prototype._state = 0;
3425
+
3426
+ Handler.prototype.state = function() {
3427
+ return this._state;
3428
+ };
3429
+
3430
+ /**
3431
+ * Recursively collapse handler chain to find the handler
3432
+ * nearest to the fully resolved value.
3433
+ * @returns {object} handler nearest the fully resolved value
3434
+ */
3435
+ Handler.prototype.join = function() {
3436
+ var h = this;
3437
+ while(h.handler !== void 0) {
3438
+ h = h.handler;
3439
+ }
3440
+ return h;
3441
+ };
3442
+
3443
+ Handler.prototype.chain = function(to, receiver, fulfilled, rejected, progress) {
3444
+ this.when({
3445
+ resolver: to,
3446
+ receiver: receiver,
3447
+ fulfilled: fulfilled,
3448
+ rejected: rejected,
3449
+ progress: progress
3450
+ });
3451
+ };
3452
+
3453
+ Handler.prototype.visit = function(receiver, fulfilled, rejected, progress) {
3454
+ this.chain(failIfRejected, receiver, fulfilled, rejected, progress);
3455
+ };
3456
+
3457
+ Handler.prototype.fold = function(f, z, c, to) {
3458
+ this.visit(to, function(x) {
3459
+ f.call(c, z, x, this);
3460
+ }, to.reject, to.notify);
3461
+ };
3462
+
3463
+ /**
3464
+ * Handler that invokes fail() on any handler it becomes
3465
+ * @constructor
3466
+ */
3467
+ function FailIfRejected() {}
3468
+
3469
+ inherit(Handler, FailIfRejected);
3470
+
3471
+ FailIfRejected.prototype.become = function(h) {
3472
+ h.fail();
3473
+ };
3474
+
3475
+ var failIfRejected = new FailIfRejected();
3476
+
3477
+ /**
3478
+ * Handler that manages a queue of consumers waiting on a pending promise
3479
+ * @constructor
3480
+ */
3481
+ function Pending(receiver, inheritedContext) {
3482
+ Promise.createContext(this, inheritedContext);
3483
+
3484
+ this.consumers = void 0;
3485
+ this.receiver = receiver;
3486
+ this.handler = void 0;
3487
+ this.resolved = false;
3488
+ }
3489
+
3490
+ inherit(Handler, Pending);
3491
+
3492
+ Pending.prototype._state = 0;
3493
+
3494
+ Pending.prototype.resolve = function(x) {
3495
+ this.become(getHandler(x));
3496
+ };
3497
+
3498
+ Pending.prototype.reject = function(x) {
3499
+ if(this.resolved) {
3500
+ return;
3501
+ }
3502
+
3503
+ this.become(new Rejected(x));
3504
+ };
3505
+
3506
+ Pending.prototype.join = function() {
3507
+ if (!this.resolved) {
3508
+ return this;
3509
+ }
3510
+
3511
+ var h = this;
3512
+
3513
+ while (h.handler !== void 0) {
3514
+ h = h.handler;
3515
+ if (h === this) {
3516
+ return this.handler = cycle();
3517
+ }
3518
+ }
3519
+
3520
+ return h;
3521
+ };
3522
+
3523
+ Pending.prototype.run = function() {
3524
+ var q = this.consumers;
3525
+ var handler = this.join();
3526
+ this.consumers = void 0;
3527
+
3528
+ for (var i = 0; i < q.length; ++i) {
3529
+ handler.when(q[i]);
3530
+ }
3531
+ };
3532
+
3533
+ Pending.prototype.become = function(handler) {
3534
+ if(this.resolved) {
3535
+ return;
3536
+ }
3537
+
3538
+ this.resolved = true;
3539
+ this.handler = handler;
3540
+ if(this.consumers !== void 0) {
3541
+ tasks.enqueue(this);
3542
+ }
3543
+
3544
+ if(this.context !== void 0) {
3545
+ handler._report(this.context);
3546
+ }
3547
+ };
3548
+
3549
+ Pending.prototype.when = function(continuation) {
3550
+ if(this.resolved) {
3551
+ tasks.enqueue(new ContinuationTask(continuation, this.handler));
3552
+ } else {
3553
+ if(this.consumers === void 0) {
3554
+ this.consumers = [continuation];
3555
+ } else {
3556
+ this.consumers.push(continuation);
3557
+ }
3558
+ }
3559
+ };
3560
+
3561
+ Pending.prototype.notify = function(x) {
3562
+ if(!this.resolved) {
3563
+ tasks.enqueue(new ProgressTask(x, this));
3564
+ }
3565
+ };
3566
+
3567
+ Pending.prototype.fail = function(context) {
3568
+ var c = typeof context === 'undefined' ? this.context : context;
3569
+ this.resolved && this.handler.join().fail(c);
3570
+ };
3571
+
3572
+ Pending.prototype._report = function(context) {
3573
+ this.resolved && this.handler.join()._report(context);
3574
+ };
3575
+
3576
+ Pending.prototype._unreport = function() {
3577
+ this.resolved && this.handler.join()._unreport();
3578
+ };
3579
+
3580
+ /**
3581
+ * Wrap another handler and force it into a future stack
3582
+ * @param {object} handler
3583
+ * @constructor
3584
+ */
3585
+ function Async(handler) {
3586
+ this.handler = handler;
3587
+ }
3588
+
3589
+ inherit(Handler, Async);
3590
+
3591
+ Async.prototype.when = function(continuation) {
3592
+ tasks.enqueue(new ContinuationTask(continuation, this));
3593
+ };
3594
+
3595
+ Async.prototype._report = function(context) {
3596
+ this.join()._report(context);
3597
+ };
3598
+
3599
+ Async.prototype._unreport = function() {
3600
+ this.join()._unreport();
3601
+ };
3602
+
3603
+ /**
3604
+ * Handler that wraps an untrusted thenable and assimilates it in a future stack
3605
+ * @param {function} then
3606
+ * @param {{then: function}} thenable
3607
+ * @constructor
3608
+ */
3609
+ function Thenable(then, thenable) {
3610
+ Pending.call(this);
3611
+ tasks.enqueue(new AssimilateTask(then, thenable, this));
3612
+ }
3613
+
3614
+ inherit(Pending, Thenable);
3615
+
3616
+ /**
3617
+ * Handler for a fulfilled promise
3618
+ * @param {*} x fulfillment value
3619
+ * @constructor
3620
+ */
3621
+ function Fulfilled(x) {
3622
+ Promise.createContext(this);
3623
+ this.value = x;
3624
+ }
3625
+
3626
+ inherit(Handler, Fulfilled);
3627
+
3628
+ Fulfilled.prototype._state = 1;
3629
+
3630
+ Fulfilled.prototype.fold = function(f, z, c, to) {
3631
+ runContinuation3(f, z, this, c, to);
3632
+ };
3633
+
3634
+ Fulfilled.prototype.when = function(cont) {
3635
+ runContinuation1(cont.fulfilled, this, cont.receiver, cont.resolver);
3636
+ };
3637
+
3638
+ var errorId = 0;
3639
+
3640
+ /**
3641
+ * Handler for a rejected promise
3642
+ * @param {*} x rejection reason
3643
+ * @constructor
3644
+ */
3645
+ function Rejected(x) {
3646
+ Promise.createContext(this);
3647
+
3648
+ this.id = ++errorId;
3649
+ this.value = x;
3650
+ this.handled = false;
3651
+ this.reported = false;
3652
+
3653
+ this._report();
3654
+ }
3655
+
3656
+ inherit(Handler, Rejected);
3657
+
3658
+ Rejected.prototype._state = -1;
3659
+
3660
+ Rejected.prototype.fold = function(f, z, c, to) {
3661
+ to.become(this);
3662
+ };
3663
+
3664
+ Rejected.prototype.when = function(cont) {
3665
+ if(typeof cont.rejected === 'function') {
3666
+ this._unreport();
3667
+ }
3668
+ runContinuation1(cont.rejected, this, cont.receiver, cont.resolver);
3669
+ };
3670
+
3671
+ Rejected.prototype._report = function(context) {
3672
+ tasks.afterQueue(new ReportTask(this, context));
3673
+ };
3674
+
3675
+ Rejected.prototype._unreport = function() {
3676
+ this.handled = true;
3677
+ tasks.afterQueue(new UnreportTask(this));
3678
+ };
3679
+
3680
+ Rejected.prototype.fail = function(context) {
3681
+ Promise.onFatalRejection(this, context === void 0 ? this.context : context);
3682
+ };
3683
+
3684
+ function ReportTask(rejection, context) {
3685
+ this.rejection = rejection;
3686
+ this.context = context;
3687
+ }
3688
+
3689
+ ReportTask.prototype.run = function() {
3690
+ if(!this.rejection.handled) {
3691
+ this.rejection.reported = true;
3692
+ Promise.onPotentiallyUnhandledRejection(this.rejection, this.context);
3693
+ }
3694
+ };
3695
+
3696
+ function UnreportTask(rejection) {
3697
+ this.rejection = rejection;
3698
+ }
3699
+
3700
+ UnreportTask.prototype.run = function() {
3701
+ if(this.rejection.reported) {
3702
+ Promise.onPotentiallyUnhandledRejectionHandled(this.rejection);
3703
+ }
3704
+ };
3705
+
3706
+ // Unhandled rejection hooks
3707
+ // By default, everything is a noop
3708
+
3709
+ // TODO: Better names: "annotate"?
3710
+ Promise.createContext
3711
+ = Promise.enterContext
3712
+ = Promise.exitContext
3713
+ = Promise.onPotentiallyUnhandledRejection
3714
+ = Promise.onPotentiallyUnhandledRejectionHandled
3715
+ = Promise.onFatalRejection
3716
+ = noop;
3717
+
3718
+ // Errors and singletons
3719
+
3720
+ var foreverPendingHandler = new Handler();
3721
+ var foreverPendingPromise = new Promise(Handler, foreverPendingHandler);
3722
+
3723
+ function cycle() {
3724
+ return new Rejected(new TypeError('Promise cycle'));
3725
+ }
3726
+
3727
+ // Task runners
3728
+
3729
+ /**
3730
+ * Run a single consumer
3731
+ * @constructor
3732
+ */
3733
+ function ContinuationTask(continuation, handler) {
3734
+ this.continuation = continuation;
3735
+ this.handler = handler;
3736
+ }
3737
+
3738
+ ContinuationTask.prototype.run = function() {
3739
+ this.handler.join().when(this.continuation);
3740
+ };
3741
+
3742
+ /**
3743
+ * Run a queue of progress handlers
3744
+ * @constructor
3745
+ */
3746
+ function ProgressTask(value, handler) {
3747
+ this.handler = handler;
3748
+ this.value = value;
3749
+ }
3750
+
3751
+ ProgressTask.prototype.run = function() {
3752
+ var q = this.handler.consumers;
3753
+ if(q === void 0) {
3754
+ return;
3755
+ }
3756
+
3757
+ for (var c, i = 0; i < q.length; ++i) {
3758
+ c = q[i];
3759
+ runNotify(c.progress, this.value, this.handler, c.receiver, c.resolver);
3760
+ }
3761
+ };
3762
+
3763
+ /**
3764
+ * Assimilate a thenable, sending it's value to resolver
3765
+ * @param {function} then
3766
+ * @param {object|function} thenable
3767
+ * @param {object} resolver
3768
+ * @constructor
3769
+ */
3770
+ function AssimilateTask(then, thenable, resolver) {
3771
+ this._then = then;
3772
+ this.thenable = thenable;
3773
+ this.resolver = resolver;
3774
+ }
3775
+
3776
+ AssimilateTask.prototype.run = function() {
3777
+ var h = this.resolver;
3778
+ tryAssimilate(this._then, this.thenable, _resolve, _reject, _notify);
3779
+
3780
+ function _resolve(x) { h.resolve(x); }
3781
+ function _reject(x) { h.reject(x); }
3782
+ function _notify(x) { h.notify(x); }
3783
+ };
3784
+
3785
+ function tryAssimilate(then, thenable, resolve, reject, notify) {
3786
+ try {
3787
+ then.call(thenable, resolve, reject, notify);
3788
+ } catch (e) {
3789
+ reject(e);
3790
+ }
3791
+ }
3792
+
3793
+ // Other helpers
3794
+
3795
+ /**
3796
+ * @param {*} x
3797
+ * @returns {boolean} true iff x is a trusted Promise
3798
+ */
3799
+ function isPromise(x) {
3800
+ return x instanceof Promise;
3801
+ }
3802
+
3803
+ /**
3804
+ * Test just enough to rule out primitives, in order to take faster
3805
+ * paths in some code
3806
+ * @param {*} x
3807
+ * @returns {boolean} false iff x is guaranteed *not* to be a thenable
3808
+ */
3809
+ function maybeThenable(x) {
3810
+ return (typeof x === 'object' || typeof x === 'function') && x !== null;
3811
+ }
3812
+
3813
+ function runContinuation1(f, h, receiver, next) {
3814
+ if(typeof f !== 'function') {
3815
+ return next.become(h);
3816
+ }
3817
+
3818
+ Promise.enterContext(h);
3819
+ tryCatchReject(f, h.value, receiver, next);
3820
+ Promise.exitContext();
3821
+ }
3822
+
3823
+ function runContinuation3(f, x, h, receiver, next) {
3824
+ if(typeof f !== 'function') {
3825
+ return next.become(h);
3826
+ }
3827
+
3828
+ Promise.enterContext(h);
3829
+ tryCatchReject3(f, x, h.value, receiver, next);
3830
+ Promise.exitContext();
3831
+ }
3832
+
3833
+ function runNotify(f, x, h, receiver, next) {
3834
+ if(typeof f !== 'function') {
3835
+ return next.notify(x);
3836
+ }
3837
+
3838
+ Promise.enterContext(h);
3839
+ tryCatchReturn(f, x, receiver, next);
3840
+ Promise.exitContext();
3841
+ }
3842
+
3843
+ /**
3844
+ * Return f.call(thisArg, x), or if it throws return a rejected promise for
3845
+ * the thrown exception
3846
+ */
3847
+ function tryCatchReject(f, x, thisArg, next) {
3848
+ try {
3849
+ next.become(getHandler(f.call(thisArg, x)));
3850
+ } catch(e) {
3851
+ next.become(new Rejected(e));
3852
+ }
3853
+ }
3854
+
3855
+ /**
3856
+ * Same as above, but includes the extra argument parameter.
3857
+ */
3858
+ function tryCatchReject3(f, x, y, thisArg, next) {
3859
+ try {
3860
+ f.call(thisArg, x, y, next);
3861
+ } catch(e) {
3862
+ next.become(new Rejected(e));
3863
+ }
3864
+ }
3865
+
3866
+ /**
3867
+ * Return f.call(thisArg, x), or if it throws, *return* the exception
3868
+ */
3869
+ function tryCatchReturn(f, x, thisArg, next) {
3870
+ try {
3871
+ next.notify(f.call(thisArg, x));
3872
+ } catch(e) {
3873
+ next.notify(e);
3874
+ }
3875
+ }
3876
+
3877
+ function inherit(Parent, Child) {
3878
+ Child.prototype = objectCreate(Parent.prototype);
3879
+ Child.prototype.constructor = Child;
3880
+ }
3881
+
3882
+ function noop() {}
3883
+
3884
+ return Promise;
3885
+ };
3886
+ });
3887
+ }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
3888
+
3889
+ },{}]},{},[10])
3890
+ (10)
3891
+ });