!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 component is a special kind of that * renders when its parent matches but none of its siblings do. * Only one such route may be used at any given level in the * route hierarchy. */ var DefaultRoute = React.createClass({ displayName: 'DefaultRoute', mixins: [ FakeNode ], propTypes: { name: React.PropTypes.string, path: PropTypes.falsy, handler: React.PropTypes.func.isRequired } }); module.exports = DefaultRoute; },{"../mixins/FakeNode":13,"../utils/PropTypes":21}],4:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); var classSet = _dereq_('react/lib/cx'); var assign = _dereq_('react/lib/Object.assign'); var Navigation = _dereq_('../mixins/Navigation'); var State = _dereq_('../mixins/State'); function isLeftClickEvent(event) { return event.button === 0; } function isModifiedEvent(event) { return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); } /** * components are used to create an element that links to a route. * When that route is active, the link gets an "active" class name (or the * value of its `activeClassName` prop). * * For example, assuming you have the following route: * * * * You could use the following component to link to that route: * * * * In addition to params, links may pass along query string parameters * using the `query` prop. * * */ var Link = React.createClass({ displayName: 'Link', mixins: [ Navigation, State ], propTypes: { activeClassName: React.PropTypes.string.isRequired, to: React.PropTypes.string.isRequired, params: React.PropTypes.object, query: React.PropTypes.object, onClick: React.PropTypes.func }, getDefaultProps: function () { return { activeClassName: 'active' }; }, handleClick: function (event) { var allowTransition = true; var clickResult; if (this.props.onClick) clickResult = this.props.onClick(event); if (isModifiedEvent(event) || !isLeftClickEvent(event)) return; if (clickResult === false || event.defaultPrevented === true) allowTransition = false; event.preventDefault(); if (allowTransition) this.transitionTo(this.props.to, this.props.params, this.props.query); }, /** * Returns the value of the "href" attribute to use on the DOM element. */ getHref: function () { return this.makeHref(this.props.to, this.props.params, this.props.query); }, /** * Returns the value of the "class" attribute to use on the DOM element, which contains * the value of the activeClassName property when this is active. */ getClassName: function () { var classNames = {}; if (this.props.className) classNames[this.props.className] = true; if (this.isActive(this.props.to, this.props.params, this.props.query)) classNames[this.props.activeClassName] = true; return classSet(classNames); }, render: function () { var props = assign({}, this.props, { href: this.getHref(), className: this.getClassName(), onClick: this.handleClick }); return React.DOM.a(props, this.props.children); } }); module.exports = Link; },{"../mixins/Navigation":14,"../mixins/State":17,"react/lib/Object.assign":36,"react/lib/cx":37}],5:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); var FakeNode = _dereq_('../mixins/FakeNode'); var PropTypes = _dereq_('../utils/PropTypes'); /** * A is a special kind of that * renders when the beginning of its parent's path matches * but none of its siblings do, including any . * Only one such route may be used at any given level in the * route hierarchy. */ var NotFoundRoute = React.createClass({ displayName: 'NotFoundRoute', mixins: [ FakeNode ], propTypes: { name: React.PropTypes.string, path: PropTypes.falsy, handler: React.PropTypes.func.isRequired } }); module.exports = NotFoundRoute; },{"../mixins/FakeNode":13,"../utils/PropTypes":21}],6:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); var FakeNode = _dereq_('../mixins/FakeNode'); var PropTypes = _dereq_('../utils/PropTypes'); /** * A component is a special kind of that always * redirects to another route when it matches. */ var Redirect = React.createClass({ displayName: 'Redirect', mixins: [ FakeNode ], propTypes: { path: React.PropTypes.string, from: React.PropTypes.string, // Alias for path. to: React.PropTypes.string, handler: PropTypes.falsy } }); module.exports = Redirect; },{"../mixins/FakeNode":13,"../utils/PropTypes":21}],7:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); var FakeNode = _dereq_('../mixins/FakeNode'); /** * components specify components that are rendered to the page when the * URL matches a given pattern. * * Routes are arranged in a nested tree structure. When a new URL is requested, * the tree is searched depth-first to find a route whose path matches the URL. * When one is found, all routes in the tree that lead to it are considered * "active" and their components are rendered into the DOM, nested in the same * order as they are in the tree. * * The preferred way to configure a router is using JSX. The XML-like syntax is * a great way to visualize how routes are laid out in an application. * * var routes = [ * * * * * * ]; * * Router.run(routes, function (Handler) { * React.render(, document.body); * }); * * Handlers for Route components that contain children can render their active * child route using a element. * * var App = React.createClass({ * render: function () { * return ( *
* *
* ); * } * }); */ var Route = React.createClass({ displayName: 'Route', mixins: [ FakeNode ], propTypes: { name: React.PropTypes.string, path: React.PropTypes.string, handler: React.PropTypes.func.isRequired, ignoreScrollBehavior: React.PropTypes.bool } }); module.exports = Route; },{"../mixins/FakeNode":13}],8:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); /** * A component renders the active child route handler * when routes are nested. */ var RouteHandler = React.createClass({ displayName: 'RouteHandler', getDefaultProps: function () { return { ref: '__routeHandler__' }; }, contextTypes: { getRouteAtDepth: React.PropTypes.func.isRequired, getRouteComponents: React.PropTypes.func.isRequired, routeHandlers: React.PropTypes.array.isRequired }, childContextTypes: { routeHandlers: React.PropTypes.array.isRequired }, getChildContext: function () { return { routeHandlers: this.context.routeHandlers.concat([ this ]) }; }, getRouteDepth: function () { return this.context.routeHandlers.length - 1; }, componentDidMount: function () { this._updateRouteComponent(); }, componentDidUpdate: function () { this._updateRouteComponent(); }, _updateRouteComponent: function () { var depth = this.getRouteDepth(); var components = this.context.getRouteComponents(); components[depth] = this.refs[this.props.ref]; }, render: function () { var route = this.context.getRouteAtDepth(this.getRouteDepth()); return route ? React.createElement(route.handler, this.props) : null; } }); module.exports = RouteHandler; },{}],9:[function(_dereq_,module,exports){ exports.DefaultRoute = _dereq_('./components/DefaultRoute'); exports.Link = _dereq_('./components/Link'); exports.NotFoundRoute = _dereq_('./components/NotFoundRoute'); exports.Redirect = _dereq_('./components/Redirect'); exports.Route = _dereq_('./components/Route'); exports.RouteHandler = _dereq_('./components/RouteHandler'); exports.HashLocation = _dereq_('./locations/HashLocation'); exports.HistoryLocation = _dereq_('./locations/HistoryLocation'); exports.RefreshLocation = _dereq_('./locations/RefreshLocation'); exports.Navigation = _dereq_('./mixins/Navigation'); exports.State = _dereq_('./mixins/State'); exports.create = _dereq_('./utils/createRouter'); exports.run = _dereq_('./utils/runRouter'); },{"./components/DefaultRoute":3,"./components/Link":4,"./components/NotFoundRoute":5,"./components/Redirect":6,"./components/Route":7,"./components/RouteHandler":8,"./locations/HashLocation":10,"./locations/HistoryLocation":11,"./locations/RefreshLocation":12,"./mixins/Navigation":14,"./mixins/State":17,"./utils/createRouter":24,"./utils/runRouter":28}],10:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; var LocationActions = _dereq_('../actions/LocationActions'); var Path = _dereq_('../utils/Path'); /** * Returns the current URL path from `window.location.hash`, including query string */ function getHashPath() { invariant( canUseDOM, 'getHashPath needs a DOM' ); return Path.decode( window.location.hash.substr(1) ); } var _actionType; function ensureSlash() { var path = getHashPath(); if (path.charAt(0) === '/') return true; HashLocation.replace('/' + path); return false; } var _changeListeners = []; function notifyChange(type) { var change = { path: getHashPath(), type: type }; _changeListeners.forEach(function (listener) { listener(change); }); } var _isListening = false; function onHashChange() { if (ensureSlash()) { // If we don't have an _actionType then all we know is the hash // changed. It was probably caused by the user clicking the Back // button, but may have also been the Forward button or manual // manipulation. So just guess 'pop'. notifyChange(_actionType || LocationActions.POP); _actionType = null; } } /** * A Location that uses `window.location.hash`. */ var HashLocation = { addChangeListener: function (listener) { _changeListeners.push(listener); // Do this BEFORE listening for hashchange. ensureSlash(); if (_isListening) return; if (window.addEventListener) { window.addEventListener('hashchange', onHashChange, false); } else { window.attachEvent('onhashchange', onHashChange); } _isListening = true; }, push: function (path) { _actionType = LocationActions.PUSH; window.location.hash = Path.encode(path); }, replace: function (path) { _actionType = LocationActions.REPLACE; window.location.replace(window.location.pathname + '#' + Path.encode(path)); }, pop: function () { _actionType = LocationActions.POP; window.history.back(); }, getCurrentPath: getHashPath, toString: function () { return ''; } }; module.exports = HashLocation; },{"../actions/LocationActions":1,"../utils/Path":19,"react/lib/ExecutionEnvironment":35,"react/lib/invariant":39}],11:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; var LocationActions = _dereq_('../actions/LocationActions'); var Path = _dereq_('../utils/Path'); /** * Returns the current URL path from `window.location`, including query string */ function getWindowPath() { invariant( canUseDOM, 'getWindowPath needs a DOM' ); return Path.decode( window.location.pathname + window.location.search ); } var _changeListeners = []; function notifyChange(type) { var change = { path: getWindowPath(), type: type }; _changeListeners.forEach(function (listener) { listener(change); }); } var _isListening = false; function onPopState() { notifyChange(LocationActions.POP); } /** * A Location that uses HTML5 history. */ var HistoryLocation = { addChangeListener: function (listener) { _changeListeners.push(listener); if (_isListening) return; if (window.addEventListener) { window.addEventListener('popstate', onPopState, false); } else { window.attachEvent('popstate', onPopState); } _isListening = true; }, push: function (path) { window.history.pushState({ path: path }, '', Path.encode(path)); notifyChange(LocationActions.PUSH); }, replace: function (path) { window.history.replaceState({ path: path }, '', Path.encode(path)); notifyChange(LocationActions.REPLACE); }, pop: function () { window.history.back(); }, getCurrentPath: getWindowPath, toString: function () { return ''; } }; module.exports = HistoryLocation; },{"../actions/LocationActions":1,"../utils/Path":19,"react/lib/ExecutionEnvironment":35,"react/lib/invariant":39}],12:[function(_dereq_,module,exports){ var HistoryLocation = _dereq_('./HistoryLocation'); var Path = _dereq_('../utils/Path'); /** * A Location that uses full page refreshes. This is used as * the fallback for HistoryLocation in browsers that do not * support the HTML5 history API. */ var RefreshLocation = { push: function (path) { window.location = Path.encode(path); }, replace: function (path) { window.location.replace(Path.encode(path)); }, pop: function () { window.history.back(); }, getCurrentPath: HistoryLocation.getCurrentPath, toString: function () { return ''; } }; module.exports = RefreshLocation; },{"../utils/Path":19,"./HistoryLocation":11}],13:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); var FakeNode = { render: function () { invariant( false, '%s elements should not be rendered', this.constructor.displayName ); } }; module.exports = FakeNode; },{"react/lib/invariant":39}],14:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); /** * A mixin for components that modify the URL. * * Example: * * var MyLink = React.createClass({ * mixins: [ Router.Navigation ], * handleClick: function (event) { * event.preventDefault(); * this.transitionTo('aRoute', { the: 'params' }, { the: 'query' }); * }, * render: function () { * return ( *
Click me! * ); * } * }); */ var Navigation = { contextTypes: { makePath: React.PropTypes.func.isRequired, makeHref: React.PropTypes.func.isRequired, transitionTo: React.PropTypes.func.isRequired, replaceWith: React.PropTypes.func.isRequired, goBack: React.PropTypes.func.isRequired }, /** * Returns an absolute URL path created from the given route * name, URL parameters, and query values. */ makePath: function (to, params, query) { return this.context.makePath(to, params, query); }, /** * Returns a string that may safely be used as the href of a * link to the route with the given name. */ makeHref: function (to, params, query) { return this.context.makeHref(to, params, query); }, /** * Transitions to the URL specified in the arguments by pushing * a new URL onto the history stack. */ transitionTo: function (to, params, query) { this.context.transitionTo(to, params, query); }, /** * Transitions to the URL specified in the arguments by replacing * the current URL in the history stack. */ replaceWith: function (to, params, query) { this.context.replaceWith(to, params, query); }, /** * Transitions to the previous URL. */ goBack: function () { this.context.goBack(); } }; module.exports = Navigation; },{}],15:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); /** * Provides the router with context for Router.Navigation. */ var NavigationContext = { childContextTypes: { makePath: React.PropTypes.func.isRequired, makeHref: React.PropTypes.func.isRequired, transitionTo: React.PropTypes.func.isRequired, replaceWith: React.PropTypes.func.isRequired, goBack: React.PropTypes.func.isRequired }, getChildContext: function () { return { makePath: this.constructor.makePath, makeHref: this.constructor.makeHref, transitionTo: this.constructor.transitionTo, replaceWith: this.constructor.replaceWith, goBack: this.constructor.goBack }; } }; module.exports = NavigationContext; },{}],16:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; var getWindowScrollPosition = _dereq_('../utils/getWindowScrollPosition'); /** * Provides the router with the ability to manage window scroll position * according to its scroll behavior. */ var Scrolling = { componentWillMount: function () { invariant( this.getScrollBehavior() == null || canUseDOM, 'Cannot use scroll behavior without a DOM' ); this._scrollHistory = {}; }, componentDidMount: function () { this._updateScroll(); }, componentWillUpdate: function () { this._scrollHistory[this.state.path] = getWindowScrollPosition(); }, componentDidUpdate: function () { this._updateScroll(); }, componentWillUnmount: function () { delete this._scrollHistory; }, /** * Returns the last known scroll position for the given URL path. */ getScrollPosition: function (path) { return this._scrollHistory[path] || null; }, _updateScroll: function () { var scrollBehavior = this.getScrollBehavior(); if (scrollBehavior) scrollBehavior.updateScrollPosition( this.getScrollPosition(this.state.path), this.state.action ); } }; module.exports = Scrolling; },{"../utils/getWindowScrollPosition":26,"react/lib/ExecutionEnvironment":35,"react/lib/invariant":39}],17:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); /** * A mixin for components that need to know the path, routes, URL * params and query that are currently active. * * Example: * * var AboutLink = React.createClass({ * mixins: [ Router.State ], * render: function () { * var className = this.props.className; * * if (this.isActive('about')) * className += ' is-active'; * * return React.DOM.a({ className: className }, this.props.children); * } * }); */ var State = { contextTypes: { getCurrentPath: React.PropTypes.func.isRequired, getCurrentRoutes: React.PropTypes.func.isRequired, getCurrentParams: React.PropTypes.func.isRequired, getCurrentQuery: React.PropTypes.func.isRequired, isActive: React.PropTypes.func.isRequired }, /** * Returns the current URL path. */ getPath: function () { return this.context.getCurrentPath(); }, /** * Returns an array of the routes that are currently active. */ getRoutes: function () { return this.context.getCurrentRoutes(); }, /** * Returns an object of the URL params that are currently active. */ getParams: function () { return this.context.getCurrentParams(); }, /** * Returns an object of the query params that are currently active. */ getQuery: function () { return this.context.getCurrentQuery(); }, /** * A helper method to determine if a given route, params, and query * are active. */ isActive: function (to, params, query) { return this.context.isActive(to, params, query); } }; module.exports = State; },{}],18:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); var assign = _dereq_('react/lib/Object.assign'); var Path = _dereq_('../utils/Path'); function routeIsActive(activeRoutes, routeName) { return activeRoutes.some(function (route) { return route.name === routeName; }); } function paramsAreActive(activeParams, params) { for (var property in params) if (String(activeParams[property]) !== String(params[property])) return false; return true; } function queryIsActive(activeQuery, query) { for (var property in query) if (String(activeQuery[property]) !== String(query[property])) return false; return true; } /** * Provides the router with context for Router.State. */ var StateContext = { /** * Returns the current URL path + query string. */ getCurrentPath: function () { return this.state.path; }, /** * Returns a read-only array of the currently active routes. */ getCurrentRoutes: function () { return this.state.routes.slice(0); }, /** * Returns a read-only object of the currently active URL parameters. */ getCurrentParams: function () { return assign({}, this.state.params); }, /** * Returns a read-only object of the currently active query parameters. */ getCurrentQuery: function () { return assign({}, this.state.query); }, /** * Returns true if the given route, params, and query are active. */ isActive: function (to, params, query) { if (Path.isAbsolute(to)) return to === this.state.path; return routeIsActive(this.state.routes, to) && paramsAreActive(this.state.params, params) && (query == null || queryIsActive(this.state.query, query)); }, childContextTypes: { getCurrentPath: React.PropTypes.func.isRequired, getCurrentRoutes: React.PropTypes.func.isRequired, getCurrentParams: React.PropTypes.func.isRequired, getCurrentQuery: React.PropTypes.func.isRequired, isActive: React.PropTypes.func.isRequired }, getChildContext: function () { return { getCurrentPath: this.getCurrentPath, getCurrentRoutes: this.getCurrentRoutes, getCurrentParams: this.getCurrentParams, getCurrentQuery: this.getCurrentQuery, isActive: this.isActive }; } }; module.exports = StateContext; },{"../utils/Path":19,"react/lib/Object.assign":36}],19:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); var merge = _dereq_('qs/lib/utils').merge; var qs = _dereq_('qs'); var paramCompileMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$]*)|[*.()\[\]\\+|{}^$]/g; var paramInjectMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$?]*[?]?)|[*]/g; var paramInjectTrailingSlashMatcher = /\/\/\?|\/\?/g; var queryMatcher = /\?(.+)/; var _compiledPatterns = {}; function compilePattern(pattern) { if (!(pattern in _compiledPatterns)) { var paramNames = []; var source = pattern.replace(paramCompileMatcher, function (match, paramName) { if (paramName) { paramNames.push(paramName); return '([^/?#]+)'; } else if (match === '*') { paramNames.push('splat'); return '(.*?)'; } else { return '\\' + match; } }); _compiledPatterns[pattern] = { matcher: new RegExp('^' + source + '$', 'i'), paramNames: paramNames }; } return _compiledPatterns[pattern]; } var Path = { /** * Safely decodes special characters in the given URL path. */ decode: function (path) { return decodeURI(path.replace(/\+/g, ' ')); }, /** * Safely encodes special characters in the given URL path. */ encode: function (path) { return encodeURI(path).replace(/%20/g, '+'); }, /** * Returns an array of the names of all parameters in the given pattern. */ extractParamNames: function (pattern) { return compilePattern(pattern).paramNames; }, /** * Extracts the portions of the given URL path that match the given pattern * and returns an object of param name => value pairs. Returns null if the * pattern does not match the given path. */ extractParams: function (pattern, path) { var object = compilePattern(pattern); var match = path.match(object.matcher); if (!match) return null; var params = {}; object.paramNames.forEach(function (paramName, index) { params[paramName] = match[index + 1]; }); return params; }, /** * Returns a version of the given route path with params interpolated. Throws * if there is a dynamic segment of the route path for which there is no param. */ injectParams: function (pattern, params) { params = params || {}; var splatIndex = 0; return pattern.replace(paramInjectMatcher, function (match, paramName) { paramName = paramName || 'splat'; // If param is optional don't check for existence if (paramName.slice(-1) !== '?') { invariant( params[paramName] != null, 'Missing "' + paramName + '" parameter for path "' + pattern + '"' ); } else { paramName = paramName.slice(0, -1); if (params[paramName] == null) return ''; } var segment; if (paramName === 'splat' && Array.isArray(params[paramName])) { segment = params[paramName][splatIndex++]; invariant( segment != null, 'Missing splat # ' + splatIndex + ' for path "' + pattern + '"' ); } else { segment = params[paramName]; } return segment; }).replace(paramInjectTrailingSlashMatcher, '/'); }, /** * Returns an object that is the result of parsing any query string contained * in the given path, null if the path contains no query string. */ extractQuery: function (path) { var match = path.match(queryMatcher); return match && qs.parse(match[1]); }, /** * Returns a version of the given path without the query string. */ withoutQuery: function (path) { return path.replace(queryMatcher, ''); }, /** * Returns a version of the given path with the parameters in the given * query merged into the query string. */ withQuery: function (path, query) { var existingQuery = Path.extractQuery(path); if (existingQuery) query = query ? merge(existingQuery, query) : existingQuery; var queryString = query && qs.stringify(query); if (queryString) return Path.withoutQuery(path) + '?' + queryString; return path; }, /** * Returns true if the given path is absolute. */ isAbsolute: function (path) { return path.charAt(0) === '/'; }, /** * Returns a normalized version of the given path. */ normalize: function (path, parentRoute) { return path.replace(/^\/*/, '/'); }, /** * Joins two URL paths together. */ join: function (a, b) { return a.replace(/\/*$/, '/') + b; } }; module.exports = Path; },{"qs":30,"qs/lib/utils":34,"react/lib/invariant":39}],20:[function(_dereq_,module,exports){ var Promise = _dereq_('when/lib/Promise'); // TODO: Use process.env.NODE_ENV check + envify to enable // when's promise monitor here when in dev. module.exports = Promise; },{"when/lib/Promise":41}],21:[function(_dereq_,module,exports){ var PropTypes = { /** * Requires that the value of a prop be falsy. */ falsy: function (props, propName, elementName) { if (props[propName]) return new Error('<' + elementName + '> may not have a "' + propName + '" prop'); } }; module.exports = PropTypes; },{}],22:[function(_dereq_,module,exports){ /** * Encapsulates a redirect to the given route. */ function Redirect(to, params, query) { this.to = to; this.params = params; this.query = query; } module.exports = Redirect; },{}],23:[function(_dereq_,module,exports){ var assign = _dereq_('react/lib/Object.assign'); var reversedArray = _dereq_('./reversedArray'); var Redirect = _dereq_('./Redirect'); var Promise = _dereq_('./Promise'); /** * Runs all hook functions serially and calls callback(error) when finished. * A hook may return a promise if it needs to execute asynchronously. */ function runHooks(hooks, callback) { try { var promise = hooks.reduce(function (promise, hook) { // The first hook to use transition.wait makes the rest // of the transition async from that point forward. return promise ? promise.then(hook) : hook(); }, null); } catch (error) { return callback(error); // Sync error. } if (promise) { // Use setTimeout to break the promise chain. promise.then(function () { setTimeout(callback); }, function (error) { setTimeout(function () { callback(error); }); }); } else { callback(); } } /** * Calls the willTransitionFrom hook of all handlers in the given matches * serially in reverse with the transition object and the current instance of * the route's handler, so that the deepest nested handlers are called first. * Calls callback(error) when finished. */ function runTransitionFromHooks(transition, routes, components, callback) { components = reversedArray(components); var hooks = reversedArray(routes).map(function (route, index) { return function () { var handler = route.handler; if (!transition.isAborted && handler.willTransitionFrom) return handler.willTransitionFrom(transition, components[index]); var promise = transition._promise; transition._promise = null; return promise; }; }); runHooks(hooks, callback); } /** * Calls the willTransitionTo hook of all handlers in the given matches * serially with the transition object and any params that apply to that * handler. Calls callback(error) when finished. */ function runTransitionToHooks(transition, routes, params, query, callback) { var hooks = routes.map(function (route) { return function () { var handler = route.handler; if (!transition.isAborted && handler.willTransitionTo) handler.willTransitionTo(transition, params, query); var promise = transition._promise; transition._promise = null; return promise; }; }); runHooks(hooks, callback); } /** * Encapsulates a transition to a given path. * * The willTransitionTo and willTransitionFrom handlers receive * an instance of this class as their first argument. */ function Transition(path, retry) { this.path = path; this.abortReason = null; this.isAborted = false; this.retry = retry.bind(this); this._promise = null; } assign(Transition.prototype, { abort: function (reason) { this.abortReason = reason; this.isAborted = true; }, redirect: function (to, params, query) { this.abort(new Redirect(to, params, query)); }, wait: function (value) { this._promise = Promise.resolve(value); }, from: function (routes, components, callback) { return runTransitionFromHooks(this, routes, components, callback); }, to: function (routes, params, query, callback) { return runTransitionToHooks(this, routes, params, query, callback); } }); module.exports = Transition; },{"./Promise":20,"./Redirect":22,"./reversedArray":27,"react/lib/Object.assign":36}],24:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); var warning = _dereq_('react/lib/warning'); var invariant = _dereq_('react/lib/invariant'); var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; var ImitateBrowserBehavior = _dereq_('../behaviors/ImitateBrowserBehavior'); var RouteHandler = _dereq_('../components/RouteHandler'); var HashLocation = _dereq_('../locations/HashLocation'); var HistoryLocation = _dereq_('../locations/HistoryLocation'); var RefreshLocation = _dereq_('../locations/RefreshLocation'); var NavigationContext = _dereq_('../mixins/NavigationContext'); var StateContext = _dereq_('../mixins/StateContext'); var Scrolling = _dereq_('../mixins/Scrolling'); var createRoutesFromChildren = _dereq_('./createRoutesFromChildren'); var supportsHistory = _dereq_('./supportsHistory'); var Transition = _dereq_('./Transition'); var PropTypes = _dereq_('./PropTypes'); var Redirect = _dereq_('./Redirect'); var Path = _dereq_('./Path'); /** * The default location for new routers. */ var DEFAULT_LOCATION = canUseDOM ? HashLocation : '/'; /** * The default scroll behavior for new routers. */ var DEFAULT_SCROLL_BEHAVIOR = canUseDOM ? ImitateBrowserBehavior : null; /** * The default error handler for new routers. */ function defaultErrorHandler(error) { // Throw so we don't silently swallow async errors. throw error; // This error probably originated in a transition hook. } /** * The default aborted transition handler for new routers. */ function defaultAbortHandler(abortReason, location) { if (typeof location === 'string') throw new Error('Unhandled aborted transition! Reason: ' + abortReason); if (abortReason instanceof Redirect) { location.replace(this.makePath(abortReason.to, abortReason.params, abortReason.query)); } else { location.pop(); } } function findMatch(pathname, routes, defaultRoute, notFoundRoute) { var match, route, params; for (var i = 0, len = routes.length; i < len; ++i) { route = routes[i]; // Check the subtree first to find the most deeply-nested match. match = findMatch(pathname, route.childRoutes, route.defaultRoute, route.notFoundRoute); if (match != null) { match.routes.unshift(route); return match; } // No routes in the subtree matched, so check this route. params = Path.extractParams(route.path, pathname); if (params) return createMatch(route, params); } // No routes matched, so try the default route if there is one. if (defaultRoute && (params = Path.extractParams(defaultRoute.path, pathname))) return createMatch(defaultRoute, params); // Last attempt: does the "not found" route match? if (notFoundRoute && (params = Path.extractParams(notFoundRoute.path, pathname))) return createMatch(notFoundRoute, params); return match; } function createMatch(route, params) { return { routes: [ route ], params: params }; } function hasMatch(routes, route, prevParams, nextParams) { return routes.some(function (r) { if (r !== route) return false; var paramNames = route.paramNames; var paramName; for (var i = 0, len = paramNames.length; i < len; ++i) { paramName = paramNames[i]; if (nextParams[paramName] !== prevParams[paramName]) return false; } return true; }); } /** * Creates and returns a new router using the given options. A router * is a ReactComponent class that knows how to react to changes in the * URL and keep the contents of the page in sync. * * Options may be any of the following: * * - routes (required) The route config * - location The location to use. Defaults to HashLocation when * the DOM is available, "/" otherwise * - scrollBehavior The scroll behavior to use. Defaults to ImitateBrowserBehavior * when the DOM is available, null otherwise * - onError A function that is used to handle errors * - onAbort A function that is used to handle aborted transitions * * When rendering in a server-side environment, the location should simply * be the URL path that was used in the request, including the query string. */ function createRouter(options) { options = options || {}; if (typeof options === 'function') { options = { routes: options }; // Router.create() } else if (Array.isArray(options)) { options = { routes: options }; // Router.create([ , ]) } var routes = []; var namedRoutes = {}; var components = []; var location = options.location || DEFAULT_LOCATION; var scrollBehavior = options.scrollBehavior || DEFAULT_SCROLL_BEHAVIOR; var onError = options.onError || defaultErrorHandler; var onAbort = options.onAbort || defaultAbortHandler; var state = {}; var nextState = {}; function updateState() { state = nextState; nextState = {}; } // Automatically fall back to full page refreshes in // browsers that don't support the HTML history API. if (location === HistoryLocation && !supportsHistory()) location = RefreshLocation; var router = React.createClass({ displayName: 'Router', mixins: [ NavigationContext, StateContext, Scrolling ], statics: { defaultRoute: null, notFoundRoute: null, /** * Adds routes to this router from the given children object (see ReactChildren). */ addRoutes: function (children) { routes.push.apply(routes, createRoutesFromChildren(children, this, namedRoutes)); }, /** * Returns an absolute URL path created from the given route * name, URL parameters, and query. */ makePath: function (to, params, query) { var path; if (Path.isAbsolute(to)) { path = Path.normalize(to); } else { var route = namedRoutes[to]; invariant( route, 'Unable to find ', to ); path = route.path; } return Path.withQuery(Path.injectParams(path, params), query); }, /** * Returns a string that may safely be used as the href of a link * to the route with the given name, URL parameters, and query. */ makeHref: function (to, params, query) { var path = this.makePath(to, params, query); return (location === HashLocation) ? '#' + path : path; }, /** * Transitions to the URL specified in the arguments by pushing * a new URL onto the history stack. */ transitionTo: function (to, params, query) { invariant( typeof location !== 'string', 'You cannot use transitionTo with a static location' ); location.push(this.makePath(to, params, query)); }, /** * Transitions to the URL specified in the arguments by replacing * the current URL in the history stack. */ replaceWith: function (to, params, query) { invariant( typeof location !== 'string', 'You cannot use replaceWith with a static location' ); location.replace(this.makePath(to, params, query)); }, /** * Transitions to the previous URL. */ goBack: function () { invariant( typeof location !== 'string', 'You cannot use goBack with a static location' ); location.pop(); }, /** * Performs a match of the given path against this router and returns an object with * the { path, routes, params, query } that match. Returns null if no match can be made. */ match: function (path) { return findMatch(Path.withoutQuery(path), routes, this.defaultRoute, this.notFoundRoute) || null; }, /** * Performs a transition to the given path and calls callback(error, abortReason) * when the transition is finished. If both arguments are null the router's state * was updated. Otherwise the transition did not complete. * * In a transition, a router first determines which routes are involved by beginning * with the current route, up the route tree to the first parent route that is shared * with the destination route, and back down the tree to the destination route. The * willTransitionFrom hook is invoked on all route handlers we're transitioning away * from, in reverse nesting order. Likewise, the willTransitionTo hook is invoked on * all route handlers we're transitioning to. * * Both willTransitionFrom and willTransitionTo hooks may either abort or redirect the * transition. To resolve asynchronously, they may use transition.wait(promise). If no * hooks wait, the transition is fully synchronous. */ dispatch: function (path, action, callback) { if (state.path === path) return; // Nothing to do! var match = this.match(path); warning( match != null, 'No route matches path "%s". Make sure you have somewhere in your routes', path, path ); if (match == null) match = {}; var prevRoutes = state.routes || []; var prevParams = state.params || {}; var nextRoutes = match.routes || []; var nextParams = match.params || {}; var nextQuery = Path.extractQuery(path) || {}; var fromRoutes, toRoutes; if (prevRoutes.length) { fromRoutes = prevRoutes.filter(function (route) { return !hasMatch(nextRoutes, route, prevParams, nextParams); }); toRoutes = nextRoutes.filter(function (route) { return !hasMatch(prevRoutes, route, prevParams, nextParams); }); } else { fromRoutes = []; toRoutes = nextRoutes; } var transition = new Transition(path, this.replaceWith.bind(this, path)); transition.from(fromRoutes, components, function (error) { if (error || transition.isAborted) return callback.call(router, error, transition); transition.to(toRoutes, nextParams, nextQuery, function (error) { if (error || transition.isAborted) return callback.call(router, error, transition); nextState.path = path; nextState.action = action; nextState.routes = nextRoutes; nextState.params = nextParams; nextState.query = nextQuery; callback.call(router, null, transition); }); }); }, /** * Starts this router and calls callback(router, state) when the route changes. * * If the router's location is static (i.e. a URL path in a server environment) * the callback is called only once. Otherwise, the location should be one of the * Router.*Location objects (e.g. Router.HashLocation or Router.HistoryLocation). */ run: function (callback) { function dispatchHandler(error, transition) { if (error) { onError.call(router, error); } else if (transition.isAborted) { onAbort.call(router, transition.abortReason, location); } else { callback.call(router, router, nextState); } } if (typeof location === 'string') { warning( !canUseDOM || "production" === 'test', 'You should not use a static location in a DOM environment because ' + 'the router will not be kept in sync with the current URL' ); // Dispatch the location. router.dispatch(location, null, dispatchHandler); } else { invariant( canUseDOM, 'You cannot use %s in a non-DOM environment', location ); // Listen for changes to the location. function changeListener(change) { router.dispatch(change.path, change.type, dispatchHandler); } if (location.addChangeListener) location.addChangeListener(changeListener); // Bootstrap using the current path. router.dispatch(location.getCurrentPath(), null, dispatchHandler); } } }, propTypes: { children: PropTypes.falsy }, getLocation: function () { return location; }, getScrollBehavior: function () { return scrollBehavior; }, getRouteAtDepth: function (depth) { var routes = this.state.routes; return routes && routes[depth]; }, getRouteComponents: function () { return components; }, getInitialState: function () { updateState(); return state; }, componentWillReceiveProps: function () { updateState(); this.setState(state); }, render: function () { return this.getRouteAtDepth(0) ? React.createElement(RouteHandler, this.props) : null; }, childContextTypes: { getRouteAtDepth: React.PropTypes.func.isRequired, getRouteComponents: React.PropTypes.func.isRequired, routeHandlers: React.PropTypes.array.isRequired }, getChildContext: function () { return { getRouteComponents: this.getRouteComponents, getRouteAtDepth: this.getRouteAtDepth, routeHandlers: [ this ] }; } }); if (options.routes) router.addRoutes(options.routes); return router; } module.exports = createRouter; },{"../behaviors/ImitateBrowserBehavior":2,"../components/RouteHandler":8,"../locations/HashLocation":10,"../locations/HistoryLocation":11,"../locations/RefreshLocation":12,"../mixins/NavigationContext":15,"../mixins/Scrolling":16,"../mixins/StateContext":18,"./Path":19,"./PropTypes":21,"./Redirect":22,"./Transition":23,"./createRoutesFromChildren":25,"./supportsHistory":29,"react/lib/ExecutionEnvironment":35,"react/lib/invariant":39,"react/lib/warning":40}],25:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); var warning = _dereq_('react/lib/warning'); var invariant = _dereq_('react/lib/invariant'); var DefaultRoute = _dereq_('../components/DefaultRoute'); var NotFoundRoute = _dereq_('../components/NotFoundRoute'); var Redirect = _dereq_('../components/Redirect'); var Route = _dereq_('../components/Route'); var Path = _dereq_('./Path'); var CONFIG_ELEMENT_TYPES = [ DefaultRoute.type, NotFoundRoute.type, Redirect.type, Route.type ]; function createRedirectHandler(to, _params, _query) { return React.createClass({ statics: { willTransitionTo: function (transition, params, query) { transition.redirect(to, _params || params, _query || query); } }, render: function () { return null; } }); } function checkPropTypes(componentName, propTypes, props) { for (var propName in propTypes) { if (propTypes.hasOwnProperty(propName)) { var error = propTypes[propName](props, propName, componentName); if (error instanceof Error) warning(false, error.message); } } } function createRoute(element, parentRoute, namedRoutes) { var type = element.type; var props = element.props; var componentName = (type && type.displayName) || 'UnknownComponent'; invariant( CONFIG_ELEMENT_TYPES.indexOf(type) !== -1, 'Unrecognized route configuration element "<%s>"', componentName ); if (type.propTypes) checkPropTypes(componentName, type.propTypes, props); var route = { name: props.name }; if (type === Redirect.type) { route.handler = createRedirectHandler(props.to, props.params, props.query); props.path = props.path || props.from || '*'; } else { route.handler = props.handler; } var parentPath = (parentRoute && parentRoute.path) || '/'; if ((props.path || props.name) && type !== DefaultRoute.type && type !== NotFoundRoute.type) { var path = props.path || props.name; // Relative paths extend their parent. if (!Path.isAbsolute(path)) path = Path.join(parentPath, path); route.path = Path.normalize(path); } else { route.path = parentPath; if (type === NotFoundRoute.type) route.path += '*'; } route.paramNames = Path.extractParamNames(route.path); // Make sure the route's path has all params its parent needs. if (parentRoute && Array.isArray(parentRoute.paramNames)) { parentRoute.paramNames.forEach(function (paramName) { invariant( route.paramNames.indexOf(paramName) !== -1, 'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"', route.path, paramName, parentRoute.path ); }); } // Make sure the route can be looked up by s. if (props.name) { invariant( namedRoutes[props.name] == null, 'You cannot use the name "%s" for more than one route', props.name ); namedRoutes[props.name] = route; } // Handle . if (type === NotFoundRoute.type) { invariant( parentRoute, ' must have a parent ' ); invariant( parentRoute.notFoundRoute == null, 'You may not have more than one per ' ); parentRoute.notFoundRoute = route; return null; } // Handle . if (type === DefaultRoute.type) { invariant( parentRoute, ' must have a parent ' ); invariant( parentRoute.defaultRoute == null, 'You may not have more than one per ' ); parentRoute.defaultRoute = route; return null; } route.childRoutes = createRoutesFromChildren(props.children, route, namedRoutes); return route; } /** * Creates and returns an array of route objects from the given ReactChildren. */ function createRoutesFromChildren(children, parentRoute, namedRoutes) { var routes = []; React.Children.forEach(children, function (child) { // Exclude s and s. if (child = createRoute(child, parentRoute, namedRoutes)) routes.push(child); }); return routes; } module.exports = createRoutesFromChildren; },{"../components/DefaultRoute":3,"../components/NotFoundRoute":5,"../components/Redirect":6,"../components/Route":7,"./Path":19,"react/lib/invariant":39,"react/lib/warning":40}],26:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; /** * Returns the current scroll position of the window as { x, y }. */ function getWindowScrollPosition() { invariant( canUseDOM, 'Cannot get current scroll position without a DOM' ); return { x: window.scrollX, y: window.scrollY }; } module.exports = getWindowScrollPosition; },{"react/lib/ExecutionEnvironment":35,"react/lib/invariant":39}],27:[function(_dereq_,module,exports){ function reversedArray(array) { return array.slice(0).reverse(); } module.exports = reversedArray; },{}],28:[function(_dereq_,module,exports){ var createRouter = _dereq_('./createRouter'); /** * A high-level convenience method that creates, configures, and * runs a router in one shot. The method signature is: * * Router.run(routes[, location ], callback); * * Using `window.location.hash` to manage the URL, you could do: * * Router.run(routes, function (Handler) { * React.render(, document.body); * }); * * Using HTML5 history and a custom "cursor" prop: * * Router.run(routes, Router.HistoryLocation, function (Handler) { * React.render(, document.body); * }); * * Returns the newly created router. * * Note: If you need to specify further options for your router such * as error/abort handling or custom scroll behavior, use Router.create * instead. * * var router = Router.create(options); * router.run(function (Handler) { * // ... * }); */ function runRouter(routes, location, callback) { if (typeof location === 'function') { callback = location; location = null; } var router = createRouter({ routes: routes, location: location }); router.run(callback); return router; } module.exports = runRouter; },{"./createRouter":24}],29:[function(_dereq_,module,exports){ function supportsHistory() { /*! taken from modernizr * https://github.com/Modernizr/Modernizr/blob/master/LICENSE * https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js */ var ua = navigator.userAgent; if ((ua.indexOf('Android 2.') !== -1 || (ua.indexOf('Android 4.0') !== -1)) && ua.indexOf('Mobile Safari') !== -1 && ua.indexOf('Chrome') === -1) { return false; } return (window.history && 'pushState' in window.history); } module.exports = supportsHistory; },{}],30:[function(_dereq_,module,exports){ module.exports = _dereq_('./lib'); },{"./lib":31}],31:[function(_dereq_,module,exports){ // Load modules var Stringify = _dereq_('./stringify'); var Parse = _dereq_('./parse'); // Declare internals var internals = {}; module.exports = { stringify: Stringify, parse: Parse }; },{"./parse":32,"./stringify":33}],32:[function(_dereq_,module,exports){ // Load modules var Utils = _dereq_('./utils'); // Declare internals var internals = { delimiter: '&', depth: 5, arrayLimit: 20, parameterLimit: 1000 }; internals.parseValues = function (str, options) { var obj = {}; var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit); for (var i = 0, il = parts.length; i < il; ++i) { var part = parts[i]; var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1; if (pos === -1) { obj[Utils.decode(part)] = ''; } else { var key = Utils.decode(part.slice(0, pos)); var val = Utils.decode(part.slice(pos + 1)); if (!obj[key]) { obj[key] = val; } else { obj[key] = [].concat(obj[key]).concat(val); } } } return obj; }; internals.parseObject = function (chain, val, options) { if (!chain.length) { return val; } var root = chain.shift(); var obj = {}; if (root === '[]') { obj = []; obj = obj.concat(internals.parseObject(chain, val, options)); } else { var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root; var index = parseInt(cleanRoot, 10); if (!isNaN(index) && root !== cleanRoot && index <= options.arrayLimit) { obj = []; obj[index] = internals.parseObject(chain, val, options); } else { obj[cleanRoot] = internals.parseObject(chain, val, options); } } return obj; }; internals.parseKeys = function (key, val, options) { if (!key) { return; } // The regex chunks var parent = /^([^\[\]]*)/; var child = /(\[[^\[\]]*\])/g; // Get the parent var segment = parent.exec(key); // Don't allow them to overwrite object prototype properties if (Object.prototype.hasOwnProperty(segment[1])) { return; } // Stash the parent if it exists var keys = []; if (segment[1]) { keys.push(segment[1]); } // Loop through children appending to the array until we hit depth var i = 0; while ((segment = child.exec(key)) !== null && i < options.depth) { ++i; if (!Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) { keys.push(segment[1]); } } // If there's a remainder, just add whatever is left if (segment) { keys.push('[' + key.slice(segment.index) + ']'); } return internals.parseObject(keys, val, options); }; module.exports = function (str, options) { if (str === '' || str === null || typeof str === 'undefined') { return {}; } options = options || {}; options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter; options.depth = typeof options.depth === 'number' ? options.depth : internals.depth; options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit; options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit; var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str; var obj = {}; // Iterate over the keys and setup the new object var keys = Object.keys(tempObj); for (var i = 0, il = keys.length; i < il; ++i) { var key = keys[i]; var newObj = internals.parseKeys(key, tempObj[key], options); obj = Utils.merge(obj, newObj); } return Utils.compact(obj); }; },{"./utils":34}],33:[function(_dereq_,module,exports){ // Load modules var Utils = _dereq_('./utils'); // Declare internals var internals = { delimiter: '&' }; internals.stringify = function (obj, prefix) { if (Utils.isBuffer(obj)) { obj = obj.toString(); } else if (obj instanceof Date) { obj = obj.toISOString(); } else if (obj === null) { obj = ''; } if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean') { return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)]; } var values = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']')); } } return values; }; module.exports = function (obj, options) { options = options || {}; var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter; var keys = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { keys = keys.concat(internals.stringify(obj[key], key)); } } return keys.join(delimiter); }; },{"./utils":34}],34:[function(_dereq_,module,exports){ // Load modules // Declare internals var internals = {}; exports.arrayToObject = function (source) { var obj = {}; for (var i = 0, il = source.length; i < il; ++i) { if (typeof source[i] !== 'undefined') { obj[i] = source[i]; } } return obj; }; exports.merge = function (target, source) { if (!source) { return target; } if (Array.isArray(source)) { for (var i = 0, il = source.length; i < il; ++i) { if (typeof source[i] !== 'undefined') { if (typeof target[i] === 'object') { target[i] = exports.merge(target[i], source[i]); } else { target[i] = source[i]; } } } return target; } if (Array.isArray(target)) { if (typeof source !== 'object') { target.push(source); return target; } else { target = exports.arrayToObject(target); } } var keys = Object.keys(source); for (var k = 0, kl = keys.length; k < kl; ++k) { var key = keys[k]; var value = source[key]; if (value && typeof value === 'object') { if (!target[key]) { target[key] = value; } else { target[key] = exports.merge(target[key], value); } } else { target[key] = value; } } return target; }; exports.decode = function (str) { try { return decodeURIComponent(str.replace(/\+/g, ' ')); } catch (e) { return str; } }; exports.compact = function (obj, refs) { if (typeof obj !== 'object' || obj === null) { return obj; } refs = refs || []; var lookup = refs.indexOf(obj); if (lookup !== -1) { return refs[lookup]; } refs.push(obj); if (Array.isArray(obj)) { var compacted = []; for (var i = 0, l = obj.length; i < l; ++i) { if (typeof obj[i] !== 'undefined') { compacted.push(obj[i]); } } return compacted; } var keys = Object.keys(obj); for (var i = 0, il = keys.length; i < il; ++i) { var key = keys[i]; obj[key] = exports.compact(obj[key], refs); } return obj; }; exports.isRegExp = function (obj) { return Object.prototype.toString.call(obj) === '[object RegExp]'; }; exports.isBuffer = function (obj) { if (typeof Buffer !== 'undefined') { return Buffer.isBuffer(obj); } else { return false; } }; },{}],35:[function(_dereq_,module,exports){ /** * Copyright 2013-2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ExecutionEnvironment */ /*jslint evil: true */ "use strict"; var canUseDOM = !!( typeof window !== 'undefined' && window.document && window.document.createElement ); /** * Simple, lightweight module assisting with the detection and context of * Worker. Helps avoid circular dependencies and allows code to reason about * whether or not they are in a Worker, even if they never include the main * `ReactWorker` dependency. */ var ExecutionEnvironment = { canUseDOM: canUseDOM, canUseWorkers: typeof Worker !== 'undefined', canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent), canUseViewport: canUseDOM && !!window.screen, isInWorker: !canUseDOM // For now, this is true - might change in the future. }; module.exports = ExecutionEnvironment; },{}],36:[function(_dereq_,module,exports){ /** * Copyright 2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule Object.assign */ // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign function assign(target, sources) { if (target == null) { throw new TypeError('Object.assign target cannot be null or undefined'); } var to = Object(target); var hasOwnProperty = Object.prototype.hasOwnProperty; for (var nextIndex = 1; nextIndex < arguments.length; nextIndex++) { var nextSource = arguments[nextIndex]; if (nextSource == null) { continue; } var from = Object(nextSource); // We don't currently support accessors nor proxies. Therefore this // copy cannot throw. If we ever supported this then we must handle // exceptions and side-effects. We don't support symbols so they won't // be transferred. for (var key in from) { if (hasOwnProperty.call(from, key)) { to[key] = from[key]; } } } return to; }; module.exports = assign; },{}],37:[function(_dereq_,module,exports){ /** * Copyright 2013-2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule cx */ /** * This function is used to mark string literals representing CSS class names * so that they can be transformed statically. This allows for modularization * and minification of CSS class names. * * In static_upstream, this function is actually implemented, but it should * eventually be replaced with something more descriptive, and the transform * that is used in the main stack should be ported for use elsewhere. * * @param string|object className to modularize, or an object of key/values. * In the object case, the values are conditions that * determine if the className keys should be included. * @param [string ...] Variable list of classNames in the string case. * @return string Renderable space-separated CSS className. */ function cx(classNames) { if (typeof classNames == 'object') { return Object.keys(classNames).filter(function(className) { return classNames[className]; }).join(' '); } else { return Array.prototype.join.call(arguments, ' '); } } module.exports = cx; },{}],38:[function(_dereq_,module,exports){ /** * Copyright 2013-2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule emptyFunction */ function makeEmptyFunction(arg) { return function() { return arg; }; } /** * This function accepts and discards inputs; it has no side effects. This is * primarily useful idiomatically for overridable function endpoints which * always need to be callable, since JS lacks a null-call idiom ala Cocoa. */ function emptyFunction() {} emptyFunction.thatReturns = makeEmptyFunction; emptyFunction.thatReturnsFalse = makeEmptyFunction(false); emptyFunction.thatReturnsTrue = makeEmptyFunction(true); emptyFunction.thatReturnsNull = makeEmptyFunction(null); emptyFunction.thatReturnsThis = function() { return this; }; emptyFunction.thatReturnsArgument = function(arg) { return arg; }; module.exports = emptyFunction; },{}],39:[function(_dereq_,module,exports){ /** * Copyright 2013-2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule invariant */ "use strict"; /** * Use invariant() to assert state which your program assumes to be true. * * Provide sprintf-style format (only %s is supported) and arguments * to provide information about what broke and what you were * expecting. * * The invariant message will be stripped in production, but the invariant * will remain to ensure logic does not differ in production. */ var invariant = function(condition, format, a, b, c, d, e, f) { if ("production" !== "production") { if (format === undefined) { throw new Error('invariant requires an error message argument'); } } if (!condition) { var error; if (format === undefined) { error = new Error( 'Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.' ); } else { var args = [a, b, c, d, e, f]; var argIndex = 0; error = new Error( 'Invariant Violation: ' + format.replace(/%s/g, function() { return args[argIndex++]; }) ); } error.framesToPop = 1; // we don't care about invariant's own frame throw error; } }; module.exports = invariant; },{}],40:[function(_dereq_,module,exports){ /** * Copyright 2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule warning */ "use strict"; var emptyFunction = _dereq_("./emptyFunction"); /** * Similar to invariant but only logs a warning if the condition is not met. * This can be used to log issues in development environments in critical * paths. Removing the logging code for production environments will keep the * same logic and follow the same code paths. */ var warning = emptyFunction; if ("production" !== "production") { warning = function(condition, format ) {var args=Array.prototype.slice.call(arguments,2); if (format === undefined) { throw new Error( '`warning(condition, format, ...args)` requires a warning ' + 'message argument' ); } if (!condition) { var argIndex = 0; console.warn('Warning: ' + format.replace(/%s/g, function() {return args[argIndex++];})); } }; } module.exports = warning; },{"./emptyFunction":38}],41:[function(_dereq_,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function (_dereq_) { var makePromise = _dereq_('./makePromise'); var Scheduler = _dereq_('./Scheduler'); var async = _dereq_('./async'); return makePromise({ scheduler: new Scheduler(async) }); }); })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(_dereq_); }); },{"./Scheduler":43,"./async":44,"./makePromise":45}],42:[function(_dereq_,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function() { /** * Circular queue * @param {number} capacityPow2 power of 2 to which this queue's capacity * will be set initially. eg when capacityPow2 == 3, queue capacity * will be 8. * @constructor */ function Queue(capacityPow2) { this.head = this.tail = this.length = 0; this.buffer = new Array(1 << capacityPow2); } Queue.prototype.push = function(x) { if(this.length === this.buffer.length) { this._ensureCapacity(this.length * 2); } this.buffer[this.tail] = x; this.tail = (this.tail + 1) & (this.buffer.length - 1); ++this.length; return this.length; }; Queue.prototype.shift = function() { var x = this.buffer[this.head]; this.buffer[this.head] = void 0; this.head = (this.head + 1) & (this.buffer.length - 1); --this.length; return x; }; Queue.prototype._ensureCapacity = function(capacity) { var head = this.head; var buffer = this.buffer; var newBuffer = new Array(capacity); var i = 0; var len; if(head === 0) { len = this.length; for(; i 0) { queue.shift().run(); } } return Scheduler; }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); })); },{"./Queue":42}],44:[function(_dereq_,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function(_dereq_) { // Sniff "best" async scheduling option // Prefer process.nextTick or MutationObserver, then check for // vertx and finally fall back to setTimeout /*jshint maxcomplexity:6*/ /*global process,document,setTimeout,MutationObserver,WebKitMutationObserver*/ var nextTick, MutationObs; if (typeof process !== 'undefined' && process !== null && typeof process.nextTick === 'function') { nextTick = function(f) { process.nextTick(f); }; } else if (MutationObs = (typeof MutationObserver === 'function' && MutationObserver) || (typeof WebKitMutationObserver === 'function' && WebKitMutationObserver)) { nextTick = (function (document, MutationObserver) { var scheduled; var el = document.createElement('div'); var o = new MutationObserver(run); o.observe(el, { attributes: true }); function run() { var f = scheduled; scheduled = void 0; f(); } return function (f) { scheduled = f; el.setAttribute('class', 'x'); }; }(document, MutationObs)); } else { nextTick = (function(cjsRequire) { var vertx; try { // vert.x 1.x || 2.x vertx = cjsRequire('vertx'); } catch (ignore) {} if (vertx) { if (typeof vertx.runOnLoop === 'function') { return vertx.runOnLoop; } if (typeof vertx.runOnContext === 'function') { return vertx.runOnContext; } } // capture setTimeout to avoid being caught by fake timers // used in time based tests var capturedSetTimeout = setTimeout; return function (t) { capturedSetTimeout(t, 0); }; }(_dereq_)); } return nextTick; }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); })); },{}],45:[function(_dereq_,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function() { return function makePromise(environment) { var tasks = environment.scheduler; var objectCreate = Object.create || function(proto) { function Child() {} Child.prototype = proto; return new Child(); }; /** * Create a promise whose fate is determined by resolver * @constructor * @returns {Promise} promise * @name Promise */ function Promise(resolver, handler) { this._handler = resolver === Handler ? handler : init(resolver); } /** * Run the supplied resolver * @param resolver * @returns {Pending} */ function init(resolver) { var handler = new Pending(); try { resolver(promiseResolve, promiseReject, promiseNotify); } catch (e) { promiseReject(e); } return handler; /** * Transition from pre-resolution state to post-resolution state, notifying * all listeners of the ultimate fulfillment or rejection * @param {*} x resolution value */ function promiseResolve (x) { handler.resolve(x); } /** * Reject this promise with reason, which will be used verbatim * @param {Error|*} reason rejection reason, strongly suggested * to be an Error type */ function promiseReject (reason) { handler.reject(reason); } /** * Issue a progress event, notifying all progress listeners * @param {*} x progress event payload to pass to all listeners */ function promiseNotify (x) { handler.notify(x); } } // Creation Promise.resolve = resolve; Promise.reject = reject; Promise.never = never; Promise._defer = defer; Promise._handler = getHandler; /** * Returns a trusted promise. If x is already a trusted promise, it is * returned, otherwise returns a new trusted Promise which follows x. * @param {*} x * @return {Promise} promise */ function resolve(x) { return isPromise(x) ? x : new Promise(Handler, new Async(getHandler(x))); } /** * Return a reject promise with x as its reason (x is used verbatim) * @param {*} x * @returns {Promise} rejected promise */ function reject(x) { return new Promise(Handler, new Async(new Rejected(x))); } /** * Return a promise that remains pending forever * @returns {Promise} forever-pending promise. */ function never() { return foreverPendingPromise; // Should be frozen } /** * Creates an internal {promise, resolver} pair * @private * @returns {Promise} */ function defer() { return new Promise(Handler, new Pending()); } // Transformation and flow control /** * Transform this promise's fulfillment value, returning a new Promise * for the transformed result. If the promise cannot be fulfilled, onRejected * is called with the reason. onProgress *may* be called with updates toward * this promise's fulfillment. * @param {function=} onFulfilled fulfillment handler * @param {function=} onRejected rejection handler * @deprecated @param {function=} onProgress progress handler * @return {Promise} new promise */ Promise.prototype.then = function(onFulfilled, onRejected) { var parent = this._handler; var state = parent.join().state(); if ((typeof onFulfilled !== 'function' && state > 0) || (typeof onRejected !== 'function' && state < 0)) { // Short circuit: value will not change, simply share handler return new this.constructor(Handler, parent); } var p = this._beget(); var child = p._handler; parent.chain(child, parent.receiver, onFulfilled, onRejected, arguments.length > 2 ? arguments[2] : void 0); return p; }; /** * If this promise cannot be fulfilled due to an error, call onRejected to * handle the error. Shortcut for .then(undefined, onRejected) * @param {function?} onRejected * @return {Promise} */ Promise.prototype['catch'] = function(onRejected) { return this.then(void 0, onRejected); }; /** * Creates a new, pending promise of the same type as this promise * @private * @returns {Promise} */ Promise.prototype._beget = function() { var parent = this._handler; var child = new Pending(parent.receiver, parent.join().context); return new this.constructor(Handler, child); }; // Array combinators Promise.all = all; Promise.race = race; /** * Return a promise that will fulfill when all promises in the * input array have fulfilled, or will reject when one of the * promises rejects. * @param {array} promises array of promises * @returns {Promise} promise for array of fulfillment values */ function all(promises) { /*jshint maxcomplexity:8*/ var resolver = new Pending(); var pending = promises.length >>> 0; var results = new Array(pending); var i, h, x, s; for (i = 0; i < promises.length; ++i) { x = promises[i]; if (x === void 0 && !(i in promises)) { --pending; continue; } if (maybeThenable(x)) { h = getHandlerMaybeThenable(x); s = h.state(); if (s === 0) { h.fold(settleAt, i, results, resolver); } else if (s > 0) { results[i] = h.value; --pending; } else { unreportRemaining(promises, i+1, h); resolver.become(h); break; } } else { results[i] = x; --pending; } } if(pending === 0) { resolver.become(new Fulfilled(results)); } return new Promise(Handler, resolver); function settleAt(i, x, resolver) { /*jshint validthis:true*/ this[i] = x; if(--pending === 0) { resolver.become(new Fulfilled(this)); } } } function unreportRemaining(promises, start, rejectedHandler) { var i, h, x; for(i=start; i