@trustcaptcha/trustcaptcha-frontend
Version:
Frondend library for trustcaptcha
178 lines (177 loc) • 7.79 kB
JavaScript
export class EventTracker {
constructor() {
this.userEvents = [];
this.active = true;
this.eventProperties = {};
// Gruppiere Event-Typen und ihre gemeinsamen Eigenschaften
const mouseEvents = ['click', 'mousedown', 'mouseup', 'mousemove'];
const mouseEventProperties = ['isTrusted', 'timeStamp', 'type', 'altKey', 'bubbles', 'button', 'buttons', 'cancelBubble', 'cancelable', 'clientX', 'clientY', 'composed', 'ctrlKey', 'defaultPrevented', 'detail', 'eventPhase', 'layerX', 'layerY', 'metaKey', 'movementX', 'movementY', 'offsetX', 'offsetY', 'pageX', 'pageY', 'returnValue', 'screenX', 'screenY', 'shiftKey', 'which', 'x', 'y'];
mouseEvents.forEach(eventType => {
this.eventProperties[eventType] = mouseEventProperties;
});
const touchEvents = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];
const touchEventProperties = ['isTrusted', 'timeStamp', 'type', 'altKey', 'bubbles', 'cancelBubble', 'cancelable', 'changedTouches', 'composed', 'ctrlKey', 'defaultPrevented', 'detail', 'eventPhase', 'metaKey', 'returnValue', 'shiftKey', 'targetTouches', 'touches'
];
touchEvents.forEach(eventType => {
this.eventProperties[eventType] = touchEventProperties;
});
const keyboardEvents = ['keydown', 'keyup'];
const keyboardEventProperties = ['isTrusted', 'timeStamp', 'type', 'altKey', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'ctrlKey', 'defaultPrevented', 'detail', 'eventPhase', 'isComposing', 'location', 'metaKey', 'repeat', 'returnValue', 'shiftKey'];
keyboardEvents.forEach(eventType => {
this.eventProperties[eventType] = keyboardEventProperties;
});
const uiEvents = ['resize'];
const uiEventProperties = ['isTrusted', 'timeStamp', 'type', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'eventPhase', 'returnValue'];
uiEvents.forEach(eventType => {
this.eventProperties[eventType] = uiEventProperties;
});
const focusEvents = ['focus', 'blur'];
const focusEventProperties = ['isTrusted', 'timeStamp', 'type', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'defaultPrevented', 'eventPhase', 'returnValue'];
focusEvents.forEach(eventType => {
this.eventProperties[eventType] = focusEventProperties;
});
const clipboardEvents = ['copy', 'paste'];
const clipboardEventProperties = ['isTrusted', 'timeStamp', 'type', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'defaultPrevented', 'eventPhase', 'returnValue', 'clipboardData'];
clipboardEvents.forEach(eventType => {
this.eventProperties[eventType] = clipboardEventProperties;
});
const scrollEvents = ['scroll'];
const scrollEventProperties = ['isTrusted', 'timeStamp', 'type', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'defaultPrevented', 'eventPhase', 'returnValue'];
scrollEvents.forEach(eventType => {
this.eventProperties[eventType] = scrollEventProperties;
});
// Event Listener hinzufügen
mouseEvents.forEach(eventType => {
if (eventType === 'mousemove') {
document.addEventListener(eventType, this.throttle(event => this.saveEvent(event), 1));
}
else {
document.addEventListener(eventType, event => this.saveEvent(event));
}
});
touchEvents.forEach(eventType => {
document.addEventListener(eventType, event => this.saveEvent(event));
});
keyboardEvents.forEach(eventType => {
document.addEventListener(eventType, event => this.saveEvent(event));
});
uiEvents.forEach(eventType => {
window.addEventListener(eventType, event => this.saveEvent(event));
});
scrollEvents.forEach(eventType => {
window.addEventListener(eventType, event => this.saveEvent(event));
});
clipboardEvents.forEach(eventType => {
document.addEventListener(eventType, event => this.saveEvent(event));
});
// Focus und Blur Events für bestimmte Elemente
const selectors = [
'a[href]',
'area[href]',
'button',
'details',
'input:not([type="hidden"]):not([type="radio"]):not([type="checkbox"]):not([disabled])',
'iframe',
'object',
'select:not([disabled])',
'textarea:not([disabled])',
'summary',
'[contenteditable]'
];
selectors.forEach(selector => {
const elements = document.querySelectorAll(selector);
elements.forEach(element => {
focusEvents.forEach(eventType => {
element.addEventListener(eventType, event => this.saveEvent(event));
});
});
});
}
throttle(func, limit) {
let inThrottle;
return function () {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
getEventsAndResetArray() {
const currentEvents = this.userEvents;
this.userEvents = [];
return currentEvents;
}
saveEvent(event) {
if (!this.active) {
return;
}
if (this.userEvents.length >= 25000) {
this.userEvents.shift();
}
const eventType = event.type;
if (this.eventProperties.hasOwnProperty(eventType)) {
const propsToInclude = this.eventProperties[eventType];
const sanitizedEvent = this.pickProperties(event, propsToInclude);
this.userEvents.push(sanitizedEvent);
}
else {
console.log('Unhandled event type:', eventType);
}
}
pickProperties(event, props) {
const safeEvent = {};
props.forEach(key => {
try {
let value = event[key];
if (key === 'clipboardData') {
value = {
files: value.files.length,
items: value.items.length,
types: value.types.length
};
}
else if (key === 'changedTouches' || key === 'targetTouches' || key === 'touches') {
value = this.mapTouchList(value);
}
if (typeof value !== 'function') {
safeEvent[key] = value;
}
}
catch (err) {
// Ignoriere nicht zugängliche Eigenschaften
}
});
return safeEvent;
}
mapTouchList(touches) {
const touchesArray = [];
for (let i = 0; i < touches.length; i++) {
const touch = touches[i];
touchesArray.push({
clientX: touch.clientX,
clientY: touch.clientY,
force: touch.force,
identifier: touch.identifier,
pageX: touch.pageX,
pageY: touch.pageY,
radiusX: touch.radiusX,
radiusY: touch.radiusY,
rotationAngle: touch.rotationAngle,
screenX: touch.screenX,
screenY: touch.screenY,
});
}
return touchesArray;
}
stop() {
this.active = false;
}
reset() {
this.userEvents = [];
this.active = true;
}
}
//# sourceMappingURL=event_tracker.js.map