diff --git a/index.d.ts b/index.d.ts index 2a628ade..4af6fc99 100644 --- a/index.d.ts +++ b/index.d.ts @@ -4,3 +4,26 @@ declare namespace mitt { (all?: { [key: string]: Array }): Emitter; } } + +declare module 'delegated-events' { + type EventHandler = (event: Event) => any; + + type EventListenerOptions = { + capture?: boolean; + document?: Document; + }; + + export function on( + name: string, + selector: string, + handler: EventHandler, + options?: EventListenerOptions, + ): void; + export function off( + name: string, + selector: string, + handler: EventHandler, + options?: EventListenerOptions, + ): void; + export function fire(target: EventTarget, name: string, detail?: any): void; +} diff --git a/package.json b/package.json index 1dc77585..9212c64c 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "typescript": "^3.1.6" }, "dependencies": { + "delegated-events": "git+https://git@github.com/rrweb-io/delegated-events.git", "mitt": "^1.1.3", "rrweb-snapshot": "^0.6.1" } diff --git a/src/record/index.ts b/src/record/index.ts index 9076d168..b886607f 100644 --- a/src/record/index.ts +++ b/src/record/index.ts @@ -53,8 +53,8 @@ function record(options: recordOptions = {}) { data: { node, initialOffset: { - left: document.documentElement.scrollLeft, - top: document.documentElement.scrollTop, + left: document.documentElement!.scrollLeft, + top: document.documentElement!.scrollTop, }, }, }), diff --git a/src/replay/index.ts b/src/replay/index.ts index 9588734a..9f9dac2a 100644 --- a/src/replay/index.ts +++ b/src/replay/index.ts @@ -1,5 +1,6 @@ import { rebuild, buildNodeWithSN } from 'rrweb-snapshot'; import * as mittProxy from 'mitt'; +import { on, off } from 'delegated-events'; import Timer from './timer'; import { EventType, @@ -155,7 +156,7 @@ export class Replayer { const firstOffset = event.data.positions[0].timeOffset; // timeOffset is a negative offset to event.timestamp const firstTimestamp = event.timestamp + firstOffset; - const delay = firstTimestamp - this.baselineTime + const delay = firstTimestamp - this.baselineTime; event.data.positions = event.data.positions.map(p => { return { ...p, @@ -207,17 +208,23 @@ export class Replayer { ) { mirror.map = rebuild(event.data.node, this.iframe.contentDocument!)[1]; // avoid form submit to refresh the iframe - this.iframe.contentDocument!.addEventListener('submit', evt => { - if (evt.target && (evt.target as Element).tagName === 'FORM') { - evt.preventDefault(); - } + off('submit', 'form', this.preventDefault, { + document: this.iframe.contentDocument!, + }); + on('submit', 'form', this.preventDefault, { + document: this.iframe.contentDocument!, }); // avoid a link click to refresh the iframe - this.iframe.contentDocument!.addEventListener('click', evt => { - if (evt.target && (evt.target as Element).tagName === 'A') { - evt.preventDefault(); - } + off('click', 'a', this.preventDefault, { + document: this.iframe.contentDocument!, }); + on('click', 'a', this.preventDefault, { + document: this.iframe.contentDocument!, + }); + } + + private preventDefault(evt: Event) { + evt.preventDefault(); } private applyIncremental(d: incrementalData, isSync: boolean) {