clarity-js
Version:
An analytics library that uses web page interactions to generate aggregated insights
192 lines (189 loc) • 8.14 kB
text/typescript
import { Constant, Event, Token } from "@clarity-types/data";
import * as scrub from "@src/core/scrub";
import { time } from "@src/core/time";
import * as baseline from "@src/data/baseline";
import { queue } from "@src/data/upload";
import { metadata } from "@src/layout/target";
import * as change from "@src/interaction/change";
import * as click from "@src/interaction/click";
import * as clipboard from "@src/interaction/clipboard";
import * as input from "@src/interaction/input";
import * as pointer from "@src/interaction/pointer";
import * as resize from "@src/interaction/resize";
import * as scroll from "@src/interaction/scroll";
import * as selection from "@src/interaction/selection";
import * as submit from "@src/interaction/submit";
import * as timeline from "@src/interaction/timeline";
import * as unload from "@src/interaction/unload";
import * as visibility from "@src/interaction/visibility";
import * as focus from "@src/interaction/focus";
export default async function (type: Event, ts: number = null): Promise<void> {
let t = ts || time();
let tokens: Token[] = [t, type];
switch (type) {
case Event.MouseDown:
case Event.MouseUp:
case Event.MouseMove:
case Event.MouseWheel:
case Event.DoubleClick:
case Event.TouchStart:
case Event.TouchEnd:
case Event.TouchMove:
case Event.TouchCancel:
for (let entry of pointer.state) {
let pTarget = metadata(entry.data.target as Node, entry.event);
if (pTarget.id > 0) {
tokens = [entry.time, entry.event];
tokens.push(pTarget.id);
tokens.push(entry.data.x);
tokens.push(entry.data.y);
if (entry.data.id !== undefined) {
tokens.push(entry.data.id);
if (entry.data.isPrimary !== undefined) {
tokens.push("" + entry.data.isPrimary);
}
}
queue(tokens);
if (entry.data.isPrimary === undefined || entry.data.isPrimary) {
baseline.track(entry.event, entry.data.x, entry.data.y, entry.time);
}
}
}
pointer.reset();
break;
case Event.Click:
case Event.ContextMenu:
for (let entry of click.state) {
let cTarget = metadata(entry.data.target as Node, entry.event, entry.data.text);
tokens = [entry.time, entry.event];
let cHash = cTarget.hash ? cTarget.hash.join(Constant.Dot) : Constant.Empty;
tokens.push(
cTarget.id, entry.data.x, entry.data.y,
entry.data.eX, entry.data.eY,
entry.data.button, entry.data.reaction, entry.data.context,
scrub.text(entry.data.text, "click", cTarget.privacy),
scrub.url(entry.data.link),
cHash, entry.data.trust, entry.data.isFullText,
entry.data.w, entry.data.h,
entry.data.tag, entry.data.class, entry.data.id, entry.data.source
);
queue(tokens);
timeline.track(entry.time, entry.event, cHash, entry.data.x, entry.data.y, entry.data.reaction, entry.data.context);
}
click.reset();
break;
case Event.Clipboard:
for (let entry of clipboard.state) {
tokens = [entry.time, entry.event];
let target = metadata(entry.data.target as Node, entry.event);
if (target.id > 0) {
tokens.push(target.id);
tokens.push(entry.data.action);
queue(tokens);
}
}
clipboard.reset();
break;
case Event.Resize:
let r = resize.data;
tokens.push(r.width, r.height);
baseline.track(type, r.width, r.height);
resize.reset();
queue(tokens);
break;
case Event.Unload:
let u = unload.data;
tokens.push(u.name, u.persisted);
unload.reset();
queue(tokens);
break;
case Event.Input:
for (let entry of input.state) {
let iTarget = metadata(entry.data.target as Node, entry.event, entry.data.value);
tokens = [entry.time, entry.event];
tokens.push(iTarget.id);
tokens.push(scrub.text(entry.data.value, "input", iTarget.privacy, false, entry.data.type));
tokens.push(entry.data.trust);
queue(tokens);
}
input.reset();
break;
case Event.Selection:
let s = selection.data;
if (s) {
let startTarget = metadata(s.start as Node, type);
let endTarget = metadata(s.end as Node, type);
tokens.push(startTarget.id, s.startOffset, endTarget.id, s.endOffset);
selection.reset();
queue(tokens);
}
break;
case Event.Scroll:
for (let entry of scroll.state) {
let sTarget = metadata(entry.data.target as Node, entry.event);
const top = metadata(entry.data.top as Node, entry.event);
const bottom = metadata(entry.data.bottom as Node, entry.event);
const sTopHash = top?.hash ? top.hash.join(Constant.Dot) : Constant.Empty;
const sBottomHash = bottom?.hash ? bottom.hash.join(Constant.Dot) : Constant.Empty;
if (sTarget.id > 0) {
tokens = [entry.time, entry.event];
tokens.push(
sTarget.id, entry.data.x, entry.data.y,
sTopHash, sBottomHash, entry.data.trust
);
queue(tokens);
baseline.track(entry.event, entry.data.x, entry.data.y, entry.time);
}
}
scroll.reset();
break;
case Event.Change:
for (let entry of change.state) {
tokens = [entry.time, entry.event];
let target = metadata(entry.data.target as Node, entry.event);
if (target.id > 0) {
tokens = [entry.time, entry.event];
tokens.push(target.id);
tokens.push(entry.data.type);
tokens.push(scrub.text(entry.data.value, "change", target.privacy));
tokens.push(scrub.text(entry.data.checksum, "checksum", target.privacy));
queue(tokens);
}
}
change.reset();
break;
case Event.Submit:
for (let entry of submit.state) {
tokens = [entry.time, entry.event];
let target = metadata(entry.data.target as Node, entry.event);
if (target.id > 0) {
tokens.push(target.id);
queue(tokens);
}
}
submit.reset();
break;
case Event.Timeline:
for (let entry of timeline.updates) {
tokens = [entry.time, entry.event];
tokens.push(entry.data.type, entry.data.hash, entry.data.x, entry.data.y, entry.data.reaction, entry.data.context);
queue(tokens, false);
}
timeline.reset();
break;
case Event.Visibility:
let v = visibility.data;
tokens.push(v.visible);
queue(tokens);
baseline.visibility(t, v.visible);
visibility.reset();
break;
case Event.Focus: {
let f = focus.data;
tokens.push(f.focused);
queue(tokens, false);
focus.reset();
break;
}
}
}