ultraviolet/client/history.js
2022-02-14 00:25:17 -05:00

78 lines
No EOL
2.9 KiB
JavaScript

import EventEmitter from "./events.js";
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;