clarity-js
Version:
An analytics library that uses web page interactions to generate aggregated insights
66 lines (54 loc) • 2.01 kB
text/typescript
import { BooleanFlag, Event } from "@clarity-types/data";
import { InputData, InputState, Setting } from "@clarity-types/interaction";
import { bind } from "@src/core/event";
import { schedule } from "@src/core/task";
import { time } from "@src/core/time";
import { clearTimeout, setTimeout } from "@src/core/timeout";
import { get } from "@src/layout/dom";
import encode from "./encode";
import { target } from "@src/layout/target";
let timeout: number = null;
export let state: InputState[] = [];
export function start(): void {
reset();
}
export function observe(root: Node): void {
bind(root, "input", recompute, true);
bind(root, "keydown", enter, true);
}
function recompute(evt: UIEvent): void {
let input = target(evt) as HTMLInputElement;
let value = get(input);
if (input && input.type && value) {
let v = input.value;
let t = input.type;
switch (input.type) {
case "radio":
case "checkbox":
v = input.checked ? "true" : "false";
break;
}
let data: InputData = { target: input, value: v, type: t, trust: evt.isTrusted ? BooleanFlag.True : BooleanFlag.False };
// If last entry in the queue is for the same target node as the current one, remove it so we can later swap it with current data.
if (state.length > 0 && (state[state.length - 1].data.target === data.target)) { state.pop(); }
state.push({ time: time(evt), event: Event.Input, data });
clearTimeout(timeout);
timeout = setTimeout(process, Setting.InputLookAhead, Event.Input);
}
}
function enter(evt: KeyboardEvent): void {
if (evt.key === "Enter" && !evt.repeat && state.length > 0) {
clearTimeout(timeout);
process(Event.Input);
}
}
function process(event: Event): void {
schedule(encode.bind(this, event));
}
export function reset(): void {
state = [];
}
export function stop(): void {
clearTimeout(timeout);
reset();
}