Skip to content
Closed
22 changes: 19 additions & 3 deletions lib/RouterMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,25 @@ var RouterMixin = {
},

childContextTypes: {
router: React.PropTypes.any
router: React.PropTypes.any,
routers: React.PropTypes.any
},

getChildContext: function() {
var routers = this.context.routers || []
if (routers.indexOf(this) === -1) {
routers.unshift(this)
}

return {
router: this
router: this,
routers: routers
};
},

contextTypes: {
router: React.PropTypes.any
router: React.PropTypes.any,
routers: React.PropTypes.any
},

getInitialState: function() {
Expand Down Expand Up @@ -133,6 +141,14 @@ var RouterMixin = {
* @param {Callback} cb
*/
navigate: function(path, navigation, cb) {
var levels = path.split('../');
if (levels.length > 1) {
var newPath = "/" + levels[levels.length-1];
var gotoContext = levels.length-1;
this.context.routers[gotoContext].navigate(newPath, navigation, cb);
return;
}

path = join(this.state.prefix, path);
this.getEnvironment().setPath(path, navigation, cb);
},
Expand Down
153 changes: 152 additions & 1 deletion tests/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ describe('Routing with async components', function() {
});

beforeEach(function() {
mainWasInLoadingState = false;
mainWasInLoadingState = false;
aboutWasInLoadingState = false;

mainSeenPendingUpdate = false;
Expand Down Expand Up @@ -553,6 +553,33 @@ describe('Contextual routers', function() {

if (!historyAPI) return;

var SubSubCat = React.createClass({

render: function() {
return div(null,
Router.Locations({ref: 'router', contextual: true},
Router.Location({
path: '/',
handler: function(props) { return div(null, 'subcat/subsubcat/root') }
}),
Router.Location({
path: '/back_to_parent',
ref: 'link',
handler: function(props) {
return Router.Link({href: '../'}, 'subcat/subsubcat/back_to_parent')
}
}),
Router.Location({
path: '/back_to_root',
ref: 'link',
handler: function(props) {
return Router.Link({href: '../../__zuul'}, 'subcat/subsubcat/back_to_root')
}
})
));
}
});

var SubCat = React.createClass({

render: function() {
Expand All @@ -575,6 +602,18 @@ describe('Contextual routers', function() {
handler: function(props) {
return Router.Link({global: true, href: '/__zuul'}, 'subcat/escape')
}
}),
Router.Location({
path: '/back_to_parent',
ref: 'link',
handler: function(props) {
return Router.Link({href: '../__zuul'}, 'subcat/back_to_parent')
}
}),
Router.Location({
path: '/subsubcat/*',
handler: SubSubCat,
ref: 'subsubcat'
})
));
}
Expand Down Expand Up @@ -652,6 +691,42 @@ describe('Contextual routers', function() {
});
});
});

it('does navigate to root context from nested', function(done) {
assertRendered('mainpage');
router.navigate('/__zuul/subcat/back_to_parent', function() {
assertRendered('subcat/back_to_parent');
clickOn(router.refs.subcat.refs.router.refs.link);
delay(function() {
assertRendered('mainpage');
done();
});
});
});

it('does navigate to nested context from double nested', function(done) {
assertRendered('mainpage');
router.navigate('/__zuul/subcat/subsubcat/back_to_parent', function() {
assertRendered('subcat/subsubcat/back_to_parent');
clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link);
delay(function() {
assertRendered('subcat/root');
done();
});
});
});

it('does navigate to root context from double nested', function(done) {
assertRendered('mainpage');
router.navigate('/__zuul/subcat/subsubcat/back_to_root', function() {
assertRendered('subcat/subsubcat/back_to_root');
clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link);
delay(function() {
assertRendered('mainpage');
done();
});
});
});
});

describe('Multiple active routers', function() {
Expand Down Expand Up @@ -833,6 +908,33 @@ describe('Hash routing', function() {

describe('Contextual Hash routers', function() {

var SubSubCat = React.createClass({

render: function() {
return div(null,
Router.Locations({ref: 'router', contextual: true},
Router.Location({
path: '/',
handler: function(props) { return div(null, 'subcat/subsubcat/root') }
}),
Router.Location({
path: '/back_to_parent',
ref: 'link',
handler: function(props) {
return Router.Link({href: '../'}, 'subcat/subsubcat/back_to_parent')
}
}),
Router.Location({
path: '/back_to_root',
ref: 'link',
handler: function(props) {
return Router.Link({href: '../../'}, 'subcat/subsubcat/back_to_root')
}
})
));
}
});

var SubCat = React.createClass({

render: function() {
Expand All @@ -848,6 +950,18 @@ describe('Contextual Hash routers', function() {
handler: function(props) {
return Router.Link({globalHash: true, href: '/'}, 'subcat/escape');
}
}),
Router.Location({
path: '/back_to_parent',
ref: 'link',
handler: function(props) {
return Router.Link({href: '../'}, 'subcat/back_to_parent')
}
}),
Router.Location({
path: '/subsubcat/*',
handler: SubSubCat,
ref: 'subsubcat'
})
));
}
Expand Down Expand Up @@ -889,6 +1003,43 @@ describe('Contextual Hash routers', function() {
});
});


it('does navigate to root context from nested', function(done) {
assertRendered('mainpage');
router.navigate('/subcat/back_to_parent', function() {
assertRendered('subcat/back_to_parent');
clickOn(router.refs.subcat.refs.router.refs.link);
delay(function() {
assertRendered('mainpage');
done();
});
});
});

it('does navigate to nested context from double nested', function(done) {
assertRendered('mainpage');
router.navigate('/subcat/subsubcat/back_to_parent', function() {
assertRendered('subcat/subsubcat/back_to_parent');
clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link);
delay(function() {
assertRendered('subcat/root');
done();
});
});
});

it('does navigate to root context from double nested', function(done) {
assertRendered('mainpage');
router.navigate('/subcat/subsubcat/back_to_root', function() {
assertRendered('subcat/subsubcat/back_to_root');
clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link);
delay(function() {
assertRendered('mainpage');
done();
});
});
});

});

});