client/router: refactor call chains

This commit is contained in:
rr- 2016-06-12 21:57:19 +02:00
parent ee829e42d2
commit e10ed4bce8
2 changed files with 29 additions and 53 deletions

View File

@ -11,19 +11,12 @@ router.Context.prototype.pushState = function() {
origPushState.call(this); origPushState.call(this);
}; };
router.cancel = function(ctx) {
prevContext = ctx;
ctx.pushState();
};
router.exit( router.exit(
/.*/, /.*/,
(ctx, next) => { (ctx, next) => {
views.unlistenToMessages(); views.unlistenToMessages();
if (misc.confirmPageExit()) { if (misc.confirmPageExit()) {
next(); next();
} else {
router.cancel(ctx);
} }
}); });

View File

@ -3,13 +3,14 @@
// modified page.js by visionmedia // modified page.js by visionmedia
// - removed unused crap // - removed unused crap
// - refactored to classes // - refactored to classes
// - simplified method chains
// - added ability to call .save() in .exit() without side effects
const pathToRegexp = require('path-to-regexp'); const pathToRegexp = require('path-to-regexp');
const clickEvent = document.ontouchstart ? 'touchstart' : 'click'; const clickEvent = document.ontouchstart ? 'touchstart' : 'click';
let location = window.history.location || window.location; let location = window.history.location || window.location;
const base = ''; const base = '';
let prevContext = null;
function _decodeURLEncodedURIComponent(val) { function _decodeURLEncodedURIComponent(val) {
if (typeof val !== 'string') { if (typeof val !== 'string') {
@ -93,7 +94,6 @@ class Router {
constructor() { constructor() {
this._callbacks = []; this._callbacks = [];
this._exits = []; this._exits = [];
this._current = '';
} }
enter(path) { enter(path) {
@ -127,76 +127,59 @@ class Router {
if (!this._running) { if (!this._running) {
return; return;
} }
this._current = '';
this._running = false; this._running = false;
document.removeEventListener(clickEvent, this._onClick, false); document.removeEventListener(clickEvent, this._onClick, false);
window.removeEventListener('popstate', this._onPopState, false); window.removeEventListener('popstate', this._onPopState, false);
} }
show(path, state, push) { show(path, state, push) {
const oldPath = this.ctx ? this.ctx.path : ctx.path;
const ctx = new Context(path, state); const ctx = new Context(path, state);
this._current = ctx.path; this.dispatch(ctx, () => {
this.dispatch(ctx); if (ctx.path !== oldPath && push !== false) {
if (ctx.handled !== false && push !== false) { ctx.pushState();
ctx.pushState(); }
} });
return ctx; return ctx;
} }
replace(path, state, dispatch) { replace(path, state, dispatch) {
var ctx = new Context(path, state); var ctx = new Context(path, state);
this._current = ctx.path;
ctx.save();
if (dispatch) { if (dispatch) {
this.dispatch(ctx); this.dispatch(ctx, () => {
ctx.save();
});
} else {
ctx.save();
} }
return ctx; return ctx;
} }
dispatch(ctx) { dispatch(ctx, middle) {
const prev = prevContext; const swap = (_ctx, next) => {
this.ctx = ctx;
middle();
next();
};
const callChain = (this.ctx ? this._exits : [])
.concat(
[swap],
this._callbacks,
[this._unhandled, (ctx, next) => {}]);
let i = 0; let i = 0;
let j = 0; let fn = () => {
callChain[i++](this.ctx, fn);
prevContext = ctx;
const nextExit = () => {
const fn = this._exits[j++];
if (!fn) {
return nextEnter();
}
fn(prev, nextExit);
}; };
fn();
const nextEnter = () => {
const fn = this._callbacks[i++];
if (ctx.path !== this._current) {
ctx.handled = false;
return;
}
if (!fn) {
return this._unhandled(ctx);
}
fn(ctx, nextEnter);
};
if (prev) {
nextExit();
} else {
nextEnter();
}
} }
_unhandled(ctx) { _unhandled(ctx, next) {
if (ctx.handled) {
return;
}
let current = location.pathname + location.search; let current = location.pathname + location.search;
if (current === ctx.canonicalPath) { if (current === ctx.canonicalPath) {
return; return;
} }
router.stop(); router.stop();
ctx.handled = false;
location.href = ctx.canonicalPath; location.href = ctx.canonicalPath;
} }
}; };