Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added examples/pinterest/app.css
Empty file.
4 changes: 2 additions & 2 deletions examples/pinterest/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ var Feed = React.createClass({
<div>
{pictures.map(picture => (
<Link
href={`/pictures/${picture.id}`}
to={`/pictures/${picture.id}`}
transitionState={{fromFeed: true}}
>
<img style={{margin: 10}} src={picture.src} height="100"/>
Expand Down Expand Up @@ -116,7 +116,7 @@ var RootRoute = {
}
};

React.render(<Router routes={RootRoute}/>, document.getElementById('example'));
React.render(<Router children={RootRoute}/>, document.getElementById('example'));

// Wait a sec ... what's happening?
//
Expand Down
12 changes: 8 additions & 4 deletions modules/BrowserHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,25 +78,29 @@ export class BrowserHistory extends DOMHistory {
}

// http://www.w3.org/TR/2011/WD-html5-20110113/history.html#dom-history-pushstate
push(path) {
push(path, transitionState) {
if (this.isSupported) {
this._recordScrollPosition();

var key = createRandomKey();
window.history.pushState({ key }, '', path);
this.location = this._createLocation(path, key, NavigationTypes.PUSH);
this.location = this._createLocation(
path, key, NavigationTypes.PUSH, transitionState
);
this._notifyChange();
} else {
window.location = path;
}
}

// http://www.w3.org/TR/2011/WD-html5-20110113/history.html#dom-history-replacestate
replace(path) {
replace(path, transitionState) {
if (this.isSupported) {
var key = createRandomKey();
window.history.replaceState({ key }, '', path);
this.location = this._createLocation(path, key, NavigationTypes.REPLACE);
this.location = this._createLocation(
path, key, NavigationTypes.REPLACE, transitionState
);
this._notifyChange();
} else {
window.location.replace(path);
Expand Down
7 changes: 5 additions & 2 deletions modules/DOMHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export class DOMHistory extends History {
super();
this.getScrollPosition = getScrollPosition;
this.scrollHistory = {};
this.stateHistory = {};
}

go(n) {
Expand All @@ -20,11 +21,13 @@ export class DOMHistory extends History {
window.history.go(n);
}

_createLocation(path, key, navigationType) {
_createLocation(path, key, navigationType, transitionState) {
var scrollKey = key || path;
var scrollPosition = this.scrollHistory[scrollKey];
transitionState = transitionState || this.stateHistory[key];
this.stateHistory[key] = transitionState;

return new Location(path, key, navigationType, scrollPosition);
return new Location(path, key, navigationType, scrollPosition, transitionState);
}

_recordScrollPosition() {
Expand Down
5 changes: 4 additions & 1 deletion modules/Link.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
console.log('got the source');

var { object, string, func } = React.PropTypes;

Expand Down Expand Up @@ -69,7 +70,9 @@ export class Link extends React.Component {
event.preventDefault();

if (allowTransition)
this.context.router.transitionTo(this.props.to, this.props.query);
this.context.router.transitionTo(
this.props.to, this.props.query, this.props.transitionState
);
}

render() {
Expand Down
5 changes: 3 additions & 2 deletions modules/Location.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ export class Location {
return new Location(object);

if (object && object.path)
return new Location(object.path, object.key, object.navigationType, object.scrollPosition);
return new Location(object.path, object.key, object.navigationType, object.scrollPosition, object.transitionState);

throw new Error('Unable to create a Location from ' + object);
}

constructor(path, key=null, navigationType=NavigationTypes.POP, scrollPosition=null) {
constructor(path, key=null, navigationType=NavigationTypes.POP, scrollPosition=null, transitionState=null) {
this.path = path;
this.key = key;
this.navigationType = navigationType;
this.scrollPosition = scrollPosition;
this.transitionState = transitionState;
}

}
Expand Down
8 changes: 4 additions & 4 deletions modules/MemoryHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ export class MemoryHistory extends History {
}

// http://www.w3.org/TR/2011/WD-html5-20110113/history.html#dom-history-pushstate
push(path) {
push(path, transitionState) {
this.current += 1;
this.entries = this.entries.slice(0, this.current).concat([ path ]);
this.location = new Location(path, null, NavigationTypes.PUSH);
this.location = new Location(path, null, NavigationTypes.PUSH, null, transitionState);
this._notifyChange();
}

// http://www.w3.org/TR/2011/WD-html5-20110113/history.html#dom-history-replacestate
replace(path) {
replace(path, transitionState) {
this.entries[this.current] = path;
this.location = new Location(path, null, NavigationTypes.REPLACE);
this.location = new Location(path, null, NavigationTypes.REPLACE, null, transitionState);
this._notifyChange();
}

Expand Down
16 changes: 8 additions & 8 deletions modules/Router.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export class Router extends React.Component {

try {
for (var i = 0, len = hooks.length; i < len; ++i) {
hooks[i].call(this);
hooks[i].call(this, location.transitionState);

if (this.nextLocation !== nextLocation)
break; // No need to proceed further.
Expand Down Expand Up @@ -218,29 +218,29 @@ export class Router extends React.Component {
return path;
}

transitionTo(pathname, query) {
transitionTo(pathname, query, transitionState) {
var path = this.makePath(pathname, query);
var { history } = this.props;

if (history) {
if (this.nextLocation) {
history.replace(path);
history.replace(path, transitionState);
} else {
history.push(path);
history.push(path, transitionState);
}
} else {
this._updateLocation(path);
this._updateLocation({ path, transitionState });
}
}

replaceWith(pathname, query) {
replaceWith(pathname, query, transitionState) {
var path = this.makePath(pathname, query);
var { history } = this.props;

if (history) {
history.replace(path);
history.replace(path, transitionState);
} else {
this._updateLocation(path);
this._updateLocation({path, transitionState});
}
}

Expand Down
48 changes: 45 additions & 3 deletions modules/__tests__/getProps-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import expect, { spyOn } from 'expect';
import Location from '../Location';
import { getProps } from '../getProps';
import qs from 'qs';

Expand All @@ -17,7 +18,7 @@ describe('Matching pathnames', function () {

CoursesRoute = {
path: 'courses',
getChildRoutes(callback) {
getChildRoutes(transitionState, callback) {
callback(null, [ GradesRoute ]);
}
};
Expand All @@ -35,7 +36,7 @@ describe('Matching pathnames', function () {
};

CourseRoute = {
getChildRoutes(callback) {
getChildRoutes(transitionState, callback) {
setTimeout(function () {
callback(null, [ CourseGradesRoute, AssignmentRoute, AssignmentsRoute ]);
}, 0);
Expand All @@ -53,7 +54,7 @@ describe('Matching pathnames', function () {

ProfileRoute = {
path: 'profile',
getIndexRoute (cb) {
getIndexRoute (transitionState, cb) {
cb(null, ProfileIndexRoute);
}
};
Expand Down Expand Up @@ -210,6 +211,46 @@ describe('Matching pathnames', function () {
expect(outerProps).toNotExist();
});
});

});

describe('transitionState', function () {
var RouteA = {path: 'test'};
var RouteB = {path: 'test'};
var RootRoute = {
path: '/',
getIndexRoute (transitionState, cb) {
if (transitionState.test)
cb(null, RouteA);
else
cb(null, RouteB);
},
getChildRoutes (transitionState, cb) {
if (transitionState.test)
cb(null, [RouteA]);
else
cb(null, [RouteB]);
}
};

it('is passed to getChildRoutes', function (done) {
var transitionState = { test: true };
var location = new Location('/test', null, null, null, transitionState);
getProps(RootRoute, location, parseQueryString, function (err, props) {
expect(props.branch).toEqual([RootRoute, RouteA]);
done();
});
});

it('is passed to getIndexRoute', function (done) {
var transitionState = { test: true };
var location = new Location('/', null, null, null, transitionState);
getProps(RootRoute, location, parseQueryString, function (err, props) {
expect(props.branch).toEqual([RootRoute, RouteA]);
done();
});
});

});

describe('Matching params', function () {
Expand Down Expand Up @@ -364,4 +405,5 @@ describe('Matching params', function () {
});
});
});

});
18 changes: 9 additions & 9 deletions modules/getProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { createRoutes } from './RouteUtils';
import { getPathname, getQueryString, matchPattern, stripLeadingSlashes } from './PathUtils';
import Location from './Location';

function getChildRoutes(route, callback) {
function getChildRoutes(route, transitionState, callback) {
if (route.childRoutes) {
callback(null, route.childRoutes);
} else if (route.getChildRoutes) {
route.getChildRoutes(callback);
route.getChildRoutes(transitionState, callback);
} else {
callback();
}
Expand All @@ -33,7 +33,7 @@ function createParams(paramNames, paramValues) {
return assignParams({}, paramNames, paramValues);
}

function matchRouteDeep(route, pathname, callback) {
function matchRouteDeep(route, pathname, transitionState, callback) {
var { remainingPathname, paramNames, paramValues } = matchPattern(route.path, pathname);
var isExactMatch = remainingPathname === '';

Expand All @@ -45,7 +45,7 @@ function matchRouteDeep(route, pathname, callback) {
branch.push(route.indexRoute);
callback(null, { params, branch });
} else if (route.getIndexRoute) {
route.getIndexRoute(function (error, indexRoute) {
route.getIndexRoute(transitionState, function (error, indexRoute) {
if (error) {
callback(error);
} else {
Expand All @@ -58,12 +58,12 @@ function matchRouteDeep(route, pathname, callback) {
}
} else if (remainingPathname != null) {
// This route matched at least some of the path.
getChildRoutes(route, function (error, childRoutes) {
getChildRoutes(route, transitionState, function (error, childRoutes) {
if (error) {
callback(error);
} else if (childRoutes) {
// Check the child routes to see if any of them match.
matchRoutes(childRoutes, remainingPathname, function (error, match) {
matchRoutes(childRoutes, remainingPathname, transitionState, function (error, match) {
if (error) {
callback(error);
} else if (match) {
Expand All @@ -84,11 +84,11 @@ function matchRouteDeep(route, pathname, callback) {
}
}

function matchRoutes(routes, pathname, callback) {
function matchRoutes(routes, pathname, transitionState, callback) {
routes = createRoutes(routes);

loopAsync(routes.length, function (index, next, done) {
matchRouteDeep(routes[index], pathname, function (error, match) {
matchRouteDeep(routes[index], pathname, transitionState, function (error, match) {
if (error || match) {
done(error, match);
} else {
Expand Down Expand Up @@ -116,7 +116,7 @@ export function getProps(routes, location, parseQueryString, callback) {

var pathname = stripLeadingSlashes(getPathname(location.path));

matchRoutes(routes, pathname, function (error, props) {
matchRoutes(routes, pathname, location.transitionState, function (error, props) {
if (error || props == null) {
callback(error);
} else {
Expand Down