Revela/src/client/history.js
2022-11-19 19:57:18 -05:00

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;