change observed mutations into serializable records
This commit is contained in:
107
src/record/observer.ts
Normal file
107
src/record/observer.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { INode } from 'rrweb-snapshot';
|
||||
import { mirror } from '../utils';
|
||||
import {
|
||||
mutationCallBack,
|
||||
textMutation,
|
||||
attributeMutation,
|
||||
removedNodeMutation,
|
||||
addedNodeMutation,
|
||||
observerParam,
|
||||
} from '../types';
|
||||
|
||||
function initMutationObserver(cb: mutationCallBack): MutationObserver {
|
||||
const observer = new MutationObserver(mutations => {
|
||||
const texts: textMutation[] = [];
|
||||
const attributes: attributeMutation[] = [];
|
||||
const removes: removedNodeMutation[] = [];
|
||||
const adds: addedNodeMutation[] = [];
|
||||
mutations.forEach(mutation => {
|
||||
const {
|
||||
type,
|
||||
target,
|
||||
oldValue,
|
||||
addedNodes,
|
||||
removedNodes,
|
||||
attributeName,
|
||||
nextSibling,
|
||||
previousSibling,
|
||||
} = mutation;
|
||||
const id = mirror.getId(target as INode);
|
||||
switch (type) {
|
||||
case 'characterData': {
|
||||
const value = target.textContent;
|
||||
if (value !== oldValue) {
|
||||
texts.push({
|
||||
id,
|
||||
value,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'attributes': {
|
||||
const value = (target as HTMLElement).getAttribute(attributeName!);
|
||||
if (value === oldValue) {
|
||||
return;
|
||||
}
|
||||
let item: attributeMutation | undefined = attributes.find(
|
||||
a => a.id === id,
|
||||
);
|
||||
if (!item) {
|
||||
item = {
|
||||
id,
|
||||
attributes: {},
|
||||
};
|
||||
attributes.push(item);
|
||||
}
|
||||
// overwrite attribute if the mutations was triggered in same time
|
||||
item.attributes[attributeName!] = value;
|
||||
}
|
||||
case 'childList': {
|
||||
removedNodes.forEach(n => {
|
||||
removes.push({
|
||||
parentId: id,
|
||||
id: mirror.getId(n as INode),
|
||||
});
|
||||
});
|
||||
addedNodes.forEach(n => {
|
||||
adds.push({
|
||||
parentId: id,
|
||||
previousId: !previousSibling
|
||||
? previousSibling
|
||||
: mirror.getId(previousSibling as INode),
|
||||
nextId: !nextSibling
|
||||
? nextSibling
|
||||
: mirror.getId(nextSibling as INode),
|
||||
id: mirror.getId(n as INode),
|
||||
});
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
cb({
|
||||
texts,
|
||||
attributes,
|
||||
removes,
|
||||
adds,
|
||||
});
|
||||
});
|
||||
observer.observe(document, {
|
||||
attributes: true,
|
||||
attributeOldValue: true,
|
||||
characterData: true,
|
||||
characterDataOldValue: true,
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
return observer;
|
||||
}
|
||||
|
||||
export default function initObservers(o: observerParam) {
|
||||
const mutationObserver = initMutationObserver(o.mutationCb);
|
||||
return {
|
||||
mutationObserver,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user