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;