Skip to content

Commit ce7f458

Browse files
committed
Environments now handle navigation.replace...
...by replacing current history record with a new one (similarly how to backbone does it). Fixes #11.
1 parent 6a38898 commit ce7f458

File tree

2 files changed

+100
-35
lines changed

2 files changed

+100
-35
lines changed

lib/Environment.js

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ Environment.prototype.navigate = function navigate(path, navigation, cb) {
5858
return this.setPath(path, navigation, cb);
5959
}
6060

61+
Environment.prototype.setPath = function(path, navigation, cb) {
62+
if (!navigation.isPopState) {
63+
if (navigation.replace) {
64+
this.replaceState(path, navigation);
65+
} else {
66+
this.pushState(path, navigation);
67+
}
68+
}
69+
this.path = path;
70+
this.notify(navigation, cb);
71+
}
72+
6173
/**
6274
* Register router with an environment.
6375
*/
@@ -96,13 +108,13 @@ PathnameEnvironment.prototype.getPath = function() {
96108
return window.location.pathname;
97109
}
98110

99-
PathnameEnvironment.prototype.setPath = function(path, navigation, cb) {
100-
if (!navigation.isPopState) {
101-
window.history.pushState({}, '', path);
102-
}
103-
this.path = path;
104-
this.notify(navigation, cb);
105-
};
111+
PathnameEnvironment.prototype.pushState = function(path, navigation) {
112+
window.history.pushState({}, '', path);
113+
}
114+
115+
PathnameEnvironment.prototype.replaceState = function(path, navigation) {
116+
window.history.replaceState({}, '', path);
117+
}
106118

