crunchit
Version:
Autotrack the events from your users
86 lines (70 loc) • 2.45 kB
JavaScript
const getIntent = require("./intent");
const getElementXPath = require("./xpathGenerator");
let timeoutId = null;
// ! Throttle function
function throttle(func, delay, batchProcessor, browserDetails, ipapi) {
if (timeoutId) {
return;
}
timeoutId = setTimeout(() => {
func(batchProcessor, browserDetails, ipapi);
timeoutId = null;
}, delay);
}
function getScrollPercent() {
const h = document.documentElement,
b = document.body,
st = "scrollTop",
sh = "scrollHeight";
const scrollTop = h[st] || b[st] || 0,
scrollHeight = h[sh] || b[sh] || 0,
clientHeight = h.clientHeight || 0;
const denominator = scrollHeight - clientHeight;
// Check if denominator is zero or not a number
if (denominator === 0 || isNaN(denominator)) {
return 0; // Return 0% if denominator is zero or not valid
}
return (scrollTop / denominator) * 100;
}
function getTopmostElement(el = document.body) {
const excludedTags = ["SCRIPT", "NOSCRIPT", "STYLE", "LINK"];
let queue = [el]; // Start with the body element
while (queue.length > 0) {
let current = queue.shift();
const rect = current.getBoundingClientRect();
// Check if the element is within viewport
if (
rect.top >= 0 &&
rect.bottom <= window.innerHeight &&
!excludedTags.includes(current.tagName)
) {
return current;
}
// If the element is not within viewport or excluded, add its children to the queue
let childrenArray = Array.from(current.children);
queue = queue.concat(childrenArray);
}
// If no valid element found in this subtree, return null
return null;
}
function handleScroll(batchProcessor, browserDetails, ipapi) {
const currentScrollPosition = window.scrollY;
const scrollPercentage = getScrollPercent().toFixed(2);
const topmostElement = getTopmostElement();
let xpath = getElementXPath(topmostElement);
let timestamp = new String(new Date() * 1);
let dataAttributes = Object.assign({}, topmostElement.dataset);
// ! Add an event on the batch
batchProcessor.addAutoCaptureActivity(xpath, {
eventType: "SCROLL",
timestamp,
browserDetails,
dataAttributes,
ipDetails: ipapi,
userIntent: topmostElement
? getIntent(null, "scrolled", topmostElement)?.intent
: "scrolled to " + scrollPercentage,
scrollDetails: { currentScrollPosition, scrollPercentage },
});
}
module.exports = { throttle, handleScroll };