@usewayn/widget
Version:
Client side widget generator for Wayn PoW CAPTCHA.
105 lines (86 loc) • 3.15 kB
JavaScript
(() => {
const handleClick = (evt, element, waynWidget, handlers) => {
const trigger = () => {
handlers.forEach((h) => {
element.addEventListener("click", h);
h.call(element, evt);
});
setTimeout(() => {
element.onclick = null;
handlers.forEach((h) => element.removeEventListener("click", h));
element.onclick = (e) => handleClick(e, element, waynWidget, handlers);
}, 50);
};
element.onclick = null;
const offset = parseInt(element.getAttribute("data-wayn-floating-offset")) || 8;
const position =
element.getAttribute("data-wayn-floating-position") || "top";
const rect = element.getBoundingClientRect();
Object.assign(waynWidget.style, {
display: "block",
position: "absolute",
zIndex: "99999"
});
const centerX = rect.left + (rect.width - waynWidget.offsetWidth) / 2;
const safeX = Math.min(centerX, window.innerWidth - waynWidget.offsetWidth);
if (position === "top") {
waynWidget.style.top = `${Math.max(
window.scrollY,
rect.top - waynWidget.offsetHeight - offset + window.scrollY
)}px`;
} else {
waynWidget.style.top = `${Math.min(
rect.bottom + offset + window.scrollY,
window.innerHeight - waynWidget.offsetHeight + window.scrollY
)}px`;
}
waynWidget.style.left = `${Math.max(safeX, 2)}px`;
waynWidget.solve();
waynWidget.addEventListener("solve", ({ detail }) => {
element.setAttribute("data-wayn-token", detail.token);
element.setAttribute("data-wayn-progress", "done");
setTimeout(() => {
trigger();
}, 500);
setTimeout(() => {
waynWidget.style.display = "none";
}, 700);
});
};
const setupElement = (element) => {
const waynWidgetSelector = element.getAttribute("data-wayn-floating");
if (!waynWidgetSelector) return;
const waynWidget = document.querySelector(waynWidgetSelector);
if (!document.contains(waynWidget) && !waynWidget.solve) {
throw new Error(`[wayn - floating] "${waynWidgetSelector}" doesn't exist or isn't a Wayn widget`);
}
waynWidget.style.display = "none";
const handlers = [element.onclick].filter(Boolean);
if (typeof getEventListeners === "function") {
handlers.push(
...(getEventListeners(element).click || []).map((l) => l.listener)
);
}
if (handlers.length) {
element.onclick = null;
handlers.forEach((h) => element.removeEventListener("click", h));
}
element.addEventListener("click", (e) => {
e.stopImmediatePropagation();
e.preventDefault();
handleClick(e, element, waynWidget, handlers);
});
};
const init = (root) => {
setupElement(root);
root.querySelectorAll("[data-wayn-floating]").forEach(setupElement);
};
init(document.body);
new MutationObserver((mutations) =>
mutations.forEach((mutation) =>
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) init(node);
})
)
).observe(document.body, { childList: true, subtree: true });
})();