react-router
Advanced tools
Comparing version 0.5.2 to 0.5.3
@@ -1,2 +0,2 @@ | ||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.ReactRouter=e()}}(function(){return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)s(r[o]);return s}({1:[function(_dereq_,module){module.exports=_dereq_("./modules/mixins/ActiveState")},{"./modules/mixins/ActiveState":24}],2:[function(_dereq_,module){module.exports=_dereq_("./modules/mixins/AsyncState")},{"./modules/mixins/AsyncState":25}],3:[function(_dereq_,module){module.exports=_dereq_("./modules/components/Link")},{"./modules/components/Link":10}],4:[function(_dereq_,module){module.exports=_dereq_("./modules/components/Redirect")},{"./modules/components/Redirect":11}],5:[function(_dereq_,module){module.exports=_dereq_("./modules/components/Route")},{"./modules/components/Route":12}],6:[function(_dereq_,module){module.exports=_dereq_("./modules/components/Routes")},{"./modules/components/Routes":13}],7:[function(_dereq_,module){module.exports=_dereq_("./modules/helpers/goBack")},{"./modules/helpers/goBack":16}],8:[function(_dereq_,module,exports){exports.ActiveState=_dereq_("./ActiveState"),exports.AsyncState=_dereq_("./AsyncState"),exports.Link=_dereq_("./Link"),exports.Redirect=_dereq_("./Redirect"),exports.Route=_dereq_("./Route"),exports.Routes=_dereq_("./Routes"),exports.goBack=_dereq_("./goBack"),exports.replaceWith=_dereq_("./replaceWith"),exports.transitionTo=_dereq_("./transitionTo"),exports.makeHref=_dereq_("./makeHref")},{"./ActiveState":1,"./AsyncState":2,"./Link":3,"./Redirect":4,"./Route":5,"./Routes":6,"./goBack":7,"./makeHref":9,"./replaceWith":62,"./transitionTo":63}],9:[function(_dereq_,module){module.exports=_dereq_("./modules/helpers/makeHref")},{"./modules/helpers/makeHref":17}],10:[function(_dereq_,module){function isLeftClick(event){return 0===event.button}function isModifiedEvent(event){return!!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,ActiveState=_dereq_("../mixins/ActiveState"),withoutProperties=_dereq_("../helpers/withoutProperties"),transitionTo=_dereq_("../helpers/transitionTo"),makeHref=_dereq_("../helpers/makeHref"),hasOwn=Function.prototype.call.bind(Object.prototype.hasOwnProperty),RESERVED_PROPS={to:!0,className:!0,activeClassName:!0,query:!0,children:!0},Link=React.createClass({displayName:"Link",mixins:[ActiveState],statics:{getUnreservedProps:function(props){return withoutProperties(props,RESERVED_PROPS)}},propTypes:{to:React.PropTypes.string.isRequired,activeClassName:React.PropTypes.string.isRequired,query:React.PropTypes.object},getDefaultProps:function(){return{activeClassName:"active"}},getInitialState:function(){return{isActive:!1}},getParams:function(){return Link.getUnreservedProps(this.props)},getHref:function(){return makeHref(this.props.to,this.getParams(),this.props.query)},getClassName:function(){var className=this.props.className||"";return this.state.isActive?className+" "+this.props.activeClassName:className},componentWillReceiveProps:function(nextProps){var params=Link.getUnreservedProps(nextProps);this.setState({isActive:Link.isActive(nextProps.to,params,nextProps.query)})},updateActiveState:function(){this.setState({isActive:Link.isActive(this.props.to,this.getParams(),this.props.query)})},handleClick:function(event){!isModifiedEvent(event)&&isLeftClick(event)&&(event.preventDefault(),transitionTo(this.props.to,this.getParams(),this.props.query))},render:function(){var props={href:this.getHref(),className:this.getClassName(),onClick:this.handleClick};for(var propName in this.props)hasOwn(this.props,propName)&&hasOwn(props,propName)===!1&&(props[propName]=this.props[propName]);return React.DOM.a(props,this.props.children)}});module.exports=Link},{"../helpers/makeHref":17,"../helpers/transitionTo":22,"../helpers/withoutProperties":23,"../mixins/ActiveState":24}],11:[function(_dereq_,module){function Redirect(props){return Route({path:props.from,handler:createRedirectClass(props.to)})}function createRedirectClass(to){return React.createClass({statics:{willTransitionTo:function(transition,params,query){transition.redirect(to,params,query)}},render:function(){return null}})}var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,Route=_dereq_("./Route");module.exports=Redirect},{"./Route":12}],12:[function(_dereq_,module){var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,withoutProperties=_dereq_("../helpers/withoutProperties"),RESERVED_PROPS={handler:!0,path:!0,children:!0},Route=React.createClass({displayName:"Route",statics:{getUnreservedProps:function(props){return withoutProperties(props,RESERVED_PROPS)}},getDefaultProps:function(){return{preserveScrollPosition:!1}},propTypes:{handler:React.PropTypes.any.isRequired,path:React.PropTypes.string,name:React.PropTypes.string,preserveScrollPosition:React.PropTypes.bool},render:function(){throw new Error("The <Route> component should not be rendered directly. You may be missing a <Routes> wrapper around your list of routes.")}});module.exports=Route},{"../helpers/withoutProperties":23}],13:[function(_dereq_,module){function Transition(path){this.path=path,this.cancelReason=null,this.isCancelled=!1}function Abort(){}function Redirect(to,params,query){this.to=to,this.params=params,this.query=query}function findMatches(path,route){var matches,params,children=route.props.children;if(Array.isArray(children))for(var i=0,len=children.length;null==matches&&len>i;++i)matches=findMatches(path,children[i]);else children&&(matches=findMatches(path,children));if(matches){var rootParams=getRootMatch(matches).params;return params={},Path.extractParamNames(route.props.path).forEach(function(paramName){params[paramName]=rootParams[paramName]}),matches.unshift(makeMatch(route,params)),matches}return params=Path.extractParams(route.props.path,path),params?[makeMatch(route,params)]:null}function makeMatch(route,params){return{route:route,params:params}}function hasMatch(matches,match){return matches.some(function(m){if(m.route!==match.route)return!1;for(var property in m.params)if(m.params[property]!==match.params[property])return!1;return!0})}function getRootMatch(matches){return matches[matches.length-1]}function updateMatchComponents(matches,refs){for(var component,i=0;component=refs[REF_NAME];)matches[i++].component=component,refs=component.refs}function syncWithTransition(routes,transition){if(routes.state.path===transition.path)return Promise.resolve();var currentMatches=routes.state.matches,nextMatches=routes.match(transition.path);warning(nextMatches,'No route matches path "'+transition.path+'". Make sure you have <Route path="'+transition.path+'"> somewhere in your routes'),nextMatches||(nextMatches=[]);var fromMatches,toMatches;return currentMatches?(updateMatchComponents(currentMatches,routes.refs),fromMatches=currentMatches.filter(function(match){return!hasMatch(nextMatches,match)}),toMatches=nextMatches.filter(function(match){return!hasMatch(currentMatches,match)})):(fromMatches=[],toMatches=nextMatches),checkTransitionFromHooks(fromMatches,transition).then(function(){return transition.isCancelled?void 0:checkTransitionToHooks(toMatches,transition).then(function(){if(!transition.isCancelled){var rootMatch=getRootMatch(nextMatches),params=rootMatch&&rootMatch.params||{},query=Path.extractQuery(transition.path)||{},state={path:transition.path,matches:nextMatches,activeParams:params,activeQuery:query,activeRoutes:nextMatches.map(function(match){return match.route})};return maybeScrollWindow(routes,toMatches[toMatches.length-1]),routes.setState(state),state}})})}function checkTransitionFromHooks(matches,transition){var promise=Promise.resolve();return reversedArray(matches).forEach(function(match){promise=promise.then(function(){var handler=match.route.props.handler;return!transition.isCancelled&&handler.willTransitionFrom?handler.willTransitionFrom(transition,match.component):void 0})}),promise}function checkTransitionToHooks(matches,transition){var promise=Promise.resolve();return matches.forEach(function(match){promise=promise.then(function(){var handler=match.route.props.handler;return!transition.isCancelled&&handler.willTransitionTo?handler.willTransitionTo(transition,match.params):void 0})}),promise}function computeHandlerProps(matches,query){var childHandler,props={ref:null,key:null,params:null,query:null,activeRouteHandler:returnNull};return reversedArray(matches).forEach(function(match){var route=match.route;props=Route.getUnreservedProps(route.props),props.ref=REF_NAME,props.key=Path.injectParams(route.props.path,match.params),props.params=match.params,props.query=query,props.activeRouteHandler=childHandler?childHandler:returnNull,childHandler=function(props,addedProps){if(arguments.length>2&&"undefined"!=typeof arguments[2])throw new Error("Passing children to a route handler is not supported");return route.props.handler(mergeProperties(props,addedProps))}.bind(this,props)}),props}function returnNull(){return null}function reversedArray(array){return array.slice(0).reverse()}function maybeScrollWindow(routes,match){routes.props.preserveScrollPosition||match&&!match.route.props.preserveScrollPosition&&window.scrollTo(0,0)}var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,warning=_dereq_("react/lib/warning"),ExecutionEnvironment=_dereq_("react/lib/ExecutionEnvironment"),mergeProperties=_dereq_("../helpers/mergeProperties"),goBack=_dereq_("../helpers/goBack"),replaceWith=_dereq_("../helpers/replaceWith"),transitionTo=_dereq_("../helpers/transitionTo"),Route=_dereq_("../components/Route"),Path=_dereq_("../helpers/Path"),ActiveStore=_dereq_("../stores/ActiveStore"),RouteStore=_dereq_("../stores/RouteStore"),URLStore=_dereq_("../stores/URLStore"),Promise=_dereq_("es6-promise").Promise,REF_NAME="__activeRoute__",Routes=React.createClass({displayName:"Routes",statics:{handleAsyncError:function(error){throw error},handleCancelledTransition:function(transition){var reason=transition.cancelReason;reason instanceof Redirect?replaceWith(reason.to,reason.params,reason.query):reason instanceof Abort&&goBack()}},propTypes:{location:React.PropTypes.oneOf(["hash","history"]).isRequired,preserveScrollPosition:React.PropTypes.bool},getDefaultProps:function(){return{location:"hash",preserveScrollPosition:!1}},getInitialState:function(){return{}},componentWillMount:function(){React.Children.forEach(this.props.children,function(child){RouteStore.registerRoute(child)}),!URLStore.isSetup()&&ExecutionEnvironment.canUseDOM&&URLStore.setup(this.props.location),URLStore.addChangeListener(this.handleRouteChange)},componentDidMount:function(){this.dispatch(URLStore.getCurrentPath())},componentWillUnmount:function(){URLStore.removeChangeListener(this.handleRouteChange)},handleRouteChange:function(){this.dispatch(URLStore.getCurrentPath())},match:function(path){var rootRoutes=this.props.children;Array.isArray(rootRoutes)||(rootRoutes=[rootRoutes]);for(var matches=null,i=0;null==matches&&i<rootRoutes.length;i++)matches=findMatches(Path.withoutQuery(path),rootRoutes[i]);return matches},dispatch:function(path,returnRejectedPromise){var transition=new Transition(path),routes=this,promise=syncWithTransition(routes,transition).then(function(newState){return transition.isCancelled?Routes.handleCancelledTransition(transition,routes):newState&&ActiveStore.updateState(newState),transition});return returnRejectedPromise||(promise=promise.then(void 0,function(error){setTimeout(function(){Routes.handleAsyncError(error,routes)})})),promise},render:function(){if(!this.state.path)return null;var matches=this.state.matches;return matches.length?matches[0].route.props.handler(computeHandlerProps(matches,this.state.activeQuery)):null}});mergeProperties(Transition.prototype,{abort:function(){this.cancelReason=new Abort,this.isCancelled=!0},redirect:function(to,params,query){this.cancelReason=new Redirect(to,params,query),this.isCancelled=!0},retry:function(){transitionTo(this.path)}}),module.exports=Routes},{"../components/Route":12,"../helpers/Path":14,"../helpers/goBack":16,"../helpers/mergeProperties":19,"../helpers/replaceWith":20,"../helpers/transitionTo":22,"../stores/ActiveStore":26,"../stores/RouteStore":27,"../stores/URLStore":28,"es6-promise":32,"react/lib/ExecutionEnvironment":57,"react/lib/warning":61}],14:[function(_dereq_,module){function getParamName(pathSegment){return"*"===pathSegment?"splat":pathSegment.substr(1)}function compilePattern(pattern){if(_compiledPatterns[pattern])return _compiledPatterns[pattern];var compiled=_compiledPatterns[pattern]={},paramNames=compiled.paramNames=[],source=pattern.replace(paramMatcher,function(match,pathSegment){return paramNames.push(getParamName(pathSegment)),"*"===pathSegment?"(.*?)":"([^/?#]+)"});return compiled.matcher=new RegExp("^"+source+"$","i"),compiled}function isDynamicPattern(pattern){return-1!==pattern.indexOf(":")||-1!==pattern.indexOf("*")}var invariant=_dereq_("react/lib/invariant"),qs=_dereq_("querystring"),mergeProperties=_dereq_("./mergeProperties"),URL=_dereq_("./URL"),paramMatcher=/((?::[a-z_$][a-z0-9_$]*)|\*)/gi,queryMatcher=/\?(.+)/,_compiledPatterns={},Path={extractParams:function(pattern,path){if(!pattern)return null;if(!isDynamicPattern(pattern))return pattern===URL.decode(path)?{}:null;var compiled=compilePattern(pattern),match=URL.decode(path).match(compiled.matcher);if(!match)return null;var params={};return compiled.paramNames.forEach(function(paramName,index){params[paramName]=match[index+1]}),params},extractParamNames:function(pattern){return pattern?compilePattern(pattern).paramNames:[]},injectParams:function(pattern,params){return pattern?isDynamicPattern(pattern)?(params=params||{},pattern.replace(paramMatcher,function(match,pathSegment){var paramName=getParamName(pathSegment);return invariant(null!=params[paramName],'Missing "'+paramName+'" parameter for path "'+pattern+'"'),String(params[paramName]).split("/").map(URL.encode).join("/")})):pattern:null},extractQuery:function(path){var match=path.match(queryMatcher);return match&&qs.parse(match[1])},withoutQuery:function(path){return path.replace(queryMatcher,"")},withQuery:function(path,query){var existingQuery=Path.extractQuery(path);existingQuery&&(query=query?mergeProperties(existingQuery,query):existingQuery);var queryString=query&&qs.stringify(query);return queryString?Path.withoutQuery(path)+"?"+queryString:path},normalize:function(path){return path.replace(/^\/*/,"/")}};module.exports=Path},{"./URL":15,"./mergeProperties":19,querystring:31,"react/lib/invariant":60}],15:[function(_dereq_,module){var urlEncodedSpaceRE=/\+/g,encodedSpaceRE=/%20/g,URL={decode:function(str){return str=str.replace(urlEncodedSpaceRE," "),decodeURIComponent(str)},encode:function(str){return str=encodeURIComponent(str),str.replace(encodedSpaceRE,"+")}};module.exports=URL},{}],16:[function(_dereq_,module){function goBack(){URLStore.back()}var URLStore=_dereq_("../stores/URLStore");module.exports=goBack},{"../stores/URLStore":28}],17:[function(_dereq_,module){function makeHref(routeName,params,query){var path=makePath(routeName,params,query);return"hash"===URLStore.getLocation()?"#"+path:path}var URLStore=_dereq_("../stores/URLStore"),makePath=_dereq_("./makePath");module.exports=makeHref},{"../stores/URLStore":28,"./makePath":18}],18:[function(_dereq_,module){function makePath(to,params,query){var path;if("/"===to.charAt(0))path=Path.normalize(to);else{var route=RouteStore.getRouteByName(to);invariant(route,'Unable to find a route named "'+to+'". Make sure you have a <Route name="'+to+'"> defined somewhere in your routes'),path=route.props.path}return Path.withQuery(Path.injectParams(path,params),query)}var invariant=_dereq_("react/lib/invariant"),RouteStore=_dereq_("../stores/RouteStore"),Path=_dereq_("./Path");module.exports=makePath},{"../stores/RouteStore":27,"./Path":14,"react/lib/invariant":60}],19:[function(_dereq_,module){function mergeProperties(object,properties){for(var property in properties)properties.hasOwnProperty(property)&&(object[property]=properties[property]);return object}module.exports=mergeProperties},{}],20:[function(_dereq_,module){function replaceWith(to,params,query){URLStore.replace(makePath(to,params,query))}var URLStore=_dereq_("../stores/URLStore"),makePath=_dereq_("./makePath");module.exports=replaceWith},{"../stores/URLStore":28,"./makePath":18}],21:[function(_dereq_,module){function resolveAsyncState(asyncState,setState){if(null==asyncState)return Promise.resolve();var keys=Object.keys(asyncState);return Promise.all(keys.map(function(key){return Promise.resolve(asyncState[key]).then(function(value){var newState={};newState[key]=value,setState(newState)})}))}var Promise=_dereq_("es6-promise").Promise;module.exports=resolveAsyncState},{"es6-promise":32}],22:[function(_dereq_,module){function transitionTo(to,params,query){URLStore.push(makePath(to,params,query))}var URLStore=_dereq_("../stores/URLStore"),makePath=_dereq_("./makePath");module.exports=transitionTo},{"../stores/URLStore":28,"./makePath":18}],23:[function(_dereq_,module){function withoutProperties(object,properties){var result={};for(var property in object)object.hasOwnProperty(property)&&!properties[property]&&(result[property]=object[property]);return result}module.exports=withoutProperties},{}],24:[function(_dereq_,module){var ActiveStore=_dereq_("../stores/ActiveStore"),ActiveState={statics:{isActive:ActiveStore.isActive},componentWillMount:function(){ActiveStore.addChangeListener(this.handleActiveStateChange)},componentDidMount:function(){this.updateActiveState&&this.updateActiveState()},componentWillUnmount:function(){ActiveStore.removeChangeListener(this.handleActiveStateChange)},handleActiveStateChange:function(){this.isMounted()&&this.updateActiveState&&this.updateActiveState()}};module.exports=ActiveState},{"../stores/ActiveStore":26}],25:[function(_dereq_,module){var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,resolveAsyncState=_dereq_("../helpers/resolveAsyncState"),AsyncState={propTypes:{initialAsyncState:React.PropTypes.object},getInitialState:function(){return this.props.initialAsyncState||null},updateAsyncState:function(state){this.isMounted()&&this.setState(state)},componentDidMount:function(){!this.props.initialAsyncState&&this.constructor.getInitialAsyncState&&resolveAsyncState(this.constructor.getInitialAsyncState(this.props.params,this.props.query,this.updateAsyncState),this.updateAsyncState)}};module.exports=AsyncState},{"../helpers/resolveAsyncState":21}],26:[function(_dereq_,module){function routeIsActive(routeName){return _activeRoutes.some(function(route){return route.props.name===routeName})}function paramsAreActive(params){for(var property in params)if(_activeParams[property]!==String(params[property]))return!1;return!0}function queryIsActive(query){for(var property in query)if(_activeQuery[property]!==String(query[property]))return!1;return!0}function notifyChange(){_events.emit("change")}var _activeRoutes=[],_activeParams={},_activeQuery={},EventEmitter=_dereq_("event-emitter"),_events=EventEmitter(),ActiveStore={addChangeListener:function(listener){_events.on("change",listener)},removeChangeListener:function(listener){_events.off("change",listener)},updateState:function(state){state=state||{},_activeRoutes=state.activeRoutes||[],_activeParams=state.activeParams||{},_activeQuery=state.activeQuery||{},notifyChange()},isActive:function(routeName,params,query){var isActive=routeIsActive(routeName)&¶msAreActive(params);return query?isActive&&queryIsActive(query):isActive}};module.exports=ActiveStore},{"event-emitter":42}],27:[function(_dereq_,module){var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,invariant=_dereq_("react/lib/invariant"),Path=(_dereq_("react/lib/warning"),_dereq_("../helpers/Path")),_namedRoutes={},RouteStore={unregisterAllRoutes:function(){_namedRoutes={}},unregisterRoute:function(route){route.props.name&&delete _namedRoutes[route.props.name],React.Children.forEach(route.props.children,function(child){RouteStore.unregisterRoute(child)})},registerRoute:function(route,_parentRoute){if(route.props.path=route.props.path||route.props.name?Path.normalize(route.props.path||route.props.name):"/",invariant(React.isValidClass(route.props.handler),'The handler for Route "'+(route.props.name||route.props.path)+'" must be a valid React component'),_parentRoute){var paramNames=Path.extractParamNames(route.props.path);Path.extractParamNames(_parentRoute.props.path).forEach(function(paramName){invariant(-1!==paramNames.indexOf(paramName),'The nested route path "'+route.props.path+'" is missing the "'+paramName+'" parameter of its parent path "'+_parentRoute.props.path+'"')})}if(route.props.name){var existingRoute=_namedRoutes[route.props.name];invariant(!existingRoute||route===existingRoute,'You cannot use the name "'+route.props.name+'" for more than one route'),_namedRoutes[route.props.name]=route}React.Children.forEach(route.props.children,function(child){RouteStore.registerRoute(child,route)})},getRouteByName:function(routeName){return _namedRoutes[routeName]||null}};module.exports=RouteStore},{"../helpers/Path":14,"react/lib/invariant":60,"react/lib/warning":61}],28:[function(_dereq_,module){function getWindowChangeEvent(location){return"history"===location?"popstate":window.addEventListener?"hashchange":"onhashchange"}function getWindowPath(){return window.location.pathname+window.location.search}function notifyChange(){_events.emit("change")}function supportsHistory(){var ua=navigator.userAgent;return-1===ua.indexOf("Android 2.")&&-1===ua.indexOf("Android 4.0")||-1===ua.indexOf("Mobile Safari")||-1!==ua.indexOf("Chrome")?window.history&&"pushState"in window.history:!1}var _location,ExecutionEnvironment=_dereq_("react/lib/ExecutionEnvironment"),invariant=_dereq_("react/lib/invariant"),warning=_dereq_("react/lib/warning"),_currentPath="/",_lastPath=null,EventEmitter=_dereq_("event-emitter"),_events=EventEmitter(),URLStore={addChangeListener:function(listener){_events.on("change",listener)},removeChangeListener:function(listener){_events.off("change",listener)},getLocation:function(){return _location||"hash"},getCurrentPath:function(){return"history"===_location||"disabledHistory"===_location?getWindowPath():"hash"===_location?window.location.hash.substr(1):_currentPath},push:function(path){return path!==this.getCurrentPath()?"disabledHistory"===_location?window.location=path:void("history"===_location?(window.history.pushState({path:path},"",path),notifyChange()):"hash"===_location?window.location.hash=path:(_lastPath=_currentPath,_currentPath=path,notifyChange())):void 0},replace:function(path){"disabledHistory"===_location?window.location.replace(path):"history"===_location?(window.history.replaceState({path:path},"",path),notifyChange()):"hash"===_location?window.location.replace(getWindowPath()+"#"+path):(_currentPath=path,notifyChange())},back:function(){null!=_location?window.history.back():(invariant(_lastPath,"You cannot make the URL store go back more than once when it does not use the DOM"),_currentPath=_lastPath,_lastPath=null,notifyChange())},isSetup:function(){return null!=_location},setup:function(location){if(invariant(ExecutionEnvironment.canUseDOM,"You cannot setup the URL store in an environment with no DOM"),null!=_location)return void warning(_location===location,"The URL store was already setup using "+_location+" location. You cannot use "+location+" location on the same page");if("history"===location&&!supportsHistory())return void(_location="disabledHistory");var changeEvent=getWindowChangeEvent(location);invariant(changeEvent||"disabledHistory"===location,'The URL store location "'+location+'" is not valid. It must be either "hash" or "history"'),_location=location,"hash"===location&&""===window.location.hash&&URLStore.replace("/"),window.addEventListener?window.addEventListener(changeEvent,notifyChange,!1):window.attachEvent(changeEvent,notifyChange),notifyChange()},teardown:function(){if(null!=_location){var changeEvent=getWindowChangeEvent(_location);window.removeEventListener?window.removeEventListener(changeEvent,notifyChange,!1):window.detachEvent(changeEvent,notifyChange),_location=null,_currentPath="/"}}};module.exports=URLStore},{"event-emitter":42,"react/lib/ExecutionEnvironment":57,"react/lib/invariant":60,"react/lib/warning":61}],29:[function(_dereq_,module){"use strict";function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop)}module.exports=function(qs,sep,eq,options){sep=sep||"&",eq=eq||"=";var obj={};if("string"!=typeof qs||0===qs.length)return obj;var regexp=/\+/g;qs=qs.split(sep);var maxKeys=1e3;options&&"number"==typeof options.maxKeys&&(maxKeys=options.maxKeys);var len=qs.length;maxKeys>0&&len>maxKeys&&(len=maxKeys);for(var i=0;len>i;++i){var kstr,vstr,k,v,x=qs[i].replace(regexp,"%20"),idx=x.indexOf(eq);idx>=0?(kstr=x.substr(0,idx),vstr=x.substr(idx+1)):(kstr=x,vstr=""),k=decodeURIComponent(kstr),v=decodeURIComponent(vstr),hasOwnProperty(obj,k)?isArray(obj[k])?obj[k].push(v):obj[k]=[obj[k],v]:obj[k]=v}return obj};var isArray=Array.isArray||function(xs){return"[object Array]"===Object.prototype.toString.call(xs)}},{}],30:[function(_dereq_,module){"use strict";function map(xs,f){if(xs.map)return xs.map(f);for(var res=[],i=0;i<xs.length;i++)res.push(f(xs[i],i));return res}var stringifyPrimitive=function(v){switch(typeof v){case"string":return v;case"boolean":return v?"true":"false";case"number":return isFinite(v)?v:"";default:return""}};module.exports=function(obj,sep,eq,name){return sep=sep||"&",eq=eq||"=",null===obj&&(obj=void 0),"object"==typeof obj?map(objectKeys(obj),function(k){var ks=encodeURIComponent(stringifyPrimitive(k))+eq;return isArray(obj[k])?map(obj[k],function(v){return ks+encodeURIComponent(stringifyPrimitive(v))}).join(sep):ks+encodeURIComponent(stringifyPrimitive(obj[k]))}).join(sep):name?encodeURIComponent(stringifyPrimitive(name))+eq+encodeURIComponent(stringifyPrimitive(obj)):""};var isArray=Array.isArray||function(xs){return"[object Array]"===Object.prototype.toString.call(xs)},objectKeys=Object.keys||function(obj){var res=[];for(var key in obj)Object.prototype.hasOwnProperty.call(obj,key)&&res.push(key);return res}},{}],31:[function(_dereq_,module,exports){"use strict";exports.decode=exports.parse=_dereq_("./decode"),exports.encode=exports.stringify=_dereq_("./encode")},{"./decode":29,"./encode":30}],32:[function(_dereq_,module,exports){"use strict";var Promise=_dereq_("./promise/promise").Promise,polyfill=_dereq_("./promise/polyfill").polyfill;exports.Promise=Promise,exports.polyfill=polyfill},{"./promise/polyfill":36,"./promise/promise":37}],33:[function(_dereq_,module,exports){"use strict";function all(promises){var Promise=this;if(!isArray(promises))throw new TypeError("You must pass an array to all.");return new Promise(function(resolve,reject){function resolver(index){return function(value){resolveAll(index,value)}}function resolveAll(index,value){results[index]=value,0===--remaining&&resolve(results)}var promise,results=[],remaining=promises.length;0===remaining&&resolve([]);for(var i=0;i<promises.length;i++)promise=promises[i],promise&&isFunction(promise.then)?promise.then(resolver(i),reject):resolveAll(i,promise)})}var isArray=_dereq_("./utils").isArray,isFunction=_dereq_("./utils").isFunction;exports.all=all},{"./utils":41}],34:[function(_dereq_,module,exports){"use strict";function useNextTick(){return function(){process.nextTick(flush)}}function useMutationObserver(){var iterations=0,observer=new BrowserMutationObserver(flush),node=document.createTextNode("");return observer.observe(node,{characterData:!0}),function(){node.data=iterations=++iterations%2}}function useSetTimeout(){return function(){local.setTimeout(flush,1)}}function flush(){for(var i=0;i<queue.length;i++){var tuple=queue[i],callback=tuple[0],arg=tuple[1];callback(arg)}queue=[]}function asap(callback,arg){var length=queue.push([callback,arg]);1===length&&scheduleFlush()}var scheduleFlush,browserGlobal="undefined"!=typeof window?window:{},BrowserMutationObserver=browserGlobal.MutationObserver||browserGlobal.WebKitMutationObserver,local="undefined"!=typeof global?global:void 0===this?window:this,queue=[];scheduleFlush="undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?useNextTick():BrowserMutationObserver?useMutationObserver():useSetTimeout(),exports.asap=asap},{}],35:[function(_dereq_,module,exports){"use strict";function configure(name,value){return 2!==arguments.length?config[name]:void(config[name]=value)}var config={instrument:!1};exports.config=config,exports.configure=configure},{}],36:[function(_dereq_,module,exports){"use strict";function polyfill(){var local;local="undefined"!=typeof global?global:"undefined"!=typeof window&&window.document?window:self;var es6PromiseSupport="Promise"in local&&"resolve"in local.Promise&&"reject"in local.Promise&&"all"in local.Promise&&"race"in local.Promise&&function(){var resolve;return new local.Promise(function(r){resolve=r}),isFunction(resolve)}();es6PromiseSupport||(local.Promise=RSVPPromise)}var RSVPPromise=_dereq_("./promise").Promise,isFunction=_dereq_("./utils").isFunction;exports.polyfill=polyfill},{"./promise":37,"./utils":41}],37:[function(_dereq_,module,exports){"use strict";function Promise(resolver){if(!isFunction(resolver))throw new TypeError("You must pass a resolver function as the first argument to the promise constructor");if(!(this instanceof Promise))throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");this._subscribers=[],invokeResolver(resolver,this)}function invokeResolver(resolver,promise){function resolvePromise(value){resolve(promise,value)}function rejectPromise(reason){reject(promise,reason)}try{resolver(resolvePromise,rejectPromise)}catch(e){rejectPromise(e)}}function invokeCallback(settled,promise,callback,detail){var value,error,succeeded,failed,hasCallback=isFunction(callback);if(hasCallback)try{value=callback(detail),succeeded=!0}catch(e){failed=!0,error=e}else value=detail,succeeded=!0;handleThenable(promise,value)||(hasCallback&&succeeded?resolve(promise,value):failed?reject(promise,error):settled===FULFILLED?resolve(promise,value):settled===REJECTED&&reject(promise,value))}function subscribe(parent,child,onFulfillment,onRejection){var subscribers=parent._subscribers,length=subscribers.length;subscribers[length]=child,subscribers[length+FULFILLED]=onFulfillment,subscribers[length+REJECTED]=onRejection}function publish(promise,settled){for(var child,callback,subscribers=promise._subscribers,detail=promise._detail,i=0;i<subscribers.length;i+=3)child=subscribers[i],callback=subscribers[i+settled],invokeCallback(settled,child,callback,detail);promise._subscribers=null}function handleThenable(promise,value){var resolved,then=null;try{if(promise===value)throw new TypeError("A promises callback cannot return that same promise.");if(objectOrFunction(value)&&(then=value.then,isFunction(then)))return then.call(value,function(val){return resolved?!0:(resolved=!0,void(value!==val?resolve(promise,val):fulfill(promise,val)))},function(val){return resolved?!0:(resolved=!0,void reject(promise,val))}),!0}catch(error){return resolved?!0:(reject(promise,error),!0) | ||
}return!1}function resolve(promise,value){promise===value?fulfill(promise,value):handleThenable(promise,value)||fulfill(promise,value)}function fulfill(promise,value){promise._state===PENDING&&(promise._state=SEALED,promise._detail=value,config.async(publishFulfillment,promise))}function reject(promise,reason){promise._state===PENDING&&(promise._state=SEALED,promise._detail=reason,config.async(publishRejection,promise))}function publishFulfillment(promise){publish(promise,promise._state=FULFILLED)}function publishRejection(promise){publish(promise,promise._state=REJECTED)}var config=_dereq_("./config").config,objectOrFunction=(_dereq_("./config").configure,_dereq_("./utils").objectOrFunction),isFunction=_dereq_("./utils").isFunction,all=(_dereq_("./utils").now,_dereq_("./all").all),race=_dereq_("./race").race,staticResolve=_dereq_("./resolve").resolve,staticReject=_dereq_("./reject").reject,asap=_dereq_("./asap").asap;config.async=asap;var PENDING=void 0,SEALED=0,FULFILLED=1,REJECTED=2;Promise.prototype={constructor:Promise,_state:void 0,_detail:void 0,_subscribers:void 0,then:function(onFulfillment,onRejection){var promise=this,thenPromise=new this.constructor(function(){});if(this._state){var callbacks=arguments;config.async(function(){invokeCallback(promise._state,thenPromise,callbacks[promise._state-1],promise._detail)})}else subscribe(this,thenPromise,onFulfillment,onRejection);return thenPromise},"catch":function(onRejection){return this.then(null,onRejection)}},Promise.all=all,Promise.race=race,Promise.resolve=staticResolve,Promise.reject=staticReject,exports.Promise=Promise},{"./all":33,"./asap":34,"./config":35,"./race":38,"./reject":39,"./resolve":40,"./utils":41}],38:[function(_dereq_,module,exports){"use strict";function race(promises){var Promise=this;if(!isArray(promises))throw new TypeError("You must pass an array to race.");return new Promise(function(resolve,reject){for(var promise,i=0;i<promises.length;i++)promise=promises[i],promise&&"function"==typeof promise.then?promise.then(resolve,reject):resolve(promise)})}var isArray=_dereq_("./utils").isArray;exports.race=race},{"./utils":41}],39:[function(_dereq_,module,exports){"use strict";function reject(reason){var Promise=this;return new Promise(function(resolve,reject){reject(reason)})}exports.reject=reject},{}],40:[function(_dereq_,module,exports){"use strict";function resolve(value){if(value&&"object"==typeof value&&value.constructor===this)return value;var Promise=this;return new Promise(function(resolve){resolve(value)})}exports.resolve=resolve},{}],41:[function(_dereq_,module,exports){"use strict";function objectOrFunction(x){return isFunction(x)||"object"==typeof x&&null!==x}function isFunction(x){return"function"==typeof x}function isArray(x){return"[object Array]"===Object.prototype.toString.call(x)}var now=Date.now||function(){return(new Date).getTime()};exports.objectOrFunction=objectOrFunction,exports.isFunction=isFunction,exports.isArray=isArray,exports.now=now},{}],42:[function(_dereq_,module,exports){"use strict";var on,once,off,emit,methods,descriptors,base,d=_dereq_("d"),callable=_dereq_("es5-ext/object/valid-callable"),apply=Function.prototype.apply,call=Function.prototype.call,create=Object.create,defineProperty=Object.defineProperty,defineProperties=Object.defineProperties,hasOwnProperty=Object.prototype.hasOwnProperty,descriptor={configurable:!0,enumerable:!1,writable:!0};on=function(type,listener){var data;return callable(listener),hasOwnProperty.call(this,"__ee__")?data=this.__ee__:(data=descriptor.value=create(null),defineProperty(this,"__ee__",descriptor),descriptor.value=null),data[type]?"object"==typeof data[type]?data[type].push(listener):data[type]=[data[type],listener]:data[type]=listener,this},once=function(type,listener){var once,self;return callable(listener),self=this,on.call(this,type,once=function(){off.call(self,type,once),apply.call(listener,this,arguments)}),once.__eeOnceListener__=listener,this},off=function(type,listener){var data,listeners,candidate,i;if(callable(listener),!hasOwnProperty.call(this,"__ee__"))return this;if(data=this.__ee__,!data[type])return this;if(listeners=data[type],"object"==typeof listeners)for(i=0;candidate=listeners[i];++i)(candidate===listener||candidate.__eeOnceListener__===listener)&&(2===listeners.length?data[type]=listeners[i?0:1]:listeners.splice(i,1));else(listeners===listener||listeners.__eeOnceListener__===listener)&&delete data[type];return this},emit=function(type){var i,l,listener,listeners,args;if(hasOwnProperty.call(this,"__ee__")&&(listeners=this.__ee__[type]))if("object"==typeof listeners){for(l=arguments.length,args=new Array(l-1),i=1;l>i;++i)args[i-1]=arguments[i];for(listeners=listeners.slice(),i=0;listener=listeners[i];++i)apply.call(listener,this,args)}else switch(arguments.length){case 1:call.call(listeners,this);break;case 2:call.call(listeners,this,arguments[1]);break;case 3:call.call(listeners,this,arguments[1],arguments[2]);break;default:for(l=arguments.length,args=new Array(l-1),i=1;l>i;++i)args[i-1]=arguments[i];apply.call(listeners,this,args)}},methods={on:on,once:once,off:off,emit:emit},descriptors={on:d(on),once:d(once),off:d(off),emit:d(emit)},base=defineProperties({},descriptors),module.exports=exports=function(o){return null==o?create(base):defineProperties(Object(o),descriptors)},exports.methods=methods},{d:43,"es5-ext/object/valid-callable":52}],43:[function(_dereq_,module){"use strict";var d,assign=_dereq_("es5-ext/object/assign"),normalizeOpts=_dereq_("es5-ext/object/normalize-options"),isCallable=_dereq_("es5-ext/object/is-callable"),contains=_dereq_("es5-ext/string/#/contains");d=module.exports=function(dscr,value){var c,e,w,options,desc;return arguments.length<2||"string"!=typeof dscr?(options=value,value=dscr,dscr=null):options=arguments[2],null==dscr?(c=w=!0,e=!1):(c=contains.call(dscr,"c"),e=contains.call(dscr,"e"),w=contains.call(dscr,"w")),desc={value:value,configurable:c,enumerable:e,writable:w},options?assign(normalizeOpts(options),desc):desc},d.gs=function(dscr,get,set){var c,e,options,desc;return"string"!=typeof dscr?(options=set,set=get,get=dscr,dscr=null):options=arguments[3],null==get?get=void 0:isCallable(get)?null==set?set=void 0:isCallable(set)||(options=set,set=void 0):(options=get,get=set=void 0),null==dscr?(c=!0,e=!1):(c=contains.call(dscr,"c"),e=contains.call(dscr,"e")),desc={get:get,set:set,configurable:c,enumerable:e},options?assign(normalizeOpts(options),desc):desc}},{"es5-ext/object/assign":44,"es5-ext/object/is-callable":47,"es5-ext/object/normalize-options":51,"es5-ext/string/#/contains":54}],44:[function(_dereq_,module){"use strict";module.exports=_dereq_("./is-implemented")()?Object.assign:_dereq_("./shim")},{"./is-implemented":45,"./shim":46}],45:[function(_dereq_,module){"use strict";module.exports=function(){var obj,assign=Object.assign;return"function"!=typeof assign?!1:(obj={foo:"raz"},assign(obj,{bar:"dwa"},{trzy:"trzy"}),obj.foo+obj.bar+obj.trzy==="razdwatrzy")}},{}],46:[function(_dereq_,module){"use strict";var keys=_dereq_("../keys"),value=_dereq_("../valid-value"),max=Math.max;module.exports=function(dest,src){var error,i,assign,l=max(arguments.length,2);for(dest=Object(value(dest)),assign=function(key){try{dest[key]=src[key]}catch(e){error||(error=e)}},i=1;l>i;++i)src=arguments[i],keys(src).forEach(assign);if(void 0!==error)throw error;return dest}},{"../keys":48,"../valid-value":53}],47:[function(_dereq_,module){"use strict";module.exports=function(obj){return"function"==typeof obj}},{}],48:[function(_dereq_,module){"use strict";module.exports=_dereq_("./is-implemented")()?Object.keys:_dereq_("./shim")},{"./is-implemented":49,"./shim":50}],49:[function(_dereq_,module){"use strict";module.exports=function(){try{return Object.keys("primitive"),!0}catch(e){return!1}}},{}],50:[function(_dereq_,module){"use strict";var keys=Object.keys;module.exports=function(object){return keys(null==object?object:Object(object))}},{}],51:[function(_dereq_,module){"use strict";var process,assign=_dereq_("./assign"),forEach=Array.prototype.forEach,create=Object.create,getPrototypeOf=Object.getPrototypeOf;process=function(src,obj){var proto=getPrototypeOf(src);return assign(proto?process(proto,obj):obj,src)},module.exports=function(){var result=create(null);return forEach.call(arguments,function(options){null!=options&&process(Object(options),result)}),result}},{"./assign":44}],52:[function(_dereq_,module){"use strict";module.exports=function(fn){if("function"!=typeof fn)throw new TypeError(fn+" is not a function");return fn}},{}],53:[function(_dereq_,module){"use strict";module.exports=function(value){if(null==value)throw new TypeError("Cannot use null or undefined");return value}},{}],54:[function(_dereq_,module){"use strict";module.exports=_dereq_("./is-implemented")()?String.prototype.contains:_dereq_("./shim")},{"./is-implemented":55,"./shim":56}],55:[function(_dereq_,module){"use strict";var str="razdwatrzy";module.exports=function(){return"function"!=typeof str.contains?!1:str.contains("dwa")===!0&&str.contains("foo")===!1}},{}],56:[function(_dereq_,module){"use strict";var indexOf=String.prototype.indexOf;module.exports=function(searchString){return indexOf.call(this,searchString,arguments[1])>-1}},{}],57:[function(_dereq_,module){"use strict";var canUseDOM=!("undefined"==typeof window||!window.document||!window.document.createElement),ExecutionEnvironment={canUseDOM:canUseDOM,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:canUseDOM&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:canUseDOM&&!!window.screen,isInWorker:!canUseDOM};module.exports=ExecutionEnvironment},{}],58:[function(_dereq_,module){function copyProperties(obj,a,b,c,d,e,f){obj=obj||{};for(var v,args=[a,b,c,d,e],ii=0;args[ii];){v=args[ii++];for(var k in v)obj[k]=v[k];v.hasOwnProperty&&v.hasOwnProperty("toString")&&"undefined"!=typeof v.toString&&obj.toString!==v.toString&&(obj.toString=v.toString)}return obj}module.exports=copyProperties},{}],59:[function(_dereq_,module){function makeEmptyFunction(arg){return function(){return arg}}function emptyFunction(){}var copyProperties=_dereq_("./copyProperties");copyProperties(emptyFunction,{thatReturns:makeEmptyFunction,thatReturnsFalse:makeEmptyFunction(!1),thatReturnsTrue:makeEmptyFunction(!0),thatReturnsNull:makeEmptyFunction(null),thatReturnsThis:function(){return this},thatReturnsArgument:function(arg){return arg}}),module.exports=emptyFunction},{"./copyProperties":58}],60:[function(_dereq_,module){"use strict";var invariant=function(condition,format,a,b,c,d,e,f){if(!condition){var error;if(void 0===format)error=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var args=[a,b,c,d,e,f],argIndex=0;error=new Error("Invariant Violation: "+format.replace(/%s/g,function(){return args[argIndex++]}))}throw error.framesToPop=1,error}};module.exports=invariant},{}],61:[function(_dereq_,module){"use strict";var emptyFunction=_dereq_("./emptyFunction"),warning=emptyFunction;module.exports=warning},{"./emptyFunction":59}],62:[function(_dereq_,module){module.exports=_dereq_("./modules/helpers/replaceWith")},{"./modules/helpers/replaceWith":20}],63:[function(_dereq_,module){module.exports=_dereq_("./modules/helpers/transitionTo")},{"./modules/helpers/transitionTo":22}]},{},[8])(8)}); | ||
!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(){return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)s(r[o]);return s}({1:[function(_dereq_,module){module.exports=_dereq_("./modules/mixins/ActiveState")},{"./modules/mixins/ActiveState":33}],2:[function(_dereq_,module){module.exports=_dereq_("./modules/mixins/AsyncState")},{"./modules/mixins/AsyncState":34}],3:[function(_dereq_,module){module.exports=_dereq_("./modules/components/DefaultRoute")},{"./modules/components/DefaultRoute":11}],4:[function(_dereq_,module){module.exports=_dereq_("./modules/components/Link")},{"./modules/components/Link":12}],5:[function(_dereq_,module){module.exports=_dereq_("./modules/components/Redirect")},{"./modules/components/Redirect":13}],6:[function(_dereq_,module){module.exports=_dereq_("./modules/components/Route")},{"./modules/components/Route":14}],7:[function(_dereq_,module){module.exports=_dereq_("./modules/components/Routes")},{"./modules/components/Routes":15}],8:[function(_dereq_,module){module.exports=_dereq_("./modules/helpers/goBack")},{"./modules/helpers/goBack":21}],9:[function(_dereq_,module,exports){exports.ActiveState=_dereq_("./ActiveState"),exports.AsyncState=_dereq_("./AsyncState"),exports.DefaultRoute=_dereq_("./DefaultRoute"),exports.Link=_dereq_("./Link"),exports.Redirect=_dereq_("./Redirect"),exports.Route=_dereq_("./Route"),exports.Routes=_dereq_("./Routes"),exports.goBack=_dereq_("./goBack"),exports.replaceWith=_dereq_("./replaceWith"),exports.transitionTo=_dereq_("./transitionTo"),exports.makeHref=_dereq_("./makeHref")},{"./ActiveState":1,"./AsyncState":2,"./DefaultRoute":3,"./Link":4,"./Redirect":5,"./Route":6,"./Routes":7,"./goBack":8,"./makeHref":10,"./replaceWith":62,"./transitionTo":63}],10:[function(_dereq_,module){module.exports=_dereq_("./modules/helpers/makeHref")},{"./modules/helpers/makeHref":23}],11:[function(_dereq_,module){function DefaultRoute(props){return Route(merge(props,{name:null,path:null}))}var merge=_dereq_("react/lib/merge"),Route=_dereq_("./Route");module.exports=DefaultRoute},{"./Route":14,"react/lib/merge":57}],12:[function(_dereq_,module){function isLeftClickEvent(event){return 0===event.button}function isModifiedEvent(event){return!!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,ActiveState=_dereq_("../mixins/ActiveState"),withoutProperties=_dereq_("../helpers/withoutProperties"),transitionTo=_dereq_("../helpers/transitionTo"),hasOwnProperty=_dereq_("../helpers/hasOwnProperty"),makeHref=_dereq_("../helpers/makeHref"),RESERVED_PROPS={to:!0,key:!0,className:!0,activeClassName:!0,query:!0,children:!0},Link=React.createClass({displayName:"Link",mixins:[ActiveState],statics:{getUnreservedProps:function(props){return withoutProperties(props,RESERVED_PROPS)}},propTypes:{to:React.PropTypes.string.isRequired,activeClassName:React.PropTypes.string.isRequired,query:React.PropTypes.object,onClick:React.PropTypes.func},getDefaultProps:function(){return{activeClassName:"active"}},getInitialState:function(){return{isActive:!1}},getParams:function(){return Link.getUnreservedProps(this.props)},getHref:function(){return makeHref(this.props.to,this.getParams(),this.props.query)},getClassName:function(){var className=this.props.className||"";return this.state.isActive?className+" "+this.props.activeClassName:className},componentWillReceiveProps:function(nextProps){var params=Link.getUnreservedProps(nextProps);this.setState({isActive:Link.isActive(nextProps.to,params,nextProps.query)})},updateActiveState:function(){this.setState({isActive:Link.isActive(this.props.to,this.getParams(),this.props.query)})},handleClick:function(event){var ret,allowTransition=!0;this.props.onClick&&(ret=this.props.onClick(event)),!isModifiedEvent(event)&&isLeftClickEvent(event)&&((ret===!1||event.defaultPrevented===!0)&&(allowTransition=!1),event.preventDefault(),allowTransition&&transitionTo(this.props.to,this.getParams(),this.props.query))},render:function(){var props={href:this.getHref(),className:this.getClassName(),onClick:this.handleClick};for(var propName in this.props)hasOwnProperty(this.props,propName)&&hasOwnProperty(props,propName)===!1&&(props[propName]=this.props[propName]);return React.DOM.a(props,this.props.children)}});module.exports=Link},{"../helpers/hasOwnProperty":22,"../helpers/makeHref":23,"../helpers/transitionTo":28,"../helpers/withoutProperties":29,"../mixins/ActiveState":33}],13:[function(_dereq_,module){function createRedirectHandler(to){return React.createClass({statics:{willTransitionTo:function(transition,params,query){transition.redirect(to,params,query)}},render:function(){return null}})}function Redirect(props){return Route({name:props.name,path:props.from||props.path,handler:createRedirectHandler(props.to)})}var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,Route=_dereq_("./Route");module.exports=Redirect},{"./Route":14}],14:[function(_dereq_,module){var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,withoutProperties=_dereq_("../helpers/withoutProperties"),RESERVED_PROPS={handler:!0,path:!0,defaultRoute:!0,paramNames:!0,children:!0},Route=React.createClass({displayName:"Route",statics:{getUnreservedProps:function(props){return withoutProperties(props,RESERVED_PROPS)}},propTypes:{preserveScrollPosition:React.PropTypes.bool.isRequired,handler:React.PropTypes.any.isRequired,path:React.PropTypes.string,name:React.PropTypes.string},getDefaultProps:function(){return{preserveScrollPosition:!1}},render:function(){throw new Error("The <Route> component should not be rendered directly. You may be missing a <Routes> wrapper around your list of routes.")}});module.exports=Route},{"../helpers/withoutProperties":29}],15:[function(_dereq_,module){function defaultAbortedTransitionHandler(transition){var reason=transition.abortReason;reason instanceof Redirect?replaceWith(reason.to,reason.params,reason.query):goBack()}function defaultActiveStateChangeHandler(state){ActiveStore.updateState(state)}function defaultTransitionErrorHandler(error){throw error}function findMatches(path,routes,defaultRoute){for(var route,params,matches=null,i=0,len=routes.length;len>i;++i){if(route=routes[i],matches=findMatches(path,route.props.children,route.props.defaultRoute),null!=matches){var rootParams=getRootMatch(matches).params;return params=route.props.paramNames.reduce(function(params,paramName){return params[paramName]=rootParams[paramName],params},{}),matches.unshift(makeMatch(route,params)),matches}if(params=Path.extractParams(route.props.path,path))return[makeMatch(route,params)]}return params=defaultRoute&&Path.extractParams(defaultRoute.props.path,path),params?[makeMatch(defaultRoute,params)]:matches}function makeMatch(route,params){return{route:route,params:params}}function hasMatch(matches,match){return matches.some(function(m){if(m.route!==match.route)return!1;for(var property in m.params)if(m.params[property]!==match.params[property])return!1;return!0})}function getRootMatch(matches){return matches[matches.length-1]}function updateMatchComponents(matches,refs){for(var component,i=0;component=refs[REF_NAME];)matches[i++].component=component,refs=component.refs}function runTransitionHooks(routes,transition){if(routes.state.path===transition.path)return Promise.resolve();var currentMatches=routes.state.matches,nextMatches=routes.match(transition.path);warning(nextMatches,'No route matches path "'+transition.path+'". Make sure you have <Route path="'+transition.path+'"> somewhere in your routes'),nextMatches||(nextMatches=[]);var fromMatches,toMatches;return currentMatches?(updateMatchComponents(currentMatches,routes.refs),fromMatches=currentMatches.filter(function(match){return!hasMatch(nextMatches,match)}),toMatches=nextMatches.filter(function(match){return!hasMatch(currentMatches,match)})):(fromMatches=[],toMatches=nextMatches),runTransitionFromHooks(fromMatches,transition).then(function(){return transition.isAborted?void 0:runTransitionToHooks(toMatches,transition).then(function(){if(!transition.isAborted){var rootMatch=getRootMatch(nextMatches),params=rootMatch&&rootMatch.params||{},query=Path.extractQuery(transition.path)||{};return{path:transition.path,matches:nextMatches,activeParams:params,activeQuery:query,activeRoutes:nextMatches.map(function(match){return match.route})}}})})}function runTransitionFromHooks(matches,transition){var promise=Promise.resolve();return reversedArray(matches).forEach(function(match){promise=promise.then(function(){var handler=match.route.props.handler;return!transition.isAborted&&handler.willTransitionFrom?handler.willTransitionFrom(transition,match.component):void 0})}),promise}function runTransitionToHooks(matches,transition){var promise=Promise.resolve();return matches.forEach(function(match){promise=promise.then(function(){var handler=match.route.props.handler;return!transition.isAborted&&handler.willTransitionTo?handler.willTransitionTo(transition,match.params):void 0})}),promise}function computeHandlerProps(matches,query){var childHandler,props={ref:null,key:null,params:null,query:null,activeRouteHandler:returnNull};return reversedArray(matches).forEach(function(match){var route=match.route;props=Route.getUnreservedProps(route.props),props.ref=REF_NAME,props.key=Path.injectParams(route.props.path,match.params),props.params=match.params,props.query=query,props.activeRouteHandler=childHandler?childHandler:returnNull,childHandler=function(props,addedProps){if(arguments.length>2&&"undefined"!=typeof arguments[2])throw new Error("Passing children to a route handler is not supported");return route.props.handler(copyProperties(props,addedProps))}.bind(this,props)}),props}function returnNull(){return null}function reversedArray(array){return array.slice(0).reverse()}function maybeScrollWindow(routes,rootRoute){routes.props.preserveScrollPosition||rootRoute.props.preserveScrollPosition||window.scrollTo(0,0)}var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,warning=_dereq_("react/lib/warning"),copyProperties=_dereq_("react/lib/copyProperties"),Promise=_dereq_("es6-promise").Promise,Route=_dereq_("../components/Route"),goBack=_dereq_("../helpers/goBack"),replaceWith=_dereq_("../helpers/replaceWith"),Path=_dereq_("../helpers/Path"),Redirect=_dereq_("../helpers/Redirect"),Transition=_dereq_("../helpers/Transition"),HashLocation=_dereq_("../locations/HashLocation"),HistoryLocation=_dereq_("../locations/HistoryLocation"),RefreshLocation=_dereq_("../locations/RefreshLocation"),ActiveStore=_dereq_("../stores/ActiveStore"),PathStore=_dereq_("../stores/PathStore"),RouteStore=_dereq_("../stores/RouteStore"),REF_NAME="__activeRoute__",NAMED_LOCATIONS={hash:HashLocation,history:HistoryLocation,refresh:RefreshLocation,disabled:RefreshLocation},Routes=React.createClass({displayName:"Routes",propTypes:{onAbortedTransition:React.PropTypes.func.isRequired,onActiveStateChange:React.PropTypes.func.isRequired,onTransitionError:React.PropTypes.func.isRequired,preserveScrollPosition:React.PropTypes.bool,location:function(props,propName,componentName){var location=props[propName];return"string"!=typeof location||location in NAMED_LOCATIONS?void 0:new Error('Unknown location "'+location+'", see '+componentName)}},getDefaultProps:function(){return{onAbortedTransition:defaultAbortedTransitionHandler,onActiveStateChange:defaultActiveStateChangeHandler,onTransitionError:defaultTransitionErrorHandler,preserveScrollPosition:!1,location:HashLocation}},getInitialState:function(){return{routes:RouteStore.registerChildren(this.props.children,this)}},getLocation:function(){var location=this.props.location;return"string"==typeof location?NAMED_LOCATIONS[location]:location},componentWillMount:function(){PathStore.setup(this.getLocation()),PathStore.addChangeListener(this.handlePathChange)},componentDidMount:function(){this.handlePathChange()},componentWillUnmount:function(){PathStore.removeChangeListener(this.handlePathChange)},handlePathChange:function(){this.dispatch(PathStore.getCurrentPath())},match:function(path){return findMatches(Path.withoutQuery(path),this.state.routes,this.props.defaultRoute)},dispatch:function(path,returnRejectedPromise){var transition=new Transition(path),routes=this,promise=runTransitionHooks(routes,transition).then(function(nextState){if(transition.isAborted)routes.props.onAbortedTransition(transition);else if(nextState){routes.setState(nextState),routes.props.onActiveStateChange(nextState);var rootMatch=getRootMatch(nextState.matches);rootMatch&&maybeScrollWindow(routes,rootMatch.route)}return transition});return returnRejectedPromise||(promise=promise.then(void 0,function(error){setTimeout(function(){routes.props.onTransitionError(error)})})),promise},render:function(){if(!this.state.path)return null;var matches=this.state.matches;return matches.length?matches[0].route.props.handler(computeHandlerProps(matches,this.state.activeQuery)):null}});module.exports=Routes},{"../components/Route":14,"../helpers/Path":16,"../helpers/Redirect":17,"../helpers/Transition":18,"../helpers/goBack":21,"../helpers/replaceWith":25,"../locations/HashLocation":30,"../locations/HistoryLocation":31,"../locations/RefreshLocation":32,"../stores/ActiveStore":35,"../stores/PathStore":36,"../stores/RouteStore":37,"es6-promise":42,"react/lib/copyProperties":53,"react/lib/warning":61}],16:[function(_dereq_,module){function getParamName(pathSegment){return"*"===pathSegment?"splat":pathSegment.substr(1)}function compilePattern(pattern){if(_compiledPatterns[pattern])return _compiledPatterns[pattern];var compiled=_compiledPatterns[pattern]={},paramNames=compiled.paramNames=[],source=pattern.replace(paramMatcher,function(match,pathSegment){return paramNames.push(getParamName(pathSegment)),"*"===pathSegment?"(.*?)":"([^/?#]+)"});return compiled.matcher=new RegExp("^"+source+"$","i"),compiled}function isDynamicPattern(pattern){return-1!==pattern.indexOf(":")||-1!==pattern.indexOf("*")}var invariant=_dereq_("react/lib/invariant"),copyProperties=_dereq_("react/lib/copyProperties"),qs=_dereq_("querystring"),URL=_dereq_("./URL"),paramMatcher=/((?::[a-z_$][a-z0-9_$]*)|\*)/gi,queryMatcher=/\?(.+)/,_compiledPatterns={},Path={extractParams:function(pattern,path){if(!pattern)return null;if(!isDynamicPattern(pattern))return pattern===URL.decode(path)?{}:null;var compiled=compilePattern(pattern),match=URL.decode(path).match(compiled.matcher);if(!match)return null;var params={};return compiled.paramNames.forEach(function(paramName,index){params[paramName]=match[index+1]}),params},extractParamNames:function(pattern){return pattern?compilePattern(pattern).paramNames:[]},injectParams:function(pattern,params){return pattern?isDynamicPattern(pattern)?(params=params||{},pattern.replace(paramMatcher,function(match,pathSegment){var paramName=getParamName(pathSegment);return invariant(null!=params[paramName],'Missing "'+paramName+'" parameter for path "'+pattern+'"'),String(params[paramName]).split("/").map(URL.encode).join("/")})):pattern:null},extractQuery:function(path){var match=path.match(queryMatcher);return match&&qs.parse(match[1])},withoutQuery:function(path){return path.replace(queryMatcher,"")},withQuery:function(path,query){var existingQuery=Path.extractQuery(path);existingQuery&&(query=query?copyProperties(existingQuery,query):existingQuery);var queryString=query&&qs.stringify(query);return queryString?Path.withoutQuery(path)+"?"+queryString:path},normalize:function(path){return path.replace(/^\/*/,"/")}};module.exports=Path},{"./URL":19,querystring:41,"react/lib/copyProperties":53,"react/lib/invariant":55}],17:[function(_dereq_,module){function Redirect(to,params,query){this.to=to,this.params=params,this.query=query}module.exports=Redirect},{}],18:[function(_dereq_,module){function Transition(path){this.path=path,this.abortReason=null,this.isAborted=!1}var mixInto=_dereq_("react/lib/mixInto"),transitionTo=_dereq_("./transitionTo"),Redirect=_dereq_("./Redirect");mixInto(Transition,{abort:function(reason){this.abortReason=reason,this.isAborted=!0},redirect:function(to,params,query){this.abort(new Redirect(to,params,query))},retry:function(){transitionTo(this.path)}}),module.exports=Transition},{"./Redirect":17,"./transitionTo":28,"react/lib/mixInto":60}],19:[function(_dereq_,module){var urlEncodedSpaceRE=/\+/g,encodedSpaceRE=/%20/g,URL={decode:function(str){return str=str.replace(urlEncodedSpaceRE," "),decodeURIComponent(str)},encode:function(str){return str=encodeURIComponent(str),str.replace(encodedSpaceRE,"+")}};module.exports=URL},{}],20:[function(_dereq_,module){function getWindowPath(){return window.location.pathname+window.location.search}module.exports=getWindowPath},{}],21:[function(_dereq_,module){function goBack(){PathStore.pop()}var PathStore=_dereq_("../stores/PathStore");module.exports=goBack},{"../stores/PathStore":36}],22:[function(_dereq_,module){module.exports=Function.prototype.call.bind(Object.prototype.hasOwnProperty)},{}],23:[function(_dereq_,module){function makeHref(to,params,query){var path=makePath(to,params,query);return PathStore.getLocation()===HashLocation?"#"+path:path}var HashLocation=_dereq_("../locations/HashLocation"),PathStore=_dereq_("../stores/PathStore"),makePath=_dereq_("./makePath");module.exports=makeHref},{"../locations/HashLocation":30,"../stores/PathStore":36,"./makePath":24}],24:[function(_dereq_,module){function makePath(to,params,query){var path;if("/"===to.charAt(0))path=Path.normalize(to);else{var route=RouteStore.getRouteByName(to);invariant(route,'Unable to find a route named "'+to+'". Make sure you have a <Route name="'+to+'"> defined somewhere in your routes'),path=route.props.path}return Path.withQuery(Path.injectParams(path,params),query)}var invariant=_dereq_("react/lib/invariant"),RouteStore=_dereq_("../stores/RouteStore"),Path=_dereq_("./Path");module.exports=makePath},{"../stores/RouteStore":37,"./Path":16,"react/lib/invariant":55}],25:[function(_dereq_,module){function replaceWith(to,params,query){PathStore.replace(makePath(to,params,query))}var PathStore=_dereq_("../stores/PathStore"),makePath=_dereq_("./makePath");module.exports=replaceWith},{"../stores/PathStore":36,"./makePath":24}],26:[function(_dereq_,module){function resolveAsyncState(asyncState,setState){if(null==asyncState)return Promise.resolve();var keys=Object.keys(asyncState);return Promise.all(keys.map(function(key){return Promise.resolve(asyncState[key]).then(function(value){var newState={};newState[key]=value,setState(newState)})}))}var Promise=_dereq_("es6-promise").Promise;module.exports=resolveAsyncState},{"es6-promise":42}],27:[function(_dereq_,module){function supportsHistory(){var ua=navigator.userAgent;return-1===ua.indexOf("Android 2.")&&-1===ua.indexOf("Android 4.0")||-1===ua.indexOf("Mobile Safari")||-1!==ua.indexOf("Chrome")?window.history&&"pushState"in window.history:!1}module.exports=supportsHistory},{}],28:[function(_dereq_,module){function transitionTo(to,params,query){PathStore.push(makePath(to,params,query))}var PathStore=_dereq_("../stores/PathStore"),makePath=_dereq_("./makePath");module.exports=transitionTo},{"../stores/PathStore":36,"./makePath":24}],29:[function(_dereq_,module){function withoutProperties(object,properties){var result={};for(var property in object)object.hasOwnProperty(property)&&!properties[property]&&(result[property]=object[property]);return result}module.exports=withoutProperties},{}],30:[function(_dereq_,module){var _onChange,invariant=_dereq_("react/lib/invariant"),ExecutionEnvironment=_dereq_("react/lib/ExecutionEnvironment"),getWindowPath=_dereq_("../helpers/getWindowPath"),HashLocation={setup:function(onChange){invariant(ExecutionEnvironment.canUseDOM,"You cannot use HashLocation in an environment with no DOM"),_onChange=onChange,""===window.location.hash&&window.location.replace(getWindowPath()+"#/"),window.addEventListener?window.addEventListener("hashchange",_onChange,!1):window.attachEvent("onhashchange",_onChange)},teardown:function(){window.removeEventListener?window.removeEventListener("hashchange",_onChange,!1):window.detachEvent("onhashchange",_onChange)},push:function(path){window.location.hash=path},replace:function(path){window.location.replace(getWindowPath()+"#"+path)},pop:function(){window.history.back()},getCurrentPath:function(){return window.location.hash.substr(1)},toString:function(){return"<HashLocation>"}};module.exports=HashLocation},{"../helpers/getWindowPath":20,"react/lib/ExecutionEnvironment":52,"react/lib/invariant":55}],31:[function(_dereq_,module){var _onChange,invariant=_dereq_("react/lib/invariant"),ExecutionEnvironment=_dereq_("react/lib/ExecutionEnvironment"),getWindowPath=_dereq_("../helpers/getWindowPath"),HistoryLocation={setup:function(onChange){invariant(ExecutionEnvironment.canUseDOM,"You cannot use HistoryLocation in an environment with no DOM"),_onChange=onChange,window.addEventListener?window.addEventListener("popstate",_onChange,!1):window.attachEvent("popstate",_onChange)},teardown:function(){window.removeEventListener?window.removeEventListener("popstate",_onChange,!1):window.detachEvent("popstate",_onChange)},push:function(path){window.history.pushState({path:path},"",path),_onChange()},replace:function(path){window.history.replaceState({path:path},"",path),_onChange()},pop:function(){window.history.back()},getCurrentPath:getWindowPath,toString:function(){return"<HistoryLocation>"}};module.exports=HistoryLocation},{"../helpers/getWindowPath":20,"react/lib/ExecutionEnvironment":52,"react/lib/invariant":55}],32:[function(_dereq_,module){var invariant=_dereq_("react/lib/invariant"),ExecutionEnvironment=_dereq_("react/lib/ExecutionEnvironment"),getWindowPath=_dereq_("../helpers/getWindowPath"),RefreshLocation={setup:function(){invariant(ExecutionEnvironment.canUseDOM,"You cannot use RefreshLocation in an environment with no DOM")},push:function(path){window.location=path},replace:function(path){window.location.replace(path)},pop:function(){window.history.back()},getCurrentPath:getWindowPath,toString:function(){return"<RefreshLocation>"}};module.exports=RefreshLocation},{"../helpers/getWindowPath":20,"react/lib/ExecutionEnvironment":52,"react/lib/invariant":55}],33:[function(_dereq_,module){var ActiveStore=_dereq_("../stores/ActiveStore"),ActiveState={statics:{isActive:ActiveStore.isActive},componentWillMount:function(){ActiveStore.addChangeListener(this.handleActiveStateChange)},componentDidMount:function(){this.updateActiveState&&this.updateActiveState()},componentWillUnmount:function(){ActiveStore.removeChangeListener(this.handleActiveStateChange)},handleActiveStateChange:function(){this.isMounted()&&this.updateActiveState&&this.updateActiveState()}};module.exports=ActiveState},{"../stores/ActiveStore":35}],34:[function(_dereq_,module){var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,resolveAsyncState=_dereq_("../helpers/resolveAsyncState"),AsyncState={propTypes:{initialAsyncState:React.PropTypes.object},getInitialState:function(){return this.props.initialAsyncState||null},updateAsyncState:function(state){this.isMounted()&&this.setState(state)},componentDidMount:function(){this.props.initialAsyncState||"function"!=typeof this.constructor.getInitialAsyncState||resolveAsyncState(this.constructor.getInitialAsyncState(this.props.params,this.props.query,this.updateAsyncState),this.updateAsyncState)}};module.exports=AsyncState},{"../helpers/resolveAsyncState":26}],35:[function(_dereq_,module){function notifyChange(){_events.emit(CHANGE_EVENT)}function routeIsActive(routeName){return _activeRoutes.some(function(route){return route.props.name===routeName})}function paramsAreActive(params){for(var property in params)if(_activeParams[property]!==String(params[property]))return!1;return!0}function queryIsActive(query){for(var property in query)if(_activeQuery[property]!==String(query[property]))return!1;return!0}var EventEmitter=_dereq_("events").EventEmitter,CHANGE_EVENT="change",_events=new EventEmitter;_events.setMaxListeners(0);var _activeRoutes=[],_activeParams={},_activeQuery={},ActiveStore={addChangeListener:function(listener){_events.on(CHANGE_EVENT,listener)},removeChangeListener:function(listener){_events.removeListener(CHANGE_EVENT,listener)},updateState:function(state){state=state||{},_activeRoutes=state.activeRoutes||[],_activeParams=state.activeParams||{},_activeQuery=state.activeQuery||{},notifyChange()},isActive:function(routeName,params,query){var isActive=routeIsActive(routeName)&¶msAreActive(params);return query?isActive&&queryIsActive(query):isActive}};module.exports=ActiveStore},{events:38}],36:[function(_dereq_,module){function notifyChange(){_events.emit(CHANGE_EVENT)}var _location,warning=_dereq_("react/lib/warning"),EventEmitter=_dereq_("events").EventEmitter,supportsHistory=_dereq_("../helpers/supportsHistory"),HistoryLocation=_dereq_("../locations/HistoryLocation"),RefreshLocation=_dereq_("../locations/RefreshLocation"),CHANGE_EVENT="change",_events=new EventEmitter,PathStore={addChangeListener:function(listener){_events.on(CHANGE_EVENT,listener)},removeChangeListener:function(listener){_events.removeListener(CHANGE_EVENT,listener),0===EventEmitter.listenerCount(_events,CHANGE_EVENT)&&PathStore.teardown()},setup:function(location){location!==HistoryLocation||supportsHistory()||(location=RefreshLocation),null==_location?(_location=location,_location&&"function"==typeof _location.setup&&_location.setup(notifyChange)):warning(_location===location,"Cannot use location %s, already using %s",location,_location)},teardown:function(){_location&&"function"==typeof _location.teardown&&_location.teardown(),_location=null},getLocation:function(){return _location},push:function(path){_location.getCurrentPath()!==path&&_location.push(path)},replace:function(path){_location.getCurrentPath()!==path&&_location.replace(path)},pop:function(){_location.pop()},getCurrentPath:function(){return _location.getCurrentPath()}};module.exports=PathStore},{"../helpers/supportsHistory":27,"../locations/HistoryLocation":31,"../locations/RefreshLocation":32,events:38,"react/lib/warning":61}],37:[function(_dereq_,module){var React="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,invariant=_dereq_("react/lib/invariant"),Path=(_dereq_("react/lib/warning"),_dereq_("../helpers/Path")),_namedRoutes={},RouteStore={unregisterAllRoutes:function(){_namedRoutes={}},unregisterRoute:function(route){var props=route.props;props.name&&delete _namedRoutes[props.name],React.Children.forEach(props.children,RouteStore.unregisterRoute)},registerRoute:function(route,parentRoute){var props=route.props;invariant(React.isValidClass(props.handler),'The handler for the "%s" route must be a valid React class',props.name||props.path);var isDefault=!(props.path||props.name||props.children);if(props.path=props.path||props.name?Path.normalize(props.path||props.name):parentRoute&&parentRoute.props.path?parentRoute.props.path:"/",props.paramNames=Path.extractParamNames(props.path),parentRoute&&Array.isArray(parentRoute.props.paramNames)&&parentRoute.props.paramNames.forEach(function(paramName){invariant(-1!==props.paramNames.indexOf(paramName),'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"',props.path,paramName,parentRoute.props.path)}),props.name){var existingRoute=_namedRoutes[props.name];invariant(!existingRoute||route===existingRoute,'You cannot use the name "%s" for more than one route',props.name),_namedRoutes[props.name]=route}return parentRoute&&isDefault?(invariant(null==parentRoute.props.defaultRoute,"You may not have more than one <DefaultRoute> per <Route>"),parentRoute.props.defaultRoute=route,null):(props.children=RouteStore.registerChildren(props.children,route),route)},registerChildren:function(children,parentRoute){var routes=[];return React.Children.forEach(children,function(child){(child=RouteStore.registerRoute(child,parentRoute))&&routes.push(child)}),routes},getRouteByName:function(routeName){return _namedRoutes[routeName]||null}};module.exports=RouteStore},{"../helpers/Path":16,"react/lib/invariant":55,"react/lib/warning":61}],38:[function(_dereq_,module){function EventEmitter(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function isFunction(arg){return"function"==typeof arg}function isNumber(arg){return"number"==typeof arg}function isObject(arg){return"object"==typeof arg&&null!==arg}function isUndefined(arg){return void 0===arg}module.exports=EventEmitter,EventEmitter.EventEmitter=EventEmitter,EventEmitter.prototype._events=void 0,EventEmitter.prototype._maxListeners=void 0,EventEmitter.defaultMaxListeners=10,EventEmitter.prototype.setMaxListeners=function(n){if(!isNumber(n)||0>n||isNaN(n))throw TypeError("n must be a positive number");return this._maxListeners=n,this},EventEmitter.prototype.emit=function(type){var er,handler,len,args,i,listeners;if(this._events||(this._events={}),"error"===type&&(!this._events.error||isObject(this._events.error)&&!this._events.error.length))throw er=arguments[1],er instanceof Error?er:TypeError('Uncaught, unspecified "error" event.');if(handler=this._events[type],isUndefined(handler))return!1;if(isFunction(handler))switch(arguments.length){case 1:handler.call(this);break;case 2:handler.call(this,arguments[1]);break;case 3:handler.call(this,arguments[1],arguments[2]);break;default:for(len=arguments.length,args=new Array(len-1),i=1;len>i;i++)args[i-1]=arguments[i];handler.apply(this,args)}else if(isObject(handler)){for(len=arguments.length,args=new Array(len-1),i=1;len>i;i++)args[i-1]=arguments[i];for(listeners=handler.slice(),len=listeners.length,i=0;len>i;i++)listeners[i].apply(this,args)}return!0},EventEmitter.prototype.addListener=function(type,listener){var m;if(!isFunction(listener))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",type,isFunction(listener.listener)?listener.listener:listener),this._events[type]?isObject(this._events[type])?this._events[type].push(listener):this._events[type]=[this._events[type],listener]:this._events[type]=listener,isObject(this._events[type])&&!this._events[type].warned){var m;m=isUndefined(this._maxListeners)?EventEmitter.defaultMaxListeners:this._maxListeners,m&&m>0&&this._events[type].length>m&&(this._events[type].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[type].length),"function"==typeof console.trace&&console.trace())}return this},EventEmitter.prototype.on=EventEmitter.prototype.addListener,EventEmitter.prototype.once=function(type,listener){function g(){this.removeListener(type,g),fired||(fired=!0,listener.apply(this,arguments))}if(!isFunction(listener))throw TypeError("listener must be a function");var fired=!1;return g.listener=listener,this.on(type,g),this},EventEmitter.prototype.removeListener=function(type,listener){var list,position,length,i;if(!isFunction(listener))throw TypeError("listener must be a function");if(!this._events||!this._events[type])return this;if(list=this._events[type],length=list.length,position=-1,list===listener||isFunction(list.listener)&&list.listener===listener)delete this._events[type],this._events.removeListener&&this.emit("removeListener",type,listener); | ||
else if(isObject(list)){for(i=length;i-->0;)if(list[i]===listener||list[i].listener&&list[i].listener===listener){position=i;break}if(0>position)return this;1===list.length?(list.length=0,delete this._events[type]):list.splice(position,1),this._events.removeListener&&this.emit("removeListener",type,listener)}return this},EventEmitter.prototype.removeAllListeners=function(type){var key,listeners;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[type]&&delete this._events[type],this;if(0===arguments.length){for(key in this._events)"removeListener"!==key&&this.removeAllListeners(key);return this.removeAllListeners("removeListener"),this._events={},this}if(listeners=this._events[type],isFunction(listeners))this.removeListener(type,listeners);else for(;listeners.length;)this.removeListener(type,listeners[listeners.length-1]);return delete this._events[type],this},EventEmitter.prototype.listeners=function(type){var ret;return ret=this._events&&this._events[type]?isFunction(this._events[type])?[this._events[type]]:this._events[type].slice():[]},EventEmitter.listenerCount=function(emitter,type){var ret;return ret=emitter._events&&emitter._events[type]?isFunction(emitter._events[type])?1:emitter._events[type].length:0}},{}],39:[function(_dereq_,module){"use strict";function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop)}module.exports=function(qs,sep,eq,options){sep=sep||"&",eq=eq||"=";var obj={};if("string"!=typeof qs||0===qs.length)return obj;var regexp=/\+/g;qs=qs.split(sep);var maxKeys=1e3;options&&"number"==typeof options.maxKeys&&(maxKeys=options.maxKeys);var len=qs.length;maxKeys>0&&len>maxKeys&&(len=maxKeys);for(var i=0;len>i;++i){var kstr,vstr,k,v,x=qs[i].replace(regexp,"%20"),idx=x.indexOf(eq);idx>=0?(kstr=x.substr(0,idx),vstr=x.substr(idx+1)):(kstr=x,vstr=""),k=decodeURIComponent(kstr),v=decodeURIComponent(vstr),hasOwnProperty(obj,k)?isArray(obj[k])?obj[k].push(v):obj[k]=[obj[k],v]:obj[k]=v}return obj};var isArray=Array.isArray||function(xs){return"[object Array]"===Object.prototype.toString.call(xs)}},{}],40:[function(_dereq_,module){"use strict";function map(xs,f){if(xs.map)return xs.map(f);for(var res=[],i=0;i<xs.length;i++)res.push(f(xs[i],i));return res}var stringifyPrimitive=function(v){switch(typeof v){case"string":return v;case"boolean":return v?"true":"false";case"number":return isFinite(v)?v:"";default:return""}};module.exports=function(obj,sep,eq,name){return sep=sep||"&",eq=eq||"=",null===obj&&(obj=void 0),"object"==typeof obj?map(objectKeys(obj),function(k){var ks=encodeURIComponent(stringifyPrimitive(k))+eq;return isArray(obj[k])?map(obj[k],function(v){return ks+encodeURIComponent(stringifyPrimitive(v))}).join(sep):ks+encodeURIComponent(stringifyPrimitive(obj[k]))}).join(sep):name?encodeURIComponent(stringifyPrimitive(name))+eq+encodeURIComponent(stringifyPrimitive(obj)):""};var isArray=Array.isArray||function(xs){return"[object Array]"===Object.prototype.toString.call(xs)},objectKeys=Object.keys||function(obj){var res=[];for(var key in obj)Object.prototype.hasOwnProperty.call(obj,key)&&res.push(key);return res}},{}],41:[function(_dereq_,module,exports){"use strict";exports.decode=exports.parse=_dereq_("./decode"),exports.encode=exports.stringify=_dereq_("./encode")},{"./decode":39,"./encode":40}],42:[function(_dereq_,module,exports){"use strict";var Promise=_dereq_("./promise/promise").Promise,polyfill=_dereq_("./promise/polyfill").polyfill;exports.Promise=Promise,exports.polyfill=polyfill},{"./promise/polyfill":46,"./promise/promise":47}],43:[function(_dereq_,module,exports){"use strict";function all(promises){var Promise=this;if(!isArray(promises))throw new TypeError("You must pass an array to all.");return new Promise(function(resolve,reject){function resolver(index){return function(value){resolveAll(index,value)}}function resolveAll(index,value){results[index]=value,0===--remaining&&resolve(results)}var promise,results=[],remaining=promises.length;0===remaining&&resolve([]);for(var i=0;i<promises.length;i++)promise=promises[i],promise&&isFunction(promise.then)?promise.then(resolver(i),reject):resolveAll(i,promise)})}var isArray=_dereq_("./utils").isArray,isFunction=_dereq_("./utils").isFunction;exports.all=all},{"./utils":51}],44:[function(_dereq_,module,exports){"use strict";function useNextTick(){return function(){process.nextTick(flush)}}function useMutationObserver(){var iterations=0,observer=new BrowserMutationObserver(flush),node=document.createTextNode("");return observer.observe(node,{characterData:!0}),function(){node.data=iterations=++iterations%2}}function useSetTimeout(){return function(){local.setTimeout(flush,1)}}function flush(){for(var i=0;i<queue.length;i++){var tuple=queue[i],callback=tuple[0],arg=tuple[1];callback(arg)}queue=[]}function asap(callback,arg){var length=queue.push([callback,arg]);1===length&&scheduleFlush()}var scheduleFlush,browserGlobal="undefined"!=typeof window?window:{},BrowserMutationObserver=browserGlobal.MutationObserver||browserGlobal.WebKitMutationObserver,local="undefined"!=typeof global?global:void 0===this?window:this,queue=[];scheduleFlush="undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?useNextTick():BrowserMutationObserver?useMutationObserver():useSetTimeout(),exports.asap=asap},{}],45:[function(_dereq_,module,exports){"use strict";function configure(name,value){return 2!==arguments.length?config[name]:void(config[name]=value)}var config={instrument:!1};exports.config=config,exports.configure=configure},{}],46:[function(_dereq_,module,exports){"use strict";function polyfill(){var local;local="undefined"!=typeof global?global:"undefined"!=typeof window&&window.document?window:self;var es6PromiseSupport="Promise"in local&&"resolve"in local.Promise&&"reject"in local.Promise&&"all"in local.Promise&&"race"in local.Promise&&function(){var resolve;return new local.Promise(function(r){resolve=r}),isFunction(resolve)}();es6PromiseSupport||(local.Promise=RSVPPromise)}var RSVPPromise=_dereq_("./promise").Promise,isFunction=_dereq_("./utils").isFunction;exports.polyfill=polyfill},{"./promise":47,"./utils":51}],47:[function(_dereq_,module,exports){"use strict";function Promise(resolver){if(!isFunction(resolver))throw new TypeError("You must pass a resolver function as the first argument to the promise constructor");if(!(this instanceof Promise))throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");this._subscribers=[],invokeResolver(resolver,this)}function invokeResolver(resolver,promise){function resolvePromise(value){resolve(promise,value)}function rejectPromise(reason){reject(promise,reason)}try{resolver(resolvePromise,rejectPromise)}catch(e){rejectPromise(e)}}function invokeCallback(settled,promise,callback,detail){var value,error,succeeded,failed,hasCallback=isFunction(callback);if(hasCallback)try{value=callback(detail),succeeded=!0}catch(e){failed=!0,error=e}else value=detail,succeeded=!0;handleThenable(promise,value)||(hasCallback&&succeeded?resolve(promise,value):failed?reject(promise,error):settled===FULFILLED?resolve(promise,value):settled===REJECTED&&reject(promise,value))}function subscribe(parent,child,onFulfillment,onRejection){var subscribers=parent._subscribers,length=subscribers.length;subscribers[length]=child,subscribers[length+FULFILLED]=onFulfillment,subscribers[length+REJECTED]=onRejection}function publish(promise,settled){for(var child,callback,subscribers=promise._subscribers,detail=promise._detail,i=0;i<subscribers.length;i+=3)child=subscribers[i],callback=subscribers[i+settled],invokeCallback(settled,child,callback,detail);promise._subscribers=null}function handleThenable(promise,value){var resolved,then=null;try{if(promise===value)throw new TypeError("A promises callback cannot return that same promise.");if(objectOrFunction(value)&&(then=value.then,isFunction(then)))return then.call(value,function(val){return resolved?!0:(resolved=!0,void(value!==val?resolve(promise,val):fulfill(promise,val)))},function(val){return resolved?!0:(resolved=!0,void reject(promise,val))}),!0}catch(error){return resolved?!0:(reject(promise,error),!0)}return!1}function resolve(promise,value){promise===value?fulfill(promise,value):handleThenable(promise,value)||fulfill(promise,value)}function fulfill(promise,value){promise._state===PENDING&&(promise._state=SEALED,promise._detail=value,config.async(publishFulfillment,promise))}function reject(promise,reason){promise._state===PENDING&&(promise._state=SEALED,promise._detail=reason,config.async(publishRejection,promise))}function publishFulfillment(promise){publish(promise,promise._state=FULFILLED)}function publishRejection(promise){publish(promise,promise._state=REJECTED)}var config=_dereq_("./config").config,objectOrFunction=(_dereq_("./config").configure,_dereq_("./utils").objectOrFunction),isFunction=_dereq_("./utils").isFunction,all=(_dereq_("./utils").now,_dereq_("./all").all),race=_dereq_("./race").race,staticResolve=_dereq_("./resolve").resolve,staticReject=_dereq_("./reject").reject,asap=_dereq_("./asap").asap;config.async=asap;var PENDING=void 0,SEALED=0,FULFILLED=1,REJECTED=2;Promise.prototype={constructor:Promise,_state:void 0,_detail:void 0,_subscribers:void 0,then:function(onFulfillment,onRejection){var promise=this,thenPromise=new this.constructor(function(){});if(this._state){var callbacks=arguments;config.async(function(){invokeCallback(promise._state,thenPromise,callbacks[promise._state-1],promise._detail)})}else subscribe(this,thenPromise,onFulfillment,onRejection);return thenPromise},"catch":function(onRejection){return this.then(null,onRejection)}},Promise.all=all,Promise.race=race,Promise.resolve=staticResolve,Promise.reject=staticReject,exports.Promise=Promise},{"./all":43,"./asap":44,"./config":45,"./race":48,"./reject":49,"./resolve":50,"./utils":51}],48:[function(_dereq_,module,exports){"use strict";function race(promises){var Promise=this;if(!isArray(promises))throw new TypeError("You must pass an array to race.");return new Promise(function(resolve,reject){for(var promise,i=0;i<promises.length;i++)promise=promises[i],promise&&"function"==typeof promise.then?promise.then(resolve,reject):resolve(promise)})}var isArray=_dereq_("./utils").isArray;exports.race=race},{"./utils":51}],49:[function(_dereq_,module,exports){"use strict";function reject(reason){var Promise=this;return new Promise(function(resolve,reject){reject(reason)})}exports.reject=reject},{}],50:[function(_dereq_,module,exports){"use strict";function resolve(value){if(value&&"object"==typeof value&&value.constructor===this)return value;var Promise=this;return new Promise(function(resolve){resolve(value)})}exports.resolve=resolve},{}],51:[function(_dereq_,module,exports){"use strict";function objectOrFunction(x){return isFunction(x)||"object"==typeof x&&null!==x}function isFunction(x){return"function"==typeof x}function isArray(x){return"[object Array]"===Object.prototype.toString.call(x)}var now=Date.now||function(){return(new Date).getTime()};exports.objectOrFunction=objectOrFunction,exports.isFunction=isFunction,exports.isArray=isArray,exports.now=now},{}],52:[function(_dereq_,module){"use strict";var canUseDOM=!("undefined"==typeof window||!window.document||!window.document.createElement),ExecutionEnvironment={canUseDOM:canUseDOM,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:canUseDOM&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:canUseDOM&&!!window.screen,isInWorker:!canUseDOM};module.exports=ExecutionEnvironment},{}],53:[function(_dereq_,module){function copyProperties(obj,a,b,c,d,e,f){obj=obj||{};for(var v,args=[a,b,c,d,e],ii=0;args[ii];){v=args[ii++];for(var k in v)obj[k]=v[k];v.hasOwnProperty&&v.hasOwnProperty("toString")&&"undefined"!=typeof v.toString&&obj.toString!==v.toString&&(obj.toString=v.toString)}return obj}module.exports=copyProperties},{}],54:[function(_dereq_,module){function makeEmptyFunction(arg){return function(){return arg}}function emptyFunction(){}var copyProperties=_dereq_("./copyProperties");copyProperties(emptyFunction,{thatReturns:makeEmptyFunction,thatReturnsFalse:makeEmptyFunction(!1),thatReturnsTrue:makeEmptyFunction(!0),thatReturnsNull:makeEmptyFunction(null),thatReturnsThis:function(){return this},thatReturnsArgument:function(arg){return arg}}),module.exports=emptyFunction},{"./copyProperties":53}],55:[function(_dereq_,module){"use strict";var invariant=function(condition,format,a,b,c,d,e,f){if(!condition){var error;if(void 0===format)error=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var args=[a,b,c,d,e,f],argIndex=0;error=new Error("Invariant Violation: "+format.replace(/%s/g,function(){return args[argIndex++]}))}throw error.framesToPop=1,error}};module.exports=invariant},{}],56:[function(_dereq_,module){"use strict";var invariant=_dereq_("./invariant"),keyMirror=function(obj){var key,ret={};invariant(obj instanceof Object&&!Array.isArray(obj));for(key in obj)obj.hasOwnProperty(key)&&(ret[key]=key);return ret};module.exports=keyMirror},{"./invariant":55}],57:[function(_dereq_,module){"use strict";var mergeInto=_dereq_("./mergeInto"),merge=function(one,two){var result={};return mergeInto(result,one),mergeInto(result,two),result};module.exports=merge},{"./mergeInto":59}],58:[function(_dereq_,module){"use strict";var invariant=_dereq_("./invariant"),keyMirror=_dereq_("./keyMirror"),MAX_MERGE_DEPTH=36,isTerminal=function(o){return"object"!=typeof o||null===o},mergeHelpers={MAX_MERGE_DEPTH:MAX_MERGE_DEPTH,isTerminal:isTerminal,normalizeMergeArg:function(arg){return void 0===arg||null===arg?{}:arg},checkMergeArrayArgs:function(one,two){invariant(Array.isArray(one)&&Array.isArray(two))},checkMergeObjectArgs:function(one,two){mergeHelpers.checkMergeObjectArg(one),mergeHelpers.checkMergeObjectArg(two)},checkMergeObjectArg:function(arg){invariant(!isTerminal(arg)&&!Array.isArray(arg))},checkMergeIntoObjectArg:function(arg){invariant(!(isTerminal(arg)&&"function"!=typeof arg||Array.isArray(arg)))},checkMergeLevel:function(level){invariant(MAX_MERGE_DEPTH>level)},checkArrayStrategy:function(strategy){invariant(void 0===strategy||strategy in mergeHelpers.ArrayStrategies)},ArrayStrategies:keyMirror({Clobber:!0,IndexByIndex:!0})};module.exports=mergeHelpers},{"./invariant":55,"./keyMirror":56}],59:[function(_dereq_,module){"use strict";function mergeInto(one,two){if(checkMergeIntoObjectArg(one),null!=two){checkMergeObjectArg(two);for(var key in two)two.hasOwnProperty(key)&&(one[key]=two[key])}}var mergeHelpers=_dereq_("./mergeHelpers"),checkMergeObjectArg=mergeHelpers.checkMergeObjectArg,checkMergeIntoObjectArg=mergeHelpers.checkMergeIntoObjectArg;module.exports=mergeInto},{"./mergeHelpers":58}],60:[function(_dereq_,module){"use strict";var mixInto=function(constructor,methodBag){var methodName;for(methodName in methodBag)methodBag.hasOwnProperty(methodName)&&(constructor.prototype[methodName]=methodBag[methodName])};module.exports=mixInto},{}],61:[function(_dereq_,module){"use strict";var emptyFunction=_dereq_("./emptyFunction"),warning=emptyFunction;module.exports=warning},{"./emptyFunction":54}],62:[function(_dereq_,module){module.exports=_dereq_("./modules/helpers/replaceWith")},{"./modules/helpers/replaceWith":25}],63:[function(_dereq_,module){module.exports=_dereq_("./modules/helpers/transitionTo")},{"./modules/helpers/transitionTo":28}]},{},[9])(9)}); |
@@ -30,2 +30,9 @@ API: `Link` (component) | ||
### `onClick` | ||
A custom handler for the click event. Works just like a handler on an `<a>` | ||
tag - calling `e.preventDefault()` or returning `false` will prevent the | ||
transition from firing, while `e.stopPropagation()` will prevent the event | ||
from bubbling. | ||
### *others* | ||
@@ -32,0 +39,0 @@ |
@@ -13,7 +13,7 @@ API: `Routes` (component) | ||
One of `"hash"` or `"history"`, defaults to `"hash"`. | ||
One of `"hash"`, `"history"` or a user defined location implementation, | ||
defaults to `"hash"`. | ||
Configures what type of url you want. `"hash"` includes `#/` in the url and | ||
works without a server, if you use `history` your server will need to | ||
support it. | ||
`"hash"` includes `#/` in the url and works without a server, if you use | ||
`history` your server will need to support it. | ||
@@ -25,2 +25,4 @@ For browsers that don't support the HTML5 history API the router will | ||
See also: [user supplied locations][Location]. | ||
### `preserveScrollPosition` | ||
@@ -32,2 +34,22 @@ | ||
### `onAbortedTransition` | ||
A function called when any transition is aborted. | ||
### `onActiveStateChange` | ||
A function called when the active routes change. | ||
#### signature | ||
`function(nextState)` | ||
### `onTransitionError` | ||
A function called when a transition has an error. | ||
#### signature | ||
`function(error)` | ||
Example | ||
@@ -37,4 +59,8 @@ ------- | ||
```jsx | ||
function onError(error) { | ||
handleError(error); | ||
} | ||
var routes = ( | ||
<Routes location="history"> | ||
<Routes location="history" onTransitionError={onError}> | ||
<Route handler={App}/> | ||
@@ -46,1 +72,3 @@ </Routes> | ||
[Location]:../misc/Location.md | ||
@@ -7,2 +7,3 @@ React Router API | ||
- Components | ||
- [`DefaultRoute`](/docs/api/components/DefaultRoute.md) | ||
- [`Link`](/docs/api/components/Link.md) | ||
@@ -9,0 +10,0 @@ - [`Redirect`](/docs/api/components/Redirect.md) |
@@ -20,3 +20,3 @@ API: `Router` | ||
Programatically transition to a new route. | ||
Programmatically transition to a new route. | ||
@@ -33,3 +33,3 @@ #### Examples | ||
Programatically replace current route with a new route. Does not add an | ||
Programmatically replace current route with a new route. Does not add an | ||
entry into the browser history. | ||
@@ -47,3 +47,3 @@ | ||
Programatically go back to the last route and remove the most recent | ||
Programmatically go back to the last route and remove the most recent | ||
entry from the browser history. | ||
@@ -69,2 +69,1 @@ | ||
``` | ||
@@ -1,55 +0,128 @@ | ||
Guide: Overview | ||
=============== | ||
React Router Guide | ||
================== | ||
``` | ||
var Routes = require('react-router/Routes'); | ||
var Route = require('react-router/Route'); | ||
Nesting UI is at the core of React Router. Think about any user | ||
interface you're accustomed to, there is likely some shared UI as you | ||
navigate around the application. | ||
React.renderComponent(( | ||
<Routes> | ||
<Route handler={App}> | ||
<Route name="about" handler={About}/> | ||
<Route name="users" handler={Users}> | ||
<Route name="user" path="/user/:userId" handler={User}/> | ||
</Route> | ||
</Route> | ||
</Routes> | ||
), document.body); | ||
Let's imagine a little app with a dashboard, inbox, and calendar. | ||
``` | ||
+---------------------------------------------------------+ | ||
| +---------+ +-------+ +--------+ | | ||
| |Dashboard| | Inbox | |Calendar| Logged in as Joe | | ||
| +---------+ +-------+ +--------+ | | ||
+---------------------------------------------------------+ | ||
| | | ||
| Dashboard | | ||
| | | ||
| | | ||
| +---------------------+ +----------------------+ | | ||
| | | | | | | ||
| | + + | +---------> | | | ||
| | | | | | | | | ||
| | | + | | +-------------> | | | ||
| | | | + | | | | | | ||
| | | | | | | | | | | ||
| +-+---+----+-----+----+ +----------------------+ | | ||
| | | ||
+---------------------------------------------------------+ | ||
``` | ||
Or if JSX isn't your jam: | ||
We have three main screens here with the top section of UI being | ||
persistent. | ||
Without React Router | ||
-------------------- | ||
Without this router, you'd share that UI by repeating render code across | ||
your views, probably with a `<Header/>` component: | ||
```js | ||
React.renderComponent(( | ||
Routes({}, | ||
Route({handler: App}, | ||
Route({name: "about", handler: About}), | ||
Route({name: "users", handler: Users}, | ||
Route({name: "user", path: "/user/:userId", handler: User}) | ||
) | ||
) | ||
) | ||
), document.body); | ||
var Header = React.createClass({ | ||
render: function() { | ||
return ( | ||
<header> | ||
<ul> | ||
<li><a href="/">Dashboard</a></li> | ||
<li><a href="/inbox">Inbox</a></li> | ||
<li><a href="/calendar">Calendar</a></li> | ||
</ul> | ||
Logged in as Joe | ||
</header> | ||
); | ||
} | ||
}); | ||
var DashboardRoute = React.createClass({ | ||
render: function() { | ||
return ( | ||
<div> | ||
<Header/> | ||
<Dashboard/> | ||
</div> | ||
); | ||
} | ||
}); | ||
var InboxRoute = React.createClass({ | ||
render: function() { | ||
return ( | ||
<div> | ||
<Header/> | ||
<Inbox/> | ||
</div> | ||
); | ||
} | ||
}); | ||
var CalendarRoute = React.createClass({ | ||
render: function() { | ||
return ( | ||
<div> | ||
<Header/> | ||
<Calendar/> | ||
</div> | ||
); | ||
} | ||
}); | ||
// Not React Router API | ||
otherRouter.route('/', function() { | ||
React.renderComponent(<DashboardRoute/>, document.body); | ||
}); | ||
otherRouter.route('/inbox', function() { | ||
React.renderComponent(<InboxRoute/>, document.body); | ||
}); | ||
otherRouter.route('/calendar', function() { | ||
React.renderComponent(<CalendarRoute/>, document.body); | ||
}); | ||
``` | ||
- URLs will be matched to the deepest route, and then all the routes up | ||
the hierarchy are activated and their "handlers" (normal React | ||
components) will be rendered. | ||
The three main view's render methods are nearly identical. While one | ||
level of shared UI like this is pretty easy to handle, getting deeper | ||
and deeper adds more complexity, along with lots of `switch` branching, | ||
etc. | ||
- Paths are assumed from names unless specified. | ||
React Router embraces this common pattern among user interfaces by | ||
nesting the views for you. | ||
- Each handler will receive a `params` property containing the matched | ||
parameters form the url, like `:userId`. | ||
With React Router | ||
----------------- | ||
- Handlers also receive a `query` prop equal to a dictionary of the | ||
current query params. | ||
Here's how it works: | ||
- Parent routes will receive a `activeRouteHandler` property. Its a function that | ||
will render the active child route handler. | ||
1. You declare your view hierarchy with nested `<Route/>`s and provide | ||
them with a React component to handle the route when its active. | ||
Here's the rest of the application: | ||
2. React Router will match the deepest route against the URL, and then | ||
activate the entire tree of routes on that branch, nesting all the | ||
UI. | ||
3. You access the active route handler in the props of the parent route. | ||
```js | ||
var Link = require('react-router/Link'); | ||
var App = React.createClass({ | ||
@@ -59,7 +132,12 @@ render: function() { | ||
<div> | ||
<ul> | ||
<li><Link to="about">About</Link></li> | ||
<li><Link to="users">Users</Link></li> | ||
<li><Link to="user" userId="123">User 123</Link></li> | ||
</ul> | ||
<header> | ||
<ul> | ||
<li><Link to="app">Dashboard</Link></li> | ||
<li><Link to="inbox">Inbox</Link></li> | ||
<li><Link to="calendar">Calendar</Link></li> | ||
</ul> | ||
Logged in as Joe | ||
</header> | ||
{/* this is the important part */} | ||
<this.props.activeRouteHandler/> | ||
@@ -71,13 +149,77 @@ </div> | ||
var About = React.createClass({ | ||
render: function() { | ||
return <h2>About</h2>; | ||
} | ||
}); | ||
var routes = ( | ||
<Routes location="history"> | ||
<Route name="app" path="/" handler={App}> | ||
<Route name="inbox" path="/inbox" handler={Inbox}/> | ||
<Route name="calendar" path="/calendar" handler={Calendar}/> | ||
<DefaultRoute handler={Dashboard}/> | ||
</Route> | ||
</Routes> | ||
); | ||
var Users = React.createClass({ | ||
React.renderComponent(routes, document.body); | ||
``` | ||
When the user lands at `/inbox`, the route named `inbox` gets matched so | ||
its parent route will render the `App` component, and since `inbox` is | ||
active, you get `Inbox` as `this.props.activeRouteHandler`. This is | ||
nearly identical to `{{outlet}}` from Ember or `<div ng-view/>` from | ||
angular. | ||
When the user navigates to `/calendar`, the same thing happens except | ||
now `Calendar` is the `activeRouteHandler` in `App`'s render method. | ||
Finally, when the user navigates to the path `/`, `App` is active, and | ||
notices that it has a `DefaultRoute`, so it receives `Dashboard` as the | ||
`activeRouteHandler`. If a `DefaultRoute` is defined, it will be active | ||
when the parent's route is matched exactly. | ||
Note that we don't need the `<Header/>` component since we don't have to | ||
repeat it anymore. React Router shares that UI for us from one place. | ||
More Nesting | ||
------------ | ||
Nesting arbitarily deep UI is not a problem. Consider the `Inbox` | ||
screen: it has a master list of messages on the left, a detail view of | ||
the message on the right, and a toolbar over the top. The toolbar and | ||
list are persistent, meanwhile the message view changes as the user | ||
navigates through the messages. | ||
``` | ||
+---------------------------------------------------------------------+ | ||
| +---------+ +-------+ +--------+ | | ||
| |Dashboard| | Inbox | |Calendar| Logged in as Joe | | ||
| +---------+ +-------+ +--------+ | | ||
+---------------------------------------------------------------------+ | ||
| +---------+ +-------+ +--------------+ | | ||
| | Compose | | Reply | |Inbox Settings| | | ||
| +---------+ +-------+ +--------------+ | | ||
+-------------------+-------------------------------------------------+ | ||
| David Brown | | | ||
| Hey, we need to...| | | ||
| | | | ||
| 12:30pm | | | ||
+-------------------+ 32 Unread Messages | | ||
| Mary Sweeney | | | ||
| I followed up w...| 456 Total Messages | | ||
| | | | ||
| 12:10pm | 3 Draft Messages | | ||
+-------------------+ | | ||
| DeMarcus Jones | | | ||
| check this out ...| | | ||
| | | | ||
| 11:25am | | | ||
+-------------------+-------------------------------------------------+ | ||
``` | ||
Let's see how React Router handles this: | ||
```js | ||
var Inbox = React.createClass({ | ||
render: function() { | ||
return ( | ||
<div> | ||
<h2>Users</h2> | ||
<Toolbar/> | ||
<Messages/> | ||
<this.props.activeRouteHandler/> | ||
@@ -89,5 +231,55 @@ </div> | ||
var User = React.createClass({ | ||
var routes = ( | ||
<Routes location="history"> | ||
<Route path="/" handler={App}> | ||
<Route name="inbox" path="/inbox" handler={Inbox}> | ||
<Route name="message" path="/inbox/:messageId" handler={Message}/> | ||
<DefaultRoute handler={InboxStats}/> | ||
</Route> | ||
<Route name="calendar" path="/calendar" handler={Calendar}/> | ||
<DefaultRoute handler={Dashboard}/> | ||
</Route> | ||
</Routes> | ||
); | ||
``` | ||
- Inbox now has `this.props.activeRouteHandler` in its render method, | ||
exactly like its parent. | ||
- We added a child routes to `inbox`; messages or the stats page can now | ||
render into it. | ||
Nesting a new level of UI does not increase the complexity of your code. | ||
You simply nest some routes and render them with `activeRouteHandler`. | ||
**Note**: the paths are not inherited from parent to child. This gives | ||
you the flexibility to have any url you need. Were the paths to be | ||
inherited, you'd be forced to couple your urls to your route hierarchy. | ||
For example, we may want `/inbox` and `/messages/123` instead of `/inbox` | ||
and `/inbox/123`. We can just change the path on the `message` route and | ||
still get view nesting even though the urls are not nested. | ||
Dynamic Segments | ||
---------------- | ||
When we added the `message` route, we introduced a "dynamic segment" to | ||
the URL. These segements get parsed from the url and passed into your | ||
route handler on `this.props.params`. | ||
Remember our message route looks like this: | ||
```xml | ||
<Route name="message" path="/inbox/:messageId" handler={Message}/> | ||
``` | ||
Lets look at accessing the `messageId` in `Message`. | ||
```js | ||
var Message = React.createClass({ | ||
render: function() { | ||
return <div>{this.props.params.userId}</div> | ||
return ( | ||
<div>{this.props.params.messageId}</div> | ||
); | ||
} | ||
@@ -97,17 +289,26 @@ }); | ||
To better understand what is happening with `activeRouteHandler` perhaps an | ||
example without the router will help. Lets take the scenario where | ||
`/users/2` has been matched. Your render method, without this router, | ||
might look something like this: | ||
Assuming the user navigates to `/inbox/123`, `this.props.messageId` is | ||
going to be `'123'`. Check out the [AsyncState][AsyncState] mixin to see | ||
how you can turn this parameter into state on your component. Or for a | ||
more basic approach, make an ajax call in `componentDidMount` with the | ||
value. | ||
```js | ||
render: function() { | ||
var user = <User params={{userId: 2}}/>; | ||
var users = <Users activeRouteHandler={user}/>; | ||
return <App activeRouteHandler={users}/>; | ||
} | ||
``` | ||
Links | ||
----- | ||
Instead, the router manages this view hierarchy for you. | ||
The `<Link/>` component allows you to conveniently navigate users around | ||
the application with accessible anchor tags that don't break normal link | ||
functionality like control/command clicking to open in a new tab. Also, | ||
when the route a link references is active, you get the `active` css | ||
class to easily style your UI. | ||
API Documentation | ||
----------------- | ||
That's the gist of what this router is all about, but there's a lot more | ||
it has to offer. Check out the [API Docs][API] to learn about | ||
redirecting transitions, query parameters and more. | ||
[AsyncState]:../api/mixins/AsyncState.md | ||
[API]:../api/ | ||
exports.ActiveState = require('./ActiveState'); | ||
exports.AsyncState = require('./AsyncState'); | ||
exports.DefaultRoute = require('./DefaultRoute'); | ||
exports.Link = require('./Link'); | ||
@@ -4,0 +5,0 @@ exports.Redirect = require('./Redirect'); |
@@ -5,4 +5,13 @@ var React = require('react'); | ||
var transitionTo = require('../helpers/transitionTo'); | ||
var hasOwnProperty = require('../helpers/hasOwnProperty'); | ||
var makeHref = require('../helpers/makeHref'); | ||
var hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty); | ||
function isLeftClickEvent(event) { | ||
return event.button === 0; | ||
} | ||
function isModifiedEvent(event) { | ||
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); | ||
} | ||
/** | ||
@@ -15,2 +24,3 @@ * A map of <Link> component props that are reserved for use by the | ||
to: true, | ||
key: true, | ||
className: true, | ||
@@ -57,3 +67,4 @@ activeClassName: true, | ||
activeClassName: React.PropTypes.string.isRequired, | ||
query: React.PropTypes.object | ||
query: React.PropTypes.object, | ||
onClick: React.PropTypes.func | ||
}, | ||
@@ -115,8 +126,18 @@ | ||
handleClick: function (event) { | ||
if (isModifiedEvent(event) || !isLeftClick(event)) | ||
var allowTransition = true; | ||
var ret; | ||
if (this.props.onClick) | ||
ret = this.props.onClick(event); | ||
if (isModifiedEvent(event) || !isLeftClickEvent(event)) | ||
return; | ||
if (ret === false || event.defaultPrevented === true) | ||
allowTransition = false; | ||
event.preventDefault(); | ||
transitionTo(this.props.to, this.getParams(), this.props.query); | ||
if (allowTransition) | ||
transitionTo(this.props.to, this.getParams(), this.props.query); | ||
}, | ||
@@ -133,5 +154,4 @@ | ||
for (var propName in this.props) { | ||
if (hasOwn(this.props, propName) && hasOwn(props, propName) === false) { | ||
if (hasOwnProperty(this.props, propName) && hasOwnProperty(props, propName) === false) | ||
props[propName] = this.props[propName]; | ||
} | ||
} | ||
@@ -144,10 +164,2 @@ | ||
function isLeftClick(event) { | ||
return event.button === 0; | ||
} | ||
function isModifiedEvent(event) { | ||
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); | ||
} | ||
module.exports = Link; |
var React = require('react'); | ||
var Route = require('./Route'); | ||
function Redirect(props) { | ||
return Route({ | ||
path: props.from, | ||
handler: createRedirectClass(props.to) | ||
}); | ||
} | ||
function createRedirectClass(to) { | ||
function createRedirectHandler(to) { | ||
return React.createClass({ | ||
statics: { | ||
willTransitionTo: function(transition, params, query) { | ||
willTransitionTo: function (transition, params, query) { | ||
transition.redirect(to, params, query); | ||
@@ -19,3 +12,3 @@ } | ||
render: function() { | ||
render: function () { | ||
return null; | ||
@@ -26,2 +19,14 @@ } | ||
/** | ||
* A <Redirect> component is a special kind of <Route> that always | ||
* redirects when it matches. | ||
*/ | ||
function Redirect(props) { | ||
return Route({ | ||
name: props.name, | ||
path: props.from || props.path, | ||
handler: createRedirectHandler(props.to) | ||
}); | ||
} | ||
module.exports = Redirect; |
@@ -12,2 +12,4 @@ var React = require('react'); | ||
path: true, | ||
defaultRoute: true, | ||
paramNames: true, | ||
children: true // ReactChildren | ||
@@ -66,2 +68,3 @@ }; | ||
var Route = React.createClass({ | ||
displayName: 'Route', | ||
@@ -77,3 +80,10 @@ | ||
getDefaultProps: function() { | ||
propTypes: { | ||
preserveScrollPosition: React.PropTypes.bool.isRequired, | ||
handler: React.PropTypes.any.isRequired, | ||
path: React.PropTypes.string, | ||
name: React.PropTypes.string | ||
}, | ||
getDefaultProps: function () { | ||
return { | ||
@@ -84,13 +94,7 @@ preserveScrollPosition: false | ||
propTypes: { | ||
handler: React.PropTypes.any.isRequired, | ||
path: React.PropTypes.string, | ||
name: React.PropTypes.string, | ||
preserveScrollPosition: React.PropTypes.bool | ||
}, | ||
render: function () { | ||
throw new Error( | ||
'The <Route> component should not be rendered directly. You may be ' + | ||
'missing a <Routes> wrapper around your list of routes.'); | ||
'missing a <Routes> wrapper around your list of routes.' | ||
); | ||
} | ||
@@ -97,0 +101,0 @@ |
var React = require('react'); | ||
var warning = require('react/lib/warning'); | ||
var ExecutionEnvironment = require('react/lib/ExecutionEnvironment'); | ||
var mergeProperties = require('../helpers/mergeProperties'); | ||
var copyProperties = require('react/lib/copyProperties'); | ||
var Promise = require('es6-promise').Promise; | ||
var Route = require('../components/Route'); | ||
var goBack = require('../helpers/goBack'); | ||
var replaceWith = require('../helpers/replaceWith'); | ||
var transitionTo = require('../helpers/transitionTo'); | ||
var Route = require('../components/Route'); | ||
var Path = require('../helpers/Path'); | ||
var Redirect = require('../helpers/Redirect'); | ||
var Transition = require('../helpers/Transition'); | ||
var HashLocation = require('../locations/HashLocation'); | ||
var HistoryLocation = require('../locations/HistoryLocation'); | ||
var RefreshLocation = require('../locations/RefreshLocation'); | ||
var ActiveStore = require('../stores/ActiveStore'); | ||
var PathStore = require('../stores/PathStore'); | ||
var RouteStore = require('../stores/RouteStore'); | ||
var URLStore = require('../stores/URLStore'); | ||
var Promise = require('es6-promise').Promise; | ||
@@ -21,2 +24,42 @@ /** | ||
/** | ||
* A hash of { name, location } pairs of all locations. | ||
*/ | ||
var NAMED_LOCATIONS = { | ||
hash: HashLocation, | ||
history: HistoryLocation, | ||
refresh: RefreshLocation, | ||
disabled: RefreshLocation // TODO: Remove | ||
}; | ||
/** | ||
* The default handler for aborted transitions. Redirects replace | ||
* the current URL and all others roll it back. | ||
*/ | ||
function defaultAbortedTransitionHandler(transition) { | ||
var reason = transition.abortReason; | ||
if (reason instanceof Redirect) { | ||
replaceWith(reason.to, reason.params, reason.query); | ||
} else { | ||
goBack(); | ||
} | ||
} | ||
/** | ||
* The default handler for active state updates. | ||
*/ | ||
function defaultActiveStateChangeHandler(state) { | ||
ActiveStore.updateState(state); | ||
} | ||
/** | ||
* The default handler for errors that were thrown asynchronously | ||
* while transitioning. The default behavior is to re-throw the | ||
* error so that it isn't silently swallowed. | ||
*/ | ||
function defaultTransitionErrorHandler(error) { | ||
throw error; // This error probably originated in a transition hook. | ||
} | ||
/** | ||
* The <Routes> component configures the route hierarchy and renders the | ||
@@ -28,39 +71,25 @@ * route matching the current location when rendered into a document. | ||
var Routes = React.createClass({ | ||
displayName: 'Routes', | ||
statics: { | ||
propTypes: { | ||
onAbortedTransition: React.PropTypes.func.isRequired, | ||
onActiveStateChange: React.PropTypes.func.isRequired, | ||
onTransitionError: React.PropTypes.func.isRequired, | ||
preserveScrollPosition: React.PropTypes.bool, | ||
location: function (props, propName, componentName) { | ||
var location = props[propName]; | ||
/** | ||
* Handles errors that were thrown asynchronously. By default, the | ||
* error is re-thrown so we don't swallow them silently. | ||
*/ | ||
handleAsyncError: function (error, route) { | ||
throw error; // This error probably originated in a transition hook. | ||
}, | ||
/** | ||
* Handles cancelled transitions. By default, redirects replace the | ||
* current URL and aborts roll it back. | ||
*/ | ||
handleCancelledTransition: function (transition, routes) { | ||
var reason = transition.cancelReason; | ||
if (reason instanceof Redirect) { | ||
replaceWith(reason.to, reason.params, reason.query); | ||
} else if (reason instanceof Abort) { | ||
goBack(); | ||
} | ||
if (typeof location === 'string' && !(location in NAMED_LOCATIONS)) | ||
return new Error('Unknown location "' + location + '", see ' + componentName); | ||
} | ||
}, | ||
propTypes: { | ||
location: React.PropTypes.oneOf([ 'hash', 'history' ]).isRequired, | ||
preserveScrollPosition: React.PropTypes.bool | ||
}, | ||
getDefaultProps: function () { | ||
return { | ||
location: 'hash', | ||
preserveScrollPosition: false | ||
onAbortedTransition: defaultAbortedTransitionHandler, | ||
onActiveStateChange: defaultActiveStateChangeHandler, | ||
onTransitionError: defaultTransitionErrorHandler, | ||
preserveScrollPosition: false, | ||
location: HashLocation | ||
}; | ||
@@ -70,26 +99,32 @@ }, | ||
getInitialState: function () { | ||
return {}; | ||
return { | ||
routes: RouteStore.registerChildren(this.props.children, this) | ||
}; | ||
}, | ||
componentWillMount: function () { | ||
React.Children.forEach(this.props.children, function (child) { | ||
RouteStore.registerRoute(child); | ||
}); | ||
if (!URLStore.isSetup() && ExecutionEnvironment.canUseDOM) | ||
URLStore.setup(this.props.location); | ||
getLocation: function () { | ||
var location = this.props.location; | ||
URLStore.addChangeListener(this.handleRouteChange); | ||
if (typeof location === 'string') | ||
return NAMED_LOCATIONS[location]; | ||
return location; | ||
}, | ||
componentWillMount: function () { | ||
PathStore.setup(this.getLocation()); | ||
PathStore.addChangeListener(this.handlePathChange); | ||
}, | ||
componentDidMount: function () { | ||
this.dispatch(URLStore.getCurrentPath()); | ||
this.handlePathChange(); | ||
}, | ||
componentWillUnmount: function () { | ||
URLStore.removeChangeListener(this.handleRouteChange); | ||
PathStore.removeChangeListener(this.handlePathChange); | ||
}, | ||
handleRouteChange: function () { | ||
this.dispatch(URLStore.getCurrentPath()); | ||
handlePathChange: function () { | ||
this.dispatch(PathStore.getCurrentPath()); | ||
}, | ||
@@ -115,11 +150,3 @@ | ||
match: function (path) { | ||
var rootRoutes = this.props.children; | ||
if (!Array.isArray(rootRoutes)) { | ||
rootRoutes = [rootRoutes]; | ||
} | ||
var matches = null; | ||
for (var i = 0; matches == null && i < rootRoutes.length; i++) { | ||
matches = findMatches(Path.withoutQuery(path), rootRoutes[i]); | ||
} | ||
return matches; | ||
return findMatches(Path.withoutQuery(path), this.state.routes, this.props.defaultRoute); | ||
}, | ||
@@ -155,7 +182,14 @@ | ||
var promise = syncWithTransition(routes, transition).then(function (newState) { | ||
if (transition.isCancelled) { | ||
Routes.handleCancelledTransition(transition, routes); | ||
} else if (newState) { | ||
ActiveStore.updateState(newState); | ||
var promise = runTransitionHooks(routes, transition).then(function (nextState) { | ||
if (transition.isAborted) { | ||
routes.props.onAbortedTransition(transition); | ||
} else if (nextState) { | ||
routes.setState(nextState); | ||
routes.props.onActiveStateChange(nextState); | ||
// TODO: add functional test | ||
var rootMatch = getRootMatch(nextState.matches); | ||
if (rootMatch) | ||
maybeScrollWindow(routes, rootMatch.route); | ||
} | ||
@@ -170,3 +204,3 @@ | ||
setTimeout(function () { | ||
Routes.handleAsyncError(error, routes); | ||
routes.props.onTransitionError(error); | ||
}); | ||
@@ -194,67 +228,38 @@ }); | ||
function Transition(path) { | ||
this.path = path; | ||
this.cancelReason = null; | ||
this.isCancelled = false; | ||
} | ||
function findMatches(path, routes, defaultRoute) { | ||
var matches = null, route, params; | ||
mergeProperties(Transition.prototype, { | ||
for (var i = 0, len = routes.length; i < len; ++i) { | ||
route = routes[i]; | ||
abort: function () { | ||
this.cancelReason = new Abort(); | ||
this.isCancelled = true; | ||
}, | ||
// Check the subtree first to find the most deeply-nested match. | ||
matches = findMatches(path, route.props.children, route.props.defaultRoute); | ||
redirect: function (to, params, query) { | ||
this.cancelReason = new Redirect(to, params, query); | ||
this.isCancelled = true; | ||
}, | ||
if (matches != null) { | ||
var rootParams = getRootMatch(matches).params; | ||
params = route.props.paramNames.reduce(function (params, paramName) { | ||
params[paramName] = rootParams[paramName]; | ||
return params; | ||
}, {}); | ||
retry: function () { | ||
transitionTo(this.path); | ||
} | ||
matches.unshift(makeMatch(route, params)); | ||
}); | ||
function Abort() {} | ||
function Redirect(to, params, query) { | ||
this.to = to; | ||
this.params = params; | ||
this.query = query; | ||
} | ||
function findMatches(path, route) { | ||
var children = route.props.children, matches; | ||
var params; | ||
// Check the subtree first to find the most deeply-nested match. | ||
if (Array.isArray(children)) { | ||
for (var i = 0, len = children.length; matches == null && i < len; ++i) { | ||
matches = findMatches(path, children[i]); | ||
return matches; | ||
} | ||
} else if (children) { | ||
matches = findMatches(path, children); | ||
} | ||
if (matches) { | ||
var rootParams = getRootMatch(matches).params; | ||
params = {}; | ||
// No routes in the subtree matched, so check this route. | ||
params = Path.extractParams(route.props.path, path); | ||
Path.extractParamNames(route.props.path).forEach(function (paramName) { | ||
params[paramName] = rootParams[paramName]; | ||
}); | ||
matches.unshift(makeMatch(route, params)); | ||
return matches; | ||
if (params) | ||
return [ makeMatch(route, params) ]; | ||
} | ||
// No routes in the subtree matched, so check this route. | ||
params = Path.extractParams(route.props.path, path); | ||
// No routes matched, so try the default route if there is one. | ||
params = defaultRoute && Path.extractParams(defaultRoute.props.path, path); | ||
if (params) | ||
return [ makeMatch(route, params) ]; | ||
return [ makeMatch(defaultRoute, params) ]; | ||
return null; | ||
return matches; | ||
} | ||
@@ -298,3 +303,3 @@ | ||
*/ | ||
function syncWithTransition(routes, transition) { | ||
function runTransitionHooks(routes, transition) { | ||
if (routes.state.path === transition.path) | ||
@@ -331,8 +336,8 @@ return Promise.resolve(); // Nothing to do! | ||
return checkTransitionFromHooks(fromMatches, transition).then(function () { | ||
if (transition.isCancelled) | ||
return runTransitionFromHooks(fromMatches, transition).then(function () { | ||
if (transition.isAborted) | ||
return; // No need to continue. | ||
return checkTransitionToHooks(toMatches, transition).then(function () { | ||
if (transition.isCancelled) | ||
return runTransitionToHooks(toMatches, transition).then(function () { | ||
if (transition.isAborted) | ||
return; // No need to continue. | ||
@@ -343,3 +348,4 @@ | ||
var query = Path.extractQuery(transition.path) || {}; | ||
var state = { | ||
return { | ||
path: transition.path, | ||
@@ -353,8 +359,2 @@ matches: nextMatches, | ||
}; | ||
// TODO: add functional test | ||
maybeScrollWindow(routes, toMatches[toMatches.length - 1]); | ||
routes.setState(state); | ||
return state; | ||
}); | ||
@@ -370,3 +370,3 @@ }); | ||
*/ | ||
function checkTransitionFromHooks(matches, transition) { | ||
function runTransitionFromHooks(matches, transition) { | ||
var promise = Promise.resolve(); | ||
@@ -378,3 +378,3 @@ | ||
if (!transition.isCancelled && handler.willTransitionFrom) | ||
if (!transition.isAborted && handler.willTransitionFrom) | ||
return handler.willTransitionFrom(transition, match.component); | ||
@@ -392,10 +392,10 @@ }); | ||
*/ | ||
function checkTransitionToHooks(matches, transition) { | ||
function runTransitionToHooks(matches, transition) { | ||
var promise = Promise.resolve(); | ||
matches.forEach(function (match, index) { | ||
matches.forEach(function (match) { | ||
promise = promise.then(function () { | ||
var handler = match.route.props.handler; | ||
if (!transition.isCancelled && handler.willTransitionTo) | ||
if (!transition.isAborted && handler.willTransitionTo) | ||
return handler.willTransitionTo(transition, match.params); | ||
@@ -442,3 +442,3 @@ }); | ||
return route.props.handler(mergeProperties(props, addedProps)); | ||
return route.props.handler(copyProperties(props, addedProps)); | ||
}.bind(this, props); | ||
@@ -458,9 +458,6 @@ }); | ||
function maybeScrollWindow(routes, match) { | ||
if (routes.props.preserveScrollPosition) | ||
function maybeScrollWindow(routes, rootRoute) { | ||
if (routes.props.preserveScrollPosition || rootRoute.props.preserveScrollPosition) | ||
return; | ||
if (!match || match.route.props.preserveScrollPosition) | ||
return; | ||
window.scrollTo(0, 0); | ||
@@ -467,0 +464,0 @@ } |
@@ -1,7 +0,10 @@ | ||
var URLStore = require('../stores/URLStore'); | ||
var PathStore = require('../stores/PathStore'); | ||
/** | ||
* Transitions to the previous URL. | ||
*/ | ||
function goBack() { | ||
URLStore.back(); | ||
PathStore.pop(); | ||
} | ||
module.exports = goBack; |
@@ -1,2 +0,3 @@ | ||
var URLStore = require('../stores/URLStore'); | ||
var HashLocation = require('../locations/HashLocation'); | ||
var PathStore = require('../stores/PathStore'); | ||
var makePath = require('./makePath'); | ||
@@ -8,6 +9,6 @@ | ||
*/ | ||
function makeHref(routeName, params, query) { | ||
var path = makePath(routeName, params, query); | ||
function makeHref(to, params, query) { | ||
var path = makePath(to, params, query); | ||
if (URLStore.getLocation() === 'hash') | ||
if (PathStore.getLocation() === HashLocation) | ||
return '#' + path; | ||
@@ -14,0 +15,0 @@ |
var invariant = require('react/lib/invariant'); | ||
var copyProperties = require('react/lib/copyProperties'); | ||
var qs = require('querystring'); | ||
var mergeProperties = require('./mergeProperties'); | ||
var URL = require('./URL'); | ||
@@ -128,3 +128,3 @@ | ||
if (existingQuery) | ||
query = query ? mergeProperties(existingQuery, query) : existingQuery; | ||
query = query ? copyProperties(existingQuery, query) : existingQuery; | ||
@@ -131,0 +131,0 @@ var queryString = query && qs.stringify(query); |
@@ -1,2 +0,2 @@ | ||
var URLStore = require('../stores/URLStore'); | ||
var PathStore = require('../stores/PathStore'); | ||
var makePath = require('./makePath'); | ||
@@ -9,5 +9,5 @@ | ||
function replaceWith(to, params, query) { | ||
URLStore.replace(makePath(to, params, query)); | ||
PathStore.replace(makePath(to, params, query)); | ||
} | ||
module.exports = replaceWith; |
@@ -1,2 +0,2 @@ | ||
var URLStore = require('../stores/URLStore'); | ||
var PathStore = require('../stores/PathStore'); | ||
var makePath = require('./makePath'); | ||
@@ -9,5 +9,5 @@ | ||
function transitionTo(to, params, query) { | ||
URLStore.push(makePath(to, params, query)); | ||
PathStore.push(makePath(to, params, query)); | ||
} | ||
module.exports = transitionTo; |
@@ -97,3 +97,3 @@ var React = require('react'); | ||
componentDidMount: function () { | ||
if (this.props.initialAsyncState || !this.constructor.getInitialAsyncState) | ||
if (this.props.initialAsyncState || typeof this.constructor.getInitialAsyncState !== 'function') | ||
return; | ||
@@ -100,0 +100,0 @@ |
@@ -0,1 +1,12 @@ | ||
var EventEmitter = require('events').EventEmitter; | ||
var CHANGE_EVENT = 'change'; | ||
var _events = new EventEmitter; | ||
_events.setMaxListeners(0); | ||
function notifyChange() { | ||
_events.emit(CHANGE_EVENT); | ||
} | ||
var _activeRoutes = []; | ||
@@ -29,9 +40,2 @@ var _activeParams = {}; | ||
var EventEmitter = require('event-emitter'); | ||
var _events = EventEmitter(); | ||
function notifyChange() { | ||
_events.emit('change'); | ||
} | ||
/** | ||
@@ -44,14 +48,8 @@ * The ActiveStore keeps track of which routes, URL and query parameters are | ||
/** | ||
* Adds a listener that will be called when this store changes. | ||
*/ | ||
addChangeListener: function (listener) { | ||
_events.on('change', listener); | ||
_events.on(CHANGE_EVENT, listener); | ||
}, | ||
/** | ||
* Removes the given change listener. | ||
*/ | ||
removeChangeListener: function (listener) { | ||
_events.off('change', listener); | ||
_events.removeListener(CHANGE_EVENT, listener); | ||
}, | ||
@@ -58,0 +56,0 @@ |
@@ -29,8 +29,8 @@ var React = require('react'); | ||
unregisterRoute: function (route) { | ||
if (route.props.name) | ||
delete _namedRoutes[route.props.name]; | ||
var props = route.props; | ||
React.Children.forEach(route.props.children, function (child) { | ||
RouteStore.unregisterRoute(child); | ||
}); | ||
if (props.name) | ||
delete _namedRoutes[props.name]; | ||
React.Children.forEach(props.children, RouteStore.unregisterRoute); | ||
}, | ||
@@ -42,28 +42,32 @@ | ||
*/ | ||
registerRoute: function (route, _parentRoute) { | ||
// Make sure the <Route>'s path begins with a slash. Default to its name. | ||
// We can't do this in getDefaultProps because it may not be called on | ||
// <Route>s that are never actually mounted. | ||
if (route.props.path || route.props.name) { | ||
route.props.path = Path.normalize(route.props.path || route.props.name); | ||
} else { | ||
route.props.path = '/'; | ||
} | ||
registerRoute: function (route, parentRoute) { | ||
// Note: parentRoute may be a <Route> _or_ a <Routes>. | ||
var props = route.props; | ||
// Make sure the <Route> has a valid React component for a handler. | ||
invariant( | ||
React.isValidClass(route.props.handler), | ||
'The handler for Route "' + (route.props.name || route.props.path) + '" ' + | ||
'must be a valid React component' | ||
React.isValidClass(props.handler), | ||
'The handler for the "%s" route must be a valid React class', | ||
props.name || props.path | ||
); | ||
// Make sure the <Route> has all params that its parent needs. | ||
if (_parentRoute) { | ||
var paramNames = Path.extractParamNames(route.props.path); | ||
// Default routes have no name, path, or children. | ||
var isDefault = !(props.path || props.name || props.children); | ||
Path.extractParamNames(_parentRoute.props.path).forEach(function (paramName) { | ||
if (props.path || props.name) { | ||
props.path = Path.normalize(props.path || props.name); | ||
} else if (parentRoute && parentRoute.props.path) { | ||
props.path = parentRoute.props.path; | ||
} else { | ||
props.path = '/'; | ||
} | ||
props.paramNames = Path.extractParamNames(props.path); | ||
// Make sure the route's path has all params its parent needs. | ||
if (parentRoute && Array.isArray(parentRoute.props.paramNames)) { | ||
parentRoute.props.paramNames.forEach(function (paramName) { | ||
invariant( | ||
paramNames.indexOf(paramName) !== -1, | ||
'The nested route path "' + route.props.path + '" is missing the "' + paramName + '" ' + | ||
'parameter of its parent path "' + _parentRoute.props.path + '"' | ||
props.paramNames.indexOf(paramName) !== -1, | ||
'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"', | ||
props.path, paramName, parentRoute.props.path | ||
); | ||
@@ -73,17 +77,45 @@ }); | ||
// Make sure the <Route> can be looked up by <Link>s. | ||
if (route.props.name) { | ||
var existingRoute = _namedRoutes[route.props.name]; | ||
// Make sure the route can be looked up by <Link>s. | ||
if (props.name) { | ||
var existingRoute = _namedRoutes[props.name]; | ||
invariant( | ||
!existingRoute || route === existingRoute, | ||
'You cannot use the name "' + route.props.name + '" for more than one route' | ||
'You cannot use the name "%s" for more than one route', | ||
props.name | ||
); | ||
_namedRoutes[route.props.name] = route; | ||
_namedRoutes[props.name] = route; | ||
} | ||
React.Children.forEach(route.props.children, function (child) { | ||
RouteStore.registerRoute(child, route); | ||
if (parentRoute && isDefault) { | ||
invariant( | ||
parentRoute.props.defaultRoute == null, | ||
'You may not have more than one <DefaultRoute> per <Route>' | ||
); | ||
parentRoute.props.defaultRoute = route; | ||
return null; | ||
} | ||
// Make sure children is an array. | ||
props.children = RouteStore.registerChildren(props.children, route); | ||
return route; | ||
}, | ||
/** | ||
* Registers many children routes at once, always returning an array. | ||
*/ | ||
registerChildren: function (children, parentRoute) { | ||
var routes = []; | ||
React.Children.forEach(children, function (child) { | ||
// Exclude <DefaultRoute>s. | ||
if (child = RouteStore.registerRoute(child, parentRoute)) | ||
routes.push(child); | ||
}); | ||
return routes; | ||
}, | ||
@@ -90,0 +122,0 @@ |
{ | ||
"name": "react-router", | ||
"version": "0.5.2", | ||
"version": "0.5.3", | ||
"description": "A complete routing library for React.js", | ||
@@ -41,3 +41,3 @@ "tags": [ | ||
"react": ">=0.11.0", | ||
"rf-release": "0.1.2", | ||
"rf-release": "0.3.1", | ||
"uglify-js": "2.4.15", | ||
@@ -52,3 +52,3 @@ "webpack": "1.2.0-beta5", | ||
"es6-promise": "^1.0.0", | ||
"event-emitter": "^0.3.1", | ||
"events": "^1.0.1", | ||
"querystring": "^0.2.0" | ||
@@ -55,0 +55,0 @@ }, |
@@ -33,3 +33,3 @@ React Router | ||
Please refer to the [upgrade guide](/UPGRADE_GUIDE.md) and | ||
[changelog](/CHANGELOG) when upgrading. | ||
[changelog](/CHANGELOG.md) when upgrading. | ||
@@ -109,4 +109,4 @@ Installation | ||
4. **URLs are your first thought, not an after-thought** - With React | ||
Nested Router, you don't get UI on the page without configuring a url | ||
first. Fortunately, its wildly productive this way, too. | ||
Router, you don't get UI on the page without configuring a url first. | ||
Fortunately, its wildly productive this way, too. | ||
@@ -113,0 +113,0 @@ Related Modules |
@@ -5,3 +5,3 @@ Upgrade Guide | ||
To see discussion around these API changes, please refer to the | ||
[CHANGELOG](/CHANGELOG) and git log the commits to find the issues | ||
[changelog](/CHANGELOG.md) and git log the commits to find the issues | ||
they refer to. | ||
@@ -8,0 +8,0 @@ |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
238787
64
4543
+ Addedevents@^1.0.1
+ Addedevents@1.1.1(transitive)
- Removedevent-emitter@^0.3.1
- Removedd@1.0.2(transitive)
- Removedes5-ext@0.10.64(transitive)
- Removedes6-iterator@2.0.3(transitive)
- Removedes6-symbol@3.1.4(transitive)
- Removedesniff@2.0.1(transitive)
- Removedevent-emitter@0.3.5(transitive)
- Removedext@1.7.0(transitive)
- Removednext-tick@1.1.0(transitive)
- Removedtype@2.7.3(transitive)