Skip to content

Commit f568812

Browse files
committed
feat: widget@0.1.45
1 parent ccd00a6 commit f568812

4 files changed

Lines changed: 48 additions & 59 deletions

File tree

widget/build.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const browser = await chromium.launch({ headless: false });
6666
const page = await browser.newPage();
6767

6868
const server = Bun.serve({
69-
port: 3006,
69+
port: 3007,
7070
routes: {
7171
"/": () => {
7272
return new Response(Bun.file("./test.html"));
@@ -104,4 +104,4 @@ const server = Bun.serve({
104104
},
105105
});
106106

107-
page.goto(`http://localhost:3006/`);
107+
page.goto(`http://localhost:3007/`);

widget/src/cap-floating.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

widget/src/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cap.js/widget",
3-
"version": "0.1.44",
3+
"version": "0.1.45",
44
"description": "Client-side widget for Cap, a lightweight, modern open-source CAPTCHA alternative designed using SHA-256 PoW.",
55
"keywords": [
66
"algorithm",

widget/src/src/cap-floating.js

Lines changed: 44 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,5 @@
11
(() => {
2-
const handleClick = (evt, element, capWidget, handlers) => {
3-
const trigger = () => {
4-
handlers.forEach((h) => {
5-
element.addEventListener("click", h);
6-
h.call(element, evt);
7-
});
8-
9-
setTimeout(() => {
10-
element.onclick = null;
11-
handlers.forEach((h) => {
12-
return element.removeEventListener("click", h);
13-
});
14-
element.onclick = (e) => handleClick(e, element, capWidget, handlers);
15-
}, 50);
16-
};
17-
18-
element.onclick = null;
19-
2+
const showWidget = (element, capWidget) => {
203
const offset = parseInt(element.getAttribute("data-cap-floating-offset")) || 8;
214
const position = element.getAttribute("data-cap-floating-position") || "top";
225

@@ -43,12 +26,10 @@
4326
const triggerRect = element.getBoundingClientRect();
4427
const containerRect = (capWidget.offsetParent ?? document.documentElement).getBoundingClientRect();
4528

46-
// Horizontally center the popup under the trigger button.
4729
const centeredLeft = triggerRect.left + (triggerRect.width - capWidget.offsetWidth) / 2;
4830
const clampedLeft = Math.max(2, Math.min(centeredLeft, window.innerWidth - capWidget.offsetWidth));
4931
capWidget.style.left = `${clampedLeft - containerRect.left}px`;
5032

51-
// Place the popup above or below the trigger, clamped to the visible area.
5233
if (position === "top") {
5334
const idealTop = triggerRect.top - capWidget.offsetHeight - offset;
5435
const clampedTop = Math.max(0, idealTop);
@@ -60,24 +41,18 @@
6041
}
6142

6243
capWidget.solve();
44+
};
6345

64-
capWidget.addEventListener("solve", ({ detail }) => {
65-
element.setAttribute("data-cap-token", detail.token);
66-
element.setAttribute("data-cap-progress", "done");
67-
setTimeout(() => {
68-
trigger();
69-
}, 500);
70-
71-
setTimeout(() => {
72-
capWidget.style.transform = "scale(0.98)";
73-
capWidget.style.opacity = "0";
74-
capWidget.style.marginTop = "-4px";
75-
}, 500);
76-
77-
setTimeout(() => {
78-
capWidget.style.display = "none";
79-
}, 700);
80-
});
46+
const hideWidget = (capWidget) => {
47+
setTimeout(() => {
48+
capWidget.style.transform = "scale(0.98)";
49+
capWidget.style.opacity = "0";
50+
capWidget.style.marginTop = "-4px";
51+
}, 500);
52+
53+
setTimeout(() => {
54+
capWidget.style.display = "none";
55+
}, 700);
8156
};
8257

8358
const setupElement = (element) => {
@@ -90,24 +65,38 @@
9065
}
9166

9267
capWidget.style.display = "none";
93-
const handlers = [element.onclick].filter(Boolean);
94-
95-
if (typeof getEventListeners === "function") {
96-
handlers.push(...(getEventListeners(element).click || []).map((l) => l.listener));
97-
}
98-
99-
if (handlers.length) {
100-
element.onclick = null;
101-
handlers.forEach((h) => {
102-
return element.removeEventListener("click", h);
103-
});
104-
}
105-
106-
element.addEventListener("click", (e) => {
107-
e.stopImmediatePropagation();
108-
e.preventDefault();
109-
handleClick(e, element, capWidget, handlers);
110-
});
68+
let bypass = false;
69+
70+
element.addEventListener(
71+
"click",
72+
(e) => {
73+
if (bypass) {
74+
bypass = false;
75+
return;
76+
}
77+
78+
e.stopImmediatePropagation();
79+
e.preventDefault();
80+
81+
showWidget(element, capWidget);
82+
83+
const onSolve = ({ detail }) => {
84+
capWidget.removeEventListener("solve", onSolve);
85+
element.setAttribute("data-cap-token", detail.token);
86+
element.setAttribute("data-cap-progress", "done");
87+
88+
setTimeout(() => {
89+
bypass = true;
90+
element.click();
91+
}, 500);
92+
93+
hideWidget(capWidget);
94+
};
95+
96+
capWidget.addEventListener("solve", onSolve);
97+
},
98+
true,
99+
);
111100
};
112101

113102
const init = (root) => {

0 commit comments

Comments
 (0)