104 lines
3.3 KiB
JavaScript
104 lines
3.3 KiB
JavaScript
import EventEmitter from 'events';
|
|
import HookEvent from './hook.js';
|
|
|
|
class History extends EventEmitter {
|
|
constructor(ctx) {
|
|
super();
|
|
this.ctx = ctx;
|
|
this.window = this.ctx.window;
|
|
this.History = this.window.History;
|
|
this.history = this.window.history;
|
|
this.historyProto = this.History ? this.History.prototype : {};
|
|
this.pushState = this.historyProto.pushState;
|
|
this.replaceState = this.historyProto.replaceState;
|
|
this.go = this.historyProto.go;
|
|
this.back = this.historyProto.back;
|
|
this.forward = this.historyProto.forward;
|
|
}
|
|
override() {
|
|
this.overridePushState();
|
|
this.overrideReplaceState();
|
|
this.overrideGo();
|
|
this.overrideForward();
|
|
this.overrideBack();
|
|
}
|
|
overridePushState() {
|
|
this.ctx.override(
|
|
this.historyProto,
|
|
'pushState',
|
|
(target, that, args) => {
|
|
if (2 > args.length) return target.apply(that, args);
|
|
let [state, title, url = ''] = args;
|
|
|
|
const event = new HookEvent(
|
|
{ state, title, url },
|
|
target,
|
|
that
|
|
);
|
|
this.emit('pushState', event);
|
|
|
|
if (event.intercepted) return event.returnValue;
|
|
return event.target.call(
|
|
event.that,
|
|
event.data.state,
|
|
event.data.title,
|
|
event.data.url
|
|
);
|
|
}
|
|
);
|
|
}
|
|
overrideReplaceState() {
|
|
this.ctx.override(
|
|
this.historyProto,
|
|
'replaceState',
|
|
(target, that, args) => {
|
|
if (2 > args.length) return target.apply(that, args);
|
|
let [state, title, url = ''] = args;
|
|
|
|
const event = new HookEvent(
|
|
{ state, title, url },
|
|
target,
|
|
that
|
|
);
|
|
this.emit('replaceState', event);
|
|
|
|
if (event.intercepted) return event.returnValue;
|
|
return event.target.call(
|
|
event.that,
|
|
event.data.state,
|
|
event.data.title,
|
|
event.data.url
|
|
);
|
|
}
|
|
);
|
|
}
|
|
overrideGo() {
|
|
this.ctx.override(this.historyProto, 'go', (target, that, [delta]) => {
|
|
const event = new HookEvent({ delta }, target, that);
|
|
this.emit('go', event);
|
|
|
|
if (event.intercepted) return event.returnValue;
|
|
return event.target.call(event.that, event.data.delta);
|
|
});
|
|
}
|
|
overrideForward() {
|
|
this.ctx.override(this.historyProto, 'forward', (target, that) => {
|
|
const event = new HookEvent(null, target, that);
|
|
this.emit('forward', event);
|
|
|
|
if (event.intercepted) return event.returnValue;
|
|
return event.target.call(event.that);
|
|
});
|
|
}
|
|
overrideBack() {
|
|
this.ctx.override(this.historyProto, 'back', (target, that) => {
|
|
const event = new HookEvent(null, target, that);
|
|
this.emit('back', event);
|
|
|
|
if (event.intercepted) return event.returnValue;
|
|
return event.target.call(event.that);
|
|
});
|
|
}
|
|
}
|
|
|
|
export default History;
|