107119
PathnameEnvironment.prototype.start = function() {
108120
window.addEventListener('popstate', this.onPopState.bind(this));
@@ -134,13 +146,14 @@ HashEnvironment.prototype.getPath = function() {
134146
return window.location.hash.slice(1) || '/';
135147
};
136148

137-
HashEnvironment.prototype.setPath = function(path, navigation, cb) {
138-
if (!navigation.isPopState) {
139-
window.location.hash = path;
140-
}
141-
this.path = path;
142-
this.notify(navigation, cb);
143-
};
149+
HashEnvironment.prototype.pushState = function(path, navigation) {
150+
window.location.hash = path;
151+
}
152+
153+
HashEnvironment.prototype.replaceState = function(path, navigation) {
154+
var href = window.location.href.replace(/(javascript:|#).*$/, '');
155+
window.location.replace(href + '#' + path);
156+
}
144157

145158
HashEnvironment.prototype.start = function() {
146159
window.addEventListener('hashchange', this.onHashChange.bind(this));

tests/browser.js

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,18 @@ var historyAPI = (
1212

1313
var host, app, router;
1414

15+
var timeout = 250;
16+
1517
var div = React.DOM.div;
1618

19+
function delay(ms, func) {
20+
if (func === undefined) {
21+
func = ms;
22+
ms = timeout;
23+
}
24+
setTimeout(func, ms);
25+
}
26+
1727
function getRenderedContent() {
1828
var content = app.refs.content || app.refs.router;
1929
var node = content.getDOMNode();
@@ -40,7 +50,7 @@ function cleanUp(done) {
4050
window.history.pushState({}, '', '/__zuul');
4151
}
4252
window.location.hash = '';
43-
setTimeout(done, 200);
53+
delay(done);
4454
}
4555

4656
function setUp(App) {
@@ -72,6 +82,10 @@ describe('Routing', function() {
7282
}, 'mainpage')
7383
}
7484
}),
85+
Router.Location({
86+
path: '/__zuul/transient',
87+
handler: function(props) { return div(null, "i'm transient") }
88+
}),
7589
Router.Location({
7690
path: '/__zuul/:slug',
7791
handler: function(props) { return div(null, props.slug) }
@@ -110,10 +124,25 @@ describe('Routing', function() {
110124
router.navigate('/__zuul/hello', function() {
111125
assertRendered('hello');
112126
history.back();
113-
setTimeout(function() {
127+
delay(function() {
114128
assertRendered('mainpage');
115129
done();
116-
}, 200);
130+
});
131+
});
132+
});
133+
134+
it('navigates to a different route (replacing current history record)', function(done) {
135+
assertRendered('mainpage');
136+
router.navigate('/__zuul/hello', function() {
137+
assertRendered('hello');
138+
router.navigate('/__zuul/transient', {replace: true}, function() {
139+
assertRendered("i'm transient");
140+
history.back();
141+
delay(function() {
142+
assertRendered('mainpage');
143+
done();
144+
});
145+
});
117146
});
118147
});
119148

@@ -138,19 +167,19 @@ describe('Routing', function() {
138167
it('navigates via onClick event', function(done) {
139168
assertRendered('mainpage');
140169
clickOn(router.refs.link);
141-
setTimeout(function() {
170+
delay(function() {
142171
assertRendered('hello');
143172
done();
144-
}, 200);
173+
});
145174
});
146175

147176
it('navigates even if it is situated outside of the router context', function(done) {
148177
assertRendered('mainpage');
149178
clickOn(app.refs.outside);
150-
setTimeout(function() {
179+
delay(function() {
151180
assertRendered('hi');
152181
done();
153-
}, 200);
182+
});
154183
});
155184

156185
});
@@ -189,9 +218,9 @@ describe('Routing with async components', function() {
189218
mixins: [ReactAsync.Mixin],
190219

191220
getInitialStateAsync: function(cb) {
192-
setTimeout(function() {
221+
delay(function() {
193222
cb(null, {message: 'about'});
194-
}, 200);
223+
});
195224
},
196225

197226
render: function() {
@@ -401,10 +430,10 @@ describe('Contextual routers', function() {
401430
router.navigate('/__zuul/subcat/page', function() {
402431
assertRendered('subcat/page');
403432
clickOn(router.refs.subcat.refs.router.refs.link);
404-
setTimeout(function() {
433+
delay(function() {
405434
assertRendered('subcat/root');
406435
done();
407-
}, 200);
436+
});
408437
});
409438
});
410439

@@ -413,10 +442,10 @@ describe('Contextual routers', function() {
413442
router.navigate('/__zuul/subcat/escape', function() {
414443
assertRendered('subcat/escape');
415444
clickOn(router.refs.subcat.refs.router.refs.link);
416-
setTimeout(function() {
445+
delay(function() {
417446
assertRendered('mainpage');
418447
done();
419-
}, 200);
448+
});
420449
});
421450
});
422451
});
@@ -489,10 +518,10 @@ describe('Multiple active routers', function() {
489518
app.refs.router1.navigate('/__zuul/hello', function() {
490519
assertRendered('hello1hello2');
491520
window.history.back();
492-
setTimeout(function() {
521+
delay(function() {
493522
assertRendered('mainpage1mainpage2');
494523
done();
495-
}, 200);
524+
});
496525
});
497526
});
498527

@@ -510,6 +539,12 @@ describe('Hash routing', function() {
510539
return Router.Link({ref: 'link', href: '/hello'}, 'mainpage');
511540
}
512541
}),
542+
Router.Location({
543+
path: '/transient',
544+
handler: function(props) {
545+
return div(null, "i'm transient");
546+
}
547+
}),
513548
Router.Location({
514549
path: '/:slug',
515550
handler: function(props) {
@@ -530,6 +565,23 @@ describe('Hash routing', function() {
530565
assert.ok(dom.classList.contains('App'));
531566
});
532567

568+
it('navigates to a different route (replacing current history record)', function(done) {
569+
assertRendered('mainpage');
570+
router.navigate('/hello', function() {
571+
assertRendered('hello');
572+
delay(function() {
573+
router.navigate('/transient', {replace: true}, function() {
574+
assertRendered("i'm transient");
575+
history.back();
576+
delay(function() {
577+
assertRendered('mainpage');
578+
done();
579+
});
580+
});
581+
});
582+
});
583+
});
584+
533585
it('navigates to a different route', function(done) {
534586
assertRendered('mainpage');
535587
router.navigate('/hello', function() {
@@ -543,10 +595,10 @@ describe('Hash routing', function() {
543595
router.navigate('/hello', function() {
544596
assertRendered('hello');
545597
window.location.hash = '/';
546-
setTimeout(function() {
598+
delay(function() {
547599
assertRendered('mainpage');
548600
done();
549-
}, 200);
601+
});
550602
});
551603
});
552604

@@ -563,10 +615,10 @@ describe('Hash routing', function() {
563615
it('navigates via onClick event', function(done) {
564616
assertRendered('mainpage');
565617
clickOn(router.refs.link);
566-
setTimeout(function() {
618+
delay(function() {
567619
assertRendered('hello');
568620
done();
569-
}, 200);
621+
});
570622
});
571623
});
572624

@@ -622,10 +674,10 @@ describe('Contextual Hash routers', function() {
622674
router.navigate('/subcat/escape', function() {
623675
assertRendered('subcat/escape');
624676
clickOn(router.refs.subcat.refs.router.refs.link);
625-
setTimeout(function() {
677+
delay(function() {
626678
assertRendered('mainpage');
627679
done();
628-
}, 200);
680+
});
629681
});
630682
});
631683

0 commit comments

Comments
 (0)