@prosopo/client-bundle-example 2.7.0 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/assets/{ProcaptchaWidget-3gKvjeiH.js → ProcaptchaWidget-DrBDhP6X.js} +7 -7
- package/dist/assets/{ProcaptchaWidget-D6-M7iAv.js → ProcaptchaWidget-rAM-9Rap.js} +4 -4
- package/dist/assets/{asU8a-DCECA0Qe.js → asU8a-CJdNkNEq.js} +1 -1
- package/dist/assets/{bip39-BQoZog_M.js → bip39-Du2cANEV.js} +2 -2
- package/dist/assets/captcha-BhkVCEXM.css +1 -0
- package/dist/assets/{captchaComponentProvider-BW2eXmc3.js → captchaComponentProvider-DmV1WTrT.js} +4 -4
- package/dist/assets/{captchaRenderer-B_MgGzr9.js → captchaRenderer-RIsSZXCC.js} +2 -2
- package/dist/assets/{emotion-element-5486c51c.browser.esm-CCAJ8JId.js → emotion-element-5486c51c.browser.esm-C3u8NMUC.js} +127 -125
- package/dist/assets/frictionless-explicit-C_AXK63E.js +1 -0
- package/dist/assets/frictionless-implicit-Dq_sNGRK.js +1 -0
- package/dist/assets/{hash-BR0YLxPF.js → hash-_rWungeW.js} +1 -1
- package/dist/assets/image-explicit-DQvfVB7-.js +4 -0
- package/dist/assets/image-implicit-Bwa9QJO5.js +1 -0
- package/dist/assets/{index-WqEmiYQ_.js → index-BVr9fC_3.js} +4 -4
- package/dist/assets/{index-BYUYvvuq.js → index-Cu5oL_7b.js} +4 -4
- package/dist/assets/index-Dpt_5E72.js +1 -0
- package/dist/assets/{index-BCjHZ8o6.js → index-DxIFpl6U.js} +1 -1
- package/dist/assets/{index-2or4-1WF.js → index-Wgw2GQWq.js} +2 -2
- package/dist/assets/invisible-frictionless-explicit-DugBtRe4.js +4 -0
- package/dist/assets/invisible-frictionless-implicit-DYYos8W9.js +1 -0
- package/dist/assets/invisible-image-explicit-C5Z4gSb1.js +4 -0
- package/dist/assets/invisible-image-implicit-DfNFNlFj.js +1 -0
- package/dist/assets/invisible-pow-explicit-DjqGWFUb.js +4 -0
- package/dist/assets/invisible-pow-implicit-BRXL14FH.js +4 -0
- package/dist/assets/pow-explicit-BexxbnHM.js +4 -0
- package/dist/assets/pow-implicit-Dpt_5E72.js +1 -0
- package/dist/assets/procaptcha.bundle.js +1 -1
- package/dist/assets/{useTranslation-BPbGzrhj.js → useTranslation-CJplXtqb.js} +1 -1
- package/dist/frictionless-explicit.html +875 -0
- package/dist/frictionless-implicit.html +874 -0
- package/dist/image-explicit.html +877 -0
- package/dist/index.html +575 -74
- package/dist/invisible-frictionless-explicit.html +626 -283
- package/dist/invisible-frictionless-implicit.html +631 -173
- package/dist/invisible-image-explicit.html +627 -284
- package/dist/invisible-image-implicit.html +631 -173
- package/dist/invisible-pow-explicit.html +627 -284
- package/dist/invisible-pow-implicit.html +629 -177
- package/dist/plugins/explanation-injector.ts +250 -0
- package/dist/plugins/form-filler-injector.ts +233 -0
- package/dist/plugins/navigation-injector.ts +237 -89
- package/dist/plugins/status-log-injector.ts +199 -0
- package/dist/pow-explicit.html +877 -0
- package/dist/pow-implicit.html +881 -0
- package/package.json +1 -1
- package/vite.config.ts +32 -3
- package/dist/assets/frictionless-ZgzyuneX.js +0 -1
- package/dist/assets/index-BWsu-rGU.js +0 -1
- package/dist/assets/invisible-frictionless-explicit-DgCaJtPg.js +0 -1
- package/dist/assets/invisible-image-explicit-DgCaJtPg.js +0 -1
- package/dist/assets/invisible-pow-explicit-DgCaJtPg.js +0 -1
- package/dist/assets/pow-BW3QYcgP.js +0 -1
- package/dist/frictionless.html +0 -343
- package/dist/pow.html +0 -323
- /package/dist/assets/{modulepreload-polyfill-B5Qt9EMX.js → captcha-ByKnSsbG.js} +0 -0
|
@@ -1,71 +1,9 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
<script type="module" src="
|
|
7
|
-
<style>
|
|
8
|
-
body {
|
|
9
|
-
font-family: Arial, sans-serif;
|
|
10
|
-
margin: 0 auto;
|
|
11
|
-
padding: 20px;
|
|
12
|
-
}
|
|
13
|
-
form {
|
|
14
|
-
border: 1px solid #ddd;
|
|
15
|
-
padding: 20px;
|
|
16
|
-
border-radius: 5px;
|
|
17
|
-
}
|
|
18
|
-
label {
|
|
19
|
-
display: block;
|
|
20
|
-
margin-bottom: 5px;
|
|
21
|
-
}
|
|
22
|
-
input[type="text"],
|
|
23
|
-
input[type="email"] {
|
|
24
|
-
width: 100%;
|
|
25
|
-
padding: 8px;
|
|
26
|
-
margin-bottom: 15px;
|
|
27
|
-
border: 1px solid #ccc;
|
|
28
|
-
border-radius: 4px;
|
|
29
|
-
}
|
|
30
|
-
button {
|
|
31
|
-
background-color: #4CAF50;
|
|
32
|
-
color: white;
|
|
33
|
-
padding: 10px 15px;
|
|
34
|
-
border: none;
|
|
35
|
-
border-radius: 4px;
|
|
36
|
-
cursor: pointer;
|
|
37
|
-
}
|
|
38
|
-
button:hover {
|
|
39
|
-
background-color: #45a049;
|
|
40
|
-
}
|
|
41
|
-
#result {
|
|
42
|
-
margin-top: 15px;
|
|
43
|
-
padding: 10px;
|
|
44
|
-
border: 1px solid #ddd;
|
|
45
|
-
border-radius: 4px;
|
|
46
|
-
background-color: #f9f9f9;
|
|
47
|
-
display: none;
|
|
48
|
-
}
|
|
49
|
-
</style>
|
|
50
|
-
<script type="text/javascript">
|
|
51
|
-
function onSubmit(token) {
|
|
52
|
-
console.log('Procaptcha verified, token: ' + token);
|
|
53
|
-
|
|
54
|
-
// Get form values
|
|
55
|
-
const name = document.getElementById('name').value;
|
|
56
|
-
const email = document.getElementById('email').value;
|
|
57
|
-
|
|
58
|
-
const resultElement = document.getElementById('result');
|
|
59
|
-
resultElement.textContent = `Form submitted with:
|
|
60
|
-
- Name: ${name}
|
|
61
|
-
- Email: ${email}
|
|
62
|
-
- Procaptcha verified: Yes`;
|
|
63
|
-
resultElement.style.display = 'block';
|
|
64
|
-
|
|
65
|
-
// Prevent actual form submission
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
</script>
|
|
4
|
+
<link href="https://cdn.muicss.com/mui-0.10.3/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
|
5
|
+
<title>Procaptcha demo: Invisible image - Implicit Rendering</title>
|
|
6
|
+
<script id="procaptchaScript" type="module" src="http://localhost:9269/procaptcha.bundle.js" async defer></script>
|
|
69
7
|
|
|
70
8
|
<style>
|
|
71
9
|
.nav-topbar {
|
|
@@ -74,60 +12,64 @@
|
|
|
74
12
|
margin-bottom: 20px;
|
|
75
13
|
transition: all 0.3s ease;
|
|
76
14
|
overflow: hidden;
|
|
77
|
-
max-height: 500px;
|
|
15
|
+
max-height: 500px;
|
|
78
16
|
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
|
|
17
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
79
18
|
}
|
|
80
19
|
.nav-topbar.collapsed {
|
|
81
|
-
max-height:
|
|
20
|
+
max-height: 60px;
|
|
82
21
|
}
|
|
83
22
|
.nav-container {
|
|
84
23
|
max-width: 1200px;
|
|
85
24
|
margin: 0 auto;
|
|
86
|
-
padding: 0
|
|
25
|
+
padding: 0 20px;
|
|
87
26
|
position: relative;
|
|
88
27
|
}
|
|
89
28
|
.nav-header {
|
|
90
29
|
display: flex;
|
|
91
30
|
justify-content: space-between;
|
|
92
31
|
align-items: center;
|
|
93
|
-
padding:
|
|
32
|
+
padding: 12px 0;
|
|
94
33
|
position: relative;
|
|
95
34
|
z-index: 20;
|
|
96
35
|
}
|
|
97
36
|
.nav-title {
|
|
98
37
|
color: white;
|
|
99
|
-
font-size:
|
|
100
|
-
font-weight:
|
|
38
|
+
font-size: 1.25rem;
|
|
39
|
+
font-weight: 600;
|
|
101
40
|
margin: 0;
|
|
102
41
|
display: flex;
|
|
103
42
|
align-items: center;
|
|
43
|
+
gap: 8px;
|
|
104
44
|
}
|
|
105
45
|
.nav-title-text {
|
|
106
|
-
margin-right:
|
|
46
|
+
margin-right: 8px;
|
|
107
47
|
}
|
|
108
48
|
.nav-title-hint {
|
|
109
|
-
font-size:
|
|
49
|
+
font-size: 0.875rem;
|
|
110
50
|
font-weight: normal;
|
|
111
51
|
opacity: 0;
|
|
112
52
|
transition: opacity 0.3s ease;
|
|
53
|
+
color: rgba(255,255,255,0.8);
|
|
113
54
|
}
|
|
114
55
|
.collapsed .nav-title-hint {
|
|
115
56
|
opacity: 0.8;
|
|
116
57
|
}
|
|
117
58
|
.nav-toggle {
|
|
118
|
-
background-color: rgba(
|
|
59
|
+
background-color: rgba(255,255,255,0.1);
|
|
119
60
|
color: white;
|
|
120
61
|
border: none;
|
|
121
|
-
padding:
|
|
62
|
+
padding: 8px 12px;
|
|
122
63
|
cursor: pointer;
|
|
123
|
-
border-radius:
|
|
64
|
+
border-radius: 6px;
|
|
124
65
|
z-index: 10;
|
|
125
66
|
display: flex;
|
|
126
67
|
align-items: center;
|
|
127
68
|
justify-content: center;
|
|
69
|
+
transition: background-color 0.2s ease;
|
|
128
70
|
}
|
|
129
71
|
.nav-toggle:hover {
|
|
130
|
-
background-color: rgba(
|
|
72
|
+
background-color: rgba(255,255,255,0.2);
|
|
131
73
|
}
|
|
132
74
|
.nav-toggle-icon {
|
|
133
75
|
width: 24px;
|
|
@@ -154,29 +96,42 @@
|
|
|
154
96
|
opacity: 1;
|
|
155
97
|
}
|
|
156
98
|
.nav-content {
|
|
157
|
-
padding: 0 0
|
|
99
|
+
padding: 0 0 20px 0;
|
|
158
100
|
transition: opacity 0.3s ease;
|
|
159
101
|
}
|
|
160
102
|
.collapsed .nav-content {
|
|
161
103
|
opacity: 0;
|
|
162
104
|
}
|
|
163
|
-
.nav-
|
|
105
|
+
.nav-sections {
|
|
164
106
|
display: flex;
|
|
165
107
|
flex-wrap: wrap;
|
|
166
|
-
|
|
108
|
+
gap: 20px;
|
|
167
109
|
}
|
|
168
|
-
.nav-
|
|
110
|
+
.nav-section {
|
|
169
111
|
flex: 1;
|
|
170
|
-
min-width:
|
|
171
|
-
|
|
172
|
-
|
|
112
|
+
min-width: 280px;
|
|
113
|
+
}
|
|
114
|
+
.nav-section h3 {
|
|
115
|
+
color: white;
|
|
116
|
+
font-size: 1rem;
|
|
117
|
+
font-weight: 600;
|
|
118
|
+
margin: 0 0 12px 0;
|
|
119
|
+
padding-bottom: 8px;
|
|
120
|
+
border-bottom: 1px solid rgba(255,255,255,0.2);
|
|
121
|
+
}
|
|
122
|
+
.nav-group {
|
|
123
|
+
background: rgba(255,255,255,0.1);
|
|
124
|
+
border-radius: 8px;
|
|
125
|
+
padding: 12px;
|
|
126
|
+
margin-bottom: 12px;
|
|
173
127
|
}
|
|
174
128
|
.nav-group-title {
|
|
175
|
-
color: rgba(255,255,255,0.
|
|
176
|
-
font-size: 0.
|
|
177
|
-
margin: 0 0 5px 0;
|
|
178
|
-
text-transform: uppercase;
|
|
129
|
+
color: rgba(255,255,255,0.9);
|
|
130
|
+
font-size: 0.875rem;
|
|
179
131
|
font-weight: 500;
|
|
132
|
+
margin: 0 0 8px 0;
|
|
133
|
+
text-transform: uppercase;
|
|
134
|
+
letter-spacing: 0.5px;
|
|
180
135
|
}
|
|
181
136
|
.nav-group-links {
|
|
182
137
|
list-style: none;
|
|
@@ -184,36 +139,348 @@
|
|
|
184
139
|
padding: 0;
|
|
185
140
|
}
|
|
186
141
|
.nav-group-links li {
|
|
187
|
-
margin:
|
|
142
|
+
margin: 6px 0;
|
|
188
143
|
}
|
|
189
144
|
.nav-group-links a {
|
|
190
145
|
color: white;
|
|
191
146
|
text-decoration: none;
|
|
192
|
-
font-weight:
|
|
193
|
-
padding:
|
|
147
|
+
font-weight: 500;
|
|
148
|
+
padding: 6px 8px;
|
|
194
149
|
display: inline-block;
|
|
150
|
+
border-radius: 4px;
|
|
151
|
+
transition: background-color 0.2s ease;
|
|
195
152
|
}
|
|
196
153
|
.nav-group-links a:hover {
|
|
197
|
-
|
|
154
|
+
background-color: rgba(255,255,255,0.2);
|
|
198
155
|
}
|
|
199
156
|
.nav-group-links .active {
|
|
200
|
-
|
|
157
|
+
background-color: rgba(255,255,255,0.2);
|
|
158
|
+
font-weight: 600;
|
|
201
159
|
}
|
|
202
160
|
.nav-group-links .disabled {
|
|
203
161
|
color: rgba(255,255,255,0.5);
|
|
204
162
|
cursor: not-allowed;
|
|
163
|
+
opacity: 0.7;
|
|
205
164
|
}
|
|
206
165
|
|
|
207
166
|
@media (max-width: 768px) {
|
|
208
|
-
.nav-
|
|
209
|
-
|
|
167
|
+
.nav-container {
|
|
168
|
+
padding: 0 16px;
|
|
169
|
+
}
|
|
170
|
+
.nav-title {
|
|
171
|
+
font-size: 1.125rem;
|
|
210
172
|
}
|
|
211
173
|
.nav-title-hint {
|
|
212
174
|
display: none;
|
|
213
175
|
}
|
|
176
|
+
.nav-sections {
|
|
177
|
+
flex-direction: column;
|
|
178
|
+
gap: 16px;
|
|
179
|
+
}
|
|
180
|
+
.nav-section {
|
|
181
|
+
min-width: 100%;
|
|
182
|
+
}
|
|
183
|
+
.nav-section h3 {
|
|
184
|
+
font-size: 0.875rem;
|
|
185
|
+
}
|
|
186
|
+
.nav-group {
|
|
187
|
+
padding: 10px;
|
|
188
|
+
}
|
|
189
|
+
.nav-group-title {
|
|
190
|
+
font-size: 0.8125rem;
|
|
191
|
+
}
|
|
192
|
+
.nav-group-links a {
|
|
193
|
+
padding: 8px 10px;
|
|
194
|
+
width: 100%;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@media (max-width: 480px) {
|
|
199
|
+
.nav-topbar {
|
|
200
|
+
max-height: 60px;
|
|
201
|
+
}
|
|
202
|
+
.nav-topbar.collapsed {
|
|
203
|
+
max-height: 60px;
|
|
204
|
+
}
|
|
205
|
+
.nav-title {
|
|
206
|
+
font-size: 1rem;
|
|
207
|
+
}
|
|
208
|
+
.nav-toggle {
|
|
209
|
+
padding: 6px 10px;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.nav-group-dropdown {
|
|
214
|
+
position: relative;
|
|
215
|
+
display: inline-block;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.nav-group-dropdown-btn {
|
|
219
|
+
background: none;
|
|
220
|
+
border: none;
|
|
221
|
+
color: white;
|
|
222
|
+
font-weight: 500;
|
|
223
|
+
padding: 6px 8px;
|
|
224
|
+
cursor: pointer;
|
|
225
|
+
display: flex;
|
|
226
|
+
align-items: center;
|
|
227
|
+
gap: 4px;
|
|
228
|
+
border-radius: 4px;
|
|
229
|
+
transition: background-color 0.2s ease;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.nav-group-dropdown-btn:hover {
|
|
233
|
+
background-color: rgba(255,255,255,0.2);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.nav-group-dropdown-btn svg {
|
|
237
|
+
width: 16px;
|
|
238
|
+
height: 16px;
|
|
239
|
+
transition: transform 0.2s ease;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.nav-group-dropdown-btn.open svg {
|
|
243
|
+
transform: rotate(180deg);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.nav-group-dropdown-content {
|
|
247
|
+
display: none;
|
|
248
|
+
position: absolute;
|
|
249
|
+
background-color: rgba(33, 150, 243, 0.95);
|
|
250
|
+
min-width: 160px;
|
|
251
|
+
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
|
|
252
|
+
z-index: 1;
|
|
253
|
+
border-radius: 4px;
|
|
254
|
+
padding: 8px 0;
|
|
255
|
+
margin-top: 4px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.nav-group-dropdown-btn.open + .nav-group-dropdown-content {
|
|
259
|
+
display: block;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.nav-group-dropdown-content a {
|
|
263
|
+
color: white;
|
|
264
|
+
padding: 8px 16px;
|
|
265
|
+
text-decoration: none;
|
|
266
|
+
display: block;
|
|
267
|
+
transition: background-color 0.2s ease;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.nav-group-dropdown-content a:hover {
|
|
271
|
+
background-color: rgba(255,255,255,0.2);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.nav-group-dropdown-content a.active {
|
|
275
|
+
background-color: rgba(255,255,255,0.2);
|
|
276
|
+
font-weight: 600;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@media (max-width: 768px) {
|
|
280
|
+
.nav-group-dropdown-content {
|
|
281
|
+
position: static;
|
|
282
|
+
box-shadow: none;
|
|
283
|
+
background-color: rgba(255,255,255,0.1);
|
|
284
|
+
margin-top: 8px;
|
|
285
|
+
}
|
|
214
286
|
}
|
|
215
287
|
</style>
|
|
216
|
-
<script
|
|
288
|
+
<script type="module" crossorigin src="/assets/invisible-image-implicit-DfNFNlFj.js"></script>
|
|
289
|
+
<link rel="modulepreload" crossorigin href="/assets/captcha-ByKnSsbG.js">
|
|
290
|
+
<link rel="stylesheet" crossorigin href="/assets/captcha-BhkVCEXM.css">
|
|
291
|
+
|
|
292
|
+
<style>
|
|
293
|
+
.form-filler-button {
|
|
294
|
+
position: fixed;
|
|
295
|
+
bottom: 20px;
|
|
296
|
+
right: 20px;
|
|
297
|
+
background-color: #2196F3;
|
|
298
|
+
color: white;
|
|
299
|
+
border: none;
|
|
300
|
+
border-radius: 30px;
|
|
301
|
+
padding: 12px 20px;
|
|
302
|
+
font-size: 14px;
|
|
303
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
304
|
+
cursor: pointer;
|
|
305
|
+
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
|
306
|
+
z-index: 9999;
|
|
307
|
+
display: flex;
|
|
308
|
+
align-items: center;
|
|
309
|
+
gap: 8px;
|
|
310
|
+
transition: all 0.2s ease;
|
|
311
|
+
outline: none;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.form-filler-button:hover {
|
|
315
|
+
background-color: #1976D2;
|
|
316
|
+
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.25);
|
|
317
|
+
transform: translateY(-2px);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.form-filler-button:active {
|
|
321
|
+
transform: translateY(1px);
|
|
322
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.form-filler-button svg {
|
|
326
|
+
width: 18px;
|
|
327
|
+
height: 18px;
|
|
328
|
+
fill: white;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.form-filler-button span {
|
|
332
|
+
font-weight: 500;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@media (max-width: 768px) {
|
|
336
|
+
.form-filler-button {
|
|
337
|
+
bottom: 15px;
|
|
338
|
+
right: 15px;
|
|
339
|
+
padding: 10px 15px;
|
|
340
|
+
font-size: 12px;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.form-filler-button svg {
|
|
344
|
+
width: 14px;
|
|
345
|
+
height: 14px;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
</style>
|
|
349
|
+
|
|
350
|
+
<style>
|
|
351
|
+
.captcha-status {
|
|
352
|
+
margin-top: 20px;
|
|
353
|
+
padding: 15px;
|
|
354
|
+
background-color: #f0f8ff;
|
|
355
|
+
border: 2px solid #2196F3;
|
|
356
|
+
border-radius: 5px;
|
|
357
|
+
font-family: monospace;
|
|
358
|
+
font-size: 14px;
|
|
359
|
+
}
|
|
360
|
+
.status-item {
|
|
361
|
+
margin: 5px 0;
|
|
362
|
+
padding: 5px;
|
|
363
|
+
}
|
|
364
|
+
.status-success {
|
|
365
|
+
color: #4CAF50;
|
|
366
|
+
font-weight: bold;
|
|
367
|
+
}
|
|
368
|
+
.status-error {
|
|
369
|
+
color: #F44336;
|
|
370
|
+
font-weight: bold;
|
|
371
|
+
}
|
|
372
|
+
.status-info {
|
|
373
|
+
color: #2196F3;
|
|
374
|
+
}
|
|
375
|
+
.status-warning {
|
|
376
|
+
color: #FF9800;
|
|
377
|
+
}
|
|
378
|
+
.status-title {
|
|
379
|
+
font-weight: bold;
|
|
380
|
+
margin-bottom: 10px;
|
|
381
|
+
border-bottom: 1px solid #2196F3;
|
|
382
|
+
padding-bottom: 5px;
|
|
383
|
+
}
|
|
384
|
+
.console-output {
|
|
385
|
+
margin-top: 20px;
|
|
386
|
+
padding: 10px;
|
|
387
|
+
background-color: #f5f5f5;
|
|
388
|
+
border: 1px solid #ddd;
|
|
389
|
+
border-radius: 4px;
|
|
390
|
+
font-family: monospace;
|
|
391
|
+
white-space: pre-wrap;
|
|
392
|
+
max-height: 200px;
|
|
393
|
+
overflow-y: auto;
|
|
394
|
+
}
|
|
395
|
+
</style>
|
|
396
|
+
|
|
397
|
+
<script type="module">
|
|
398
|
+
// Function to update CAPTCHA status display
|
|
399
|
+
function updateCaptchaStatus(message, type = 'info') {
|
|
400
|
+
const statusContainer = document.getElementById('captcha-status');
|
|
401
|
+
if (!statusContainer) return;
|
|
402
|
+
|
|
403
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
404
|
+
const statusItem = document.createElement('div');
|
|
405
|
+
statusItem.className = `status-item status-${type}`;
|
|
406
|
+
statusItem.innerHTML = `[${timestamp}] ${message}`;
|
|
407
|
+
statusContainer.appendChild(statusItem);
|
|
408
|
+
|
|
409
|
+
// Also log to console
|
|
410
|
+
console.log(`CAPTCHA Status: ${message}`);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Make updateCaptchaStatus available globally
|
|
414
|
+
window.updateCaptchaStatus = updateCaptchaStatus;
|
|
415
|
+
|
|
416
|
+
// Override the original callbacks with enhanced versions that use status logging
|
|
417
|
+
const originalOnCaptchaFailed = window.onCaptchaFailed;
|
|
418
|
+
window.onCaptchaFailed = function() {
|
|
419
|
+
updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
|
|
420
|
+
if (originalOnCaptchaFailed) originalOnCaptchaFailed();
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const originalOnCaptchaVerified = window.onCaptchaVerified;
|
|
424
|
+
window.onCaptchaVerified = function(output) {
|
|
425
|
+
updateCaptchaStatus('Challenge passed successfully!', 'success');
|
|
426
|
+
updateCaptchaStatus(`Token generated: ${output.substring(0, 15)}...`, 'success');
|
|
427
|
+
if (originalOnCaptchaVerified) originalOnCaptchaVerified(output);
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
const originalOnActionHandler = window.onActionHandler;
|
|
431
|
+
window.onActionHandler = function() {
|
|
432
|
+
const procaptchaElements = document.getElementsByName('procaptcha-response');
|
|
433
|
+
|
|
434
|
+
if (!procaptchaElements.length) {
|
|
435
|
+
updateCaptchaStatus('Error: No CAPTCHA response token found', 'error');
|
|
436
|
+
alert("Must complete captcha");
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
updateCaptchaStatus('Form submission initiated with valid CAPTCHA token', 'info');
|
|
441
|
+
if (originalOnActionHandler) originalOnActionHandler();
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
445
|
+
updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
|
|
446
|
+
|
|
447
|
+
// Monitor DOM for CAPTCHA initialization
|
|
448
|
+
const observer = new MutationObserver((mutations) => {
|
|
449
|
+
mutations.forEach((mutation) => {
|
|
450
|
+
if (mutation.addedNodes.length) {
|
|
451
|
+
for (let i = 0; i < mutation.addedNodes.length; i++) {
|
|
452
|
+
const node = mutation.addedNodes[i];
|
|
453
|
+
if (node.classList && (node.classList.contains('procaptcha') ||
|
|
454
|
+
node.querySelector && node.querySelector('.procaptcha'))) {
|
|
455
|
+
updateCaptchaStatus('CAPTCHA DOM elements initialized', 'info');
|
|
456
|
+
observer.disconnect();
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
// Create a method to show CAPTCHA execution events
|
|
468
|
+
document.addEventListener('procaptcha:execute', function(e) {
|
|
469
|
+
// Determine captcha type from the page URL
|
|
470
|
+
const url = window.location.pathname;
|
|
471
|
+
const isFrictionless = url.includes('frictionless');
|
|
472
|
+
const isImage = url.includes('image');
|
|
473
|
+
const isPow = url.includes('pow');
|
|
474
|
+
|
|
475
|
+
let captchaType = 'unknown';
|
|
476
|
+
if (isFrictionless) captchaType = 'frictionless';
|
|
477
|
+
else if (isImage) captchaType = 'image';
|
|
478
|
+
else if (isPow) captchaType = 'pow';
|
|
479
|
+
|
|
480
|
+
updateCaptchaStatus(`CAPTCHA execution started: type=${captchaType}`, 'info');
|
|
481
|
+
updateCaptchaStatus(`Container: ${e.detail.containerId}, timestamp: ${new Date(e.detail.timestamp).toLocaleTimeString()}`, 'info');
|
|
482
|
+
});
|
|
483
|
+
</script>
|
|
217
484
|
</head>
|
|
218
485
|
<body>
|
|
219
486
|
|
|
@@ -236,36 +503,36 @@
|
|
|
236
503
|
</button>
|
|
237
504
|
</div>
|
|
238
505
|
<div class="nav-content">
|
|
239
|
-
<div class="nav-
|
|
506
|
+
<div class="nav-sections">
|
|
240
507
|
|
|
241
508
|
<div class="nav-section">
|
|
242
|
-
<h3
|
|
509
|
+
<h3>Standard Captchas</h3>
|
|
243
510
|
<div class="nav-row">
|
|
244
511
|
|
|
245
512
|
<div class="nav-group">
|
|
246
513
|
<div class="nav-group-title">Image</div>
|
|
247
|
-
<
|
|
248
|
-
<
|
|
249
|
-
<
|
|
250
|
-
</
|
|
514
|
+
<div class="nav-group-links">
|
|
515
|
+
<a href="image-implicit.html">Implicit</a>
|
|
516
|
+
<a href="image-explicit.html">Explicit</a>
|
|
517
|
+
</div>
|
|
251
518
|
</div>
|
|
252
519
|
|
|
253
520
|
|
|
254
521
|
<div class="nav-group">
|
|
255
522
|
<div class="nav-group-title">Pow</div>
|
|
256
|
-
<
|
|
257
|
-
<
|
|
258
|
-
<
|
|
259
|
-
</
|
|
523
|
+
<div class="nav-group-links">
|
|
524
|
+
<a href="pow-implicit.html">Implicit</a>
|
|
525
|
+
<a href="pow-explicit.html">Explicit</a>
|
|
526
|
+
</div>
|
|
260
527
|
</div>
|
|
261
528
|
|
|
262
529
|
|
|
263
530
|
<div class="nav-group">
|
|
264
531
|
<div class="nav-group-title">Frictionless</div>
|
|
265
|
-
<
|
|
266
|
-
<
|
|
267
|
-
<
|
|
268
|
-
</
|
|
532
|
+
<div class="nav-group-links">
|
|
533
|
+
<a href="frictionless-implicit.html">Implicit</a>
|
|
534
|
+
<a href="frictionless-explicit.html">Explicit</a>
|
|
535
|
+
</div>
|
|
269
536
|
</div>
|
|
270
537
|
|
|
271
538
|
</div>
|
|
@@ -273,33 +540,33 @@
|
|
|
273
540
|
|
|
274
541
|
|
|
275
542
|
<div class="nav-section">
|
|
276
|
-
<h3
|
|
543
|
+
<h3>Invisible Captchas</h3>
|
|
277
544
|
<div class="nav-row">
|
|
278
545
|
|
|
279
546
|
<div class="nav-group">
|
|
280
547
|
<div class="nav-group-title">Image</div>
|
|
281
|
-
<
|
|
282
|
-
<
|
|
283
|
-
<
|
|
284
|
-
</
|
|
548
|
+
<div class="nav-group-links">
|
|
549
|
+
<a href="invisible-image-implicit.html" class="active">Implicit</a>
|
|
550
|
+
<a href="invisible-image-explicit.html">Explicit</a>
|
|
551
|
+
</div>
|
|
285
552
|
</div>
|
|
286
553
|
|
|
287
554
|
|
|
288
555
|
<div class="nav-group">
|
|
289
556
|
<div class="nav-group-title">Pow</div>
|
|
290
|
-
<
|
|
291
|
-
<
|
|
292
|
-
<
|
|
293
|
-
</
|
|
557
|
+
<div class="nav-group-links">
|
|
558
|
+
<a href="invisible-pow-implicit.html">Implicit</a>
|
|
559
|
+
<a href="invisible-pow-explicit.html">Explicit</a>
|
|
560
|
+
</div>
|
|
294
561
|
</div>
|
|
295
562
|
|
|
296
563
|
|
|
297
564
|
<div class="nav-group">
|
|
298
565
|
<div class="nav-group-title">Frictionless</div>
|
|
299
|
-
<
|
|
300
|
-
<
|
|
301
|
-
<
|
|
302
|
-
</
|
|
566
|
+
<div class="nav-group-links">
|
|
567
|
+
<a href="invisible-frictionless-implicit.html">Implicit</a>
|
|
568
|
+
<a href="invisible-frictionless-explicit.html">Explicit</a>
|
|
569
|
+
</div>
|
|
303
570
|
</div>
|
|
304
571
|
|
|
305
572
|
</div>
|
|
@@ -310,62 +577,64 @@
|
|
|
310
577
|
</div>
|
|
311
578
|
</div>
|
|
312
579
|
|
|
313
|
-
|
|
314
|
-
|
|
580
|
+
|
|
581
|
+
<div class="mui-container">
|
|
582
|
+
<h1>Invisible image CAPTCHA - Implicit Rendering</h1>
|
|
583
|
+
<p>This example demonstrates how to use Procaptcha in invisible image mode with implicit rendering directly on a button.</p>
|
|
584
|
+
|
|
585
|
+
<!-- CAPTCHA Status Display will be injected by the status-log-injector plugin -->
|
|
315
586
|
|
|
316
|
-
<form
|
|
317
|
-
<
|
|
318
|
-
|
|
319
|
-
<
|
|
587
|
+
<form action="undefined/signup" method="POST" class="mui-form">
|
|
588
|
+
<h2>Example Login Form</h2>
|
|
589
|
+
<div class="mui-textfield mui-textfield--float-label">
|
|
590
|
+
<label for="name">Name</label>
|
|
591
|
+
<input id="name" type="text" name="name" required/>
|
|
320
592
|
</div>
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
<
|
|
324
|
-
<input type="email" id="email" name="email" placeholder="Your email" required />
|
|
593
|
+
<div class="mui-textfield mui-textfield--float-label">
|
|
594
|
+
<label for="email">Email Address</label>
|
|
595
|
+
<input id="email" type="email" name="email" required/>
|
|
325
596
|
</div>
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
597
|
+
<div class="mui-textfield mui-textfield--float-label">
|
|
598
|
+
<label for="password">Password</label>
|
|
599
|
+
<input id="password" type="password" name="password" required/>
|
|
600
|
+
</div>
|
|
601
|
+
<div class="mui-textfield mui-textfield--float-label">
|
|
602
|
+
<!-- The div here was empty, we don't need it for invisible mode -->
|
|
603
|
+
</div>
|
|
604
|
+
<div id="messageContainer" style="display: none; color: black;"><span id="message"></span></div>
|
|
329
605
|
<button
|
|
330
|
-
|
|
606
|
+
type="button"
|
|
607
|
+
class="mui-btn mui-btn--raised procaptcha"
|
|
331
608
|
data-sitekey="undefined"
|
|
332
|
-
data-callback="
|
|
333
|
-
data-
|
|
609
|
+
data-callback="onActionHandler"
|
|
610
|
+
data-failed-callback="onCaptchaFailed"
|
|
611
|
+
data-captcha-type="image"
|
|
612
|
+
data-size="invisible"
|
|
613
|
+
data-cy="submit-button">
|
|
334
614
|
Submit
|
|
335
615
|
</button>
|
|
336
616
|
</form>
|
|
617
|
+
<!-- CAPTCHA Status Display -->
|
|
618
|
+
<div id="captcha-status" class="captcha-status">
|
|
619
|
+
<div class="status-title">CAPTCHA Status Log</div>
|
|
620
|
+
</div>
|
|
621
|
+
|
|
622
|
+
<!-- Console output display area -->
|
|
623
|
+
<div id="console-output" class="console-output" style="display: none;"></div>
|
|
624
|
+
|
|
337
625
|
|
|
338
|
-
|
|
626
|
+
<!-- Console output display area -->
|
|
627
|
+
<div id="console-output" class="console-output" style="display: none;"></div>
|
|
339
628
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
<p>This example demonstrates how to use Procaptcha in invisible image mode with implicit rendering:</p>
|
|
343
|
-
<ol>
|
|
344
|
-
<li>Include the Procaptcha script in the head of your document</li>
|
|
345
|
-
<li>Add the <code>p-procaptcha</code> class to your submit button</li>
|
|
346
|
-
<li>Add the <code>data-sitekey</code> attribute with your site key</li>
|
|
347
|
-
<li>Add the <code>data-callback</code> attribute with the name of your callback function</li>
|
|
348
|
-
<li>The CAPTCHA verification happens invisibly when the user clicks the button</li>
|
|
349
|
-
</ol>
|
|
350
|
-
<p>The key elements are:</p>
|
|
351
|
-
<pre>
|
|
352
|
-
<script type="module" src="./assets/procaptcha.bundle.js" async defer></script>
|
|
353
|
-
|
|
354
|
-
<button
|
|
355
|
-
class="p-procaptcha"
|
|
356
|
-
data-sitekey="undefined"
|
|
357
|
-
data-callback="onSubmit"
|
|
358
|
-
data-captcha-type="image">
|
|
359
|
-
Submit
|
|
360
|
-
</button>
|
|
361
|
-
</pre>
|
|
362
|
-
</div>
|
|
629
|
+
<!-- Explanation will be injected by the explanation-injector plugin -->
|
|
630
|
+
</div>
|
|
363
631
|
|
|
364
632
|
<script>
|
|
365
633
|
document.addEventListener('DOMContentLoaded', function() {
|
|
366
634
|
const toggleBtn = document.getElementById('nav-toggle');
|
|
367
635
|
const navBar = document.getElementById('nav-topbar');
|
|
368
636
|
const navHeader = document.getElementById('nav-header');
|
|
637
|
+
const isMobile = window.innerWidth <= 768;
|
|
369
638
|
|
|
370
639
|
// Check if navigation was previously collapsed
|
|
371
640
|
const navCollapsed = localStorage.getItem('navCollapsed') === 'true';
|
|
@@ -397,20 +666,21 @@
|
|
|
397
666
|
|
|
398
667
|
// Toggle on button click
|
|
399
668
|
toggleBtn.addEventListener('click', function(e) {
|
|
400
|
-
e.stopPropagation();
|
|
669
|
+
e.stopPropagation();
|
|
401
670
|
toggleNav();
|
|
402
671
|
});
|
|
403
672
|
|
|
404
|
-
// Expand on toggle button hover when collapsed
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
673
|
+
// Expand on toggle button hover when collapsed (desktop only)
|
|
674
|
+
if (!isMobile) {
|
|
675
|
+
toggleBtn.addEventListener('mouseenter', function() {
|
|
676
|
+
if (navBar.classList.contains('collapsed')) {
|
|
677
|
+
expandNav();
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
}
|
|
410
681
|
|
|
411
682
|
// Toggle on header click
|
|
412
683
|
navHeader.addEventListener('click', function(e) {
|
|
413
|
-
// Don't toggle if a link within the header was clicked
|
|
414
684
|
if (e.target.tagName === 'A') {
|
|
415
685
|
return;
|
|
416
686
|
}
|
|
@@ -419,8 +689,196 @@
|
|
|
419
689
|
|
|
420
690
|
// Make the header appear clickable with cursor style
|
|
421
691
|
navHeader.style.cursor = 'pointer';
|
|
692
|
+
|
|
693
|
+
// Handle window resize
|
|
694
|
+
window.addEventListener('resize', function() {
|
|
695
|
+
const newIsMobile = window.innerWidth <= 768;
|
|
696
|
+
if (newIsMobile !== isMobile) {
|
|
697
|
+
if (newIsMobile) {
|
|
698
|
+
// On mobile, collapse the nav by default
|
|
699
|
+
collapseNav();
|
|
700
|
+
} else {
|
|
701
|
+
// On desktop, expand the nav by default
|
|
702
|
+
expandNav();
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
// Handle dropdown toggles
|
|
708
|
+
document.querySelectorAll('.nav-group-dropdown-btn').forEach(button => {
|
|
709
|
+
button.addEventListener('click', function(e) {
|
|
710
|
+
e.stopPropagation();
|
|
711
|
+
this.classList.toggle('open');
|
|
712
|
+
});
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
// Close dropdowns when clicking outside
|
|
716
|
+
document.addEventListener('click', function(e) {
|
|
717
|
+
if (!e.target.closest('.nav-group-dropdown')) {
|
|
718
|
+
document.querySelectorAll('.nav-group-dropdown-btn').forEach(button => {
|
|
719
|
+
button.classList.remove('open');
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
});
|
|
724
|
+
</script>
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
<button id="form-filler-button" class="form-filler-button" title="Fill all form fields with default values">
|
|
728
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
729
|
+
<path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
|
|
730
|
+
</svg>
|
|
731
|
+
<span>Fill Form</span>
|
|
732
|
+
</button>
|
|
733
|
+
|
|
734
|
+
<script>
|
|
735
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
736
|
+
// Create a function to fill the form with sensible default values
|
|
737
|
+
function fillFormWithDefaults() {
|
|
738
|
+
// Get all input elements
|
|
739
|
+
const inputs = document.querySelectorAll('input, select, textarea');
|
|
740
|
+
|
|
741
|
+
// Record which elements were filled for status feedback
|
|
742
|
+
const filledElements = [];
|
|
743
|
+
|
|
744
|
+
// Process each input
|
|
745
|
+
inputs.forEach(input => {
|
|
746
|
+
let filled = true;
|
|
747
|
+
|
|
748
|
+
// Skip hidden inputs and those with existing values
|
|
749
|
+
if (input.type === 'hidden' || (input.value && input.value.trim() !== '')) {
|
|
750
|
+
filled = false;
|
|
751
|
+
}
|
|
752
|
+
// Handle different input types
|
|
753
|
+
else if (input.type === 'text') {
|
|
754
|
+
if (input.id.toLowerCase().includes('name') || input.name.toLowerCase().includes('name')) {
|
|
755
|
+
input.value = 'John Doe';
|
|
756
|
+
} else {
|
|
757
|
+
input.value = 'Default Text';
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
else if (input.type === 'email') {
|
|
761
|
+
input.value = 'test@example.com';
|
|
762
|
+
}
|
|
763
|
+
else if (input.type === 'password') {
|
|
764
|
+
input.value = 'Password123!';
|
|
765
|
+
}
|
|
766
|
+
else if (input.type === 'tel') {
|
|
767
|
+
input.value = '+1234567890';
|
|
768
|
+
}
|
|
769
|
+
else if (input.type === 'number') {
|
|
770
|
+
input.value = '42';
|
|
771
|
+
}
|
|
772
|
+
else if (input.type === 'url') {
|
|
773
|
+
input.value = 'https://example.com';
|
|
774
|
+
}
|
|
775
|
+
else if (input.type === 'date') {
|
|
776
|
+
const today = new Date();
|
|
777
|
+
const yyyy = today.getFullYear();
|
|
778
|
+
const mm = String(today.getMonth() + 1).padStart(2, '0');
|
|
779
|
+
const dd = String(today.getDate()).padStart(2, '0');
|
|
780
|
+
input.value = `${yyyy}-${mm}-${dd}`;
|
|
781
|
+
}
|
|
782
|
+
else if (input.type === 'time') {
|
|
783
|
+
input.value = '12:00';
|
|
784
|
+
}
|
|
785
|
+
else if (input.type === 'checkbox' || input.type === 'radio') {
|
|
786
|
+
input.checked = true;
|
|
787
|
+
}
|
|
788
|
+
else if (input.tagName === 'SELECT') {
|
|
789
|
+
if (input.options.length > 0) {
|
|
790
|
+
input.selectedIndex = 1 >= input.options.length ? 0 : 1; // Select second option if available, first otherwise
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
else if (input.tagName === 'TEXTAREA') {
|
|
794
|
+
input.value = 'This is a sample text for the textarea field.';
|
|
795
|
+
}
|
|
796
|
+
else {
|
|
797
|
+
// For any other input types
|
|
798
|
+
input.value = 'Default Value';
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// Add to filled elements if we actually filled it
|
|
802
|
+
if (filled) {
|
|
803
|
+
filledElements.push(input);
|
|
804
|
+
|
|
805
|
+
// Dispatch input event to trigger any listeners
|
|
806
|
+
const event = new Event('input', { bubbles: true });
|
|
807
|
+
input.dispatchEvent(event);
|
|
808
|
+
|
|
809
|
+
// For select elements, also dispatch change event
|
|
810
|
+
if (input.tagName === 'SELECT') {
|
|
811
|
+
const changeEvent = new Event('change', { bubbles: true });
|
|
812
|
+
input.dispatchEvent(changeEvent);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
// Show a notification about what was filled
|
|
818
|
+
if (filledElements.length > 0) {
|
|
819
|
+
// If an updateCaptchaStatus function exists (from our other demos), use it
|
|
820
|
+
if (typeof window.updateCaptchaStatus === 'function') {
|
|
821
|
+
window.updateCaptchaStatus(`Filled ${filledElements.length} form fields with default values`, 'info');
|
|
822
|
+
} else {
|
|
823
|
+
console.log(`Filled ${filledElements.length} form fields with default values`);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Highlight the filled fields briefly
|
|
827
|
+
filledElements.forEach(el => {
|
|
828
|
+
const originalBackground = el.style.backgroundColor;
|
|
829
|
+
const originalTransition = el.style.transition;
|
|
830
|
+
|
|
831
|
+
el.style.transition = 'background-color 1.5s ease';
|
|
832
|
+
el.style.backgroundColor = '#e3f2fd';
|
|
833
|
+
|
|
834
|
+
setTimeout(() => {
|
|
835
|
+
el.style.backgroundColor = originalBackground;
|
|
836
|
+
setTimeout(() => {
|
|
837
|
+
el.style.transition = originalTransition;
|
|
838
|
+
}, 1500);
|
|
839
|
+
}, 500);
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// Add the click event listener to the form filler button
|
|
845
|
+
const formFillerButton = document.getElementById('form-filler-button');
|
|
846
|
+
if (formFillerButton) {
|
|
847
|
+
formFillerButton.addEventListener('click', fillFormWithDefaults);
|
|
848
|
+
}
|
|
422
849
|
});
|
|
423
850
|
</script>
|
|
424
851
|
|
|
425
|
-
|
|
426
|
-
</
|
|
852
|
+
<div class="explanation">
|
|
853
|
+
<h2>How Invisible Image CAPTCHA Works (Implicit Rendering)</h2>
|
|
854
|
+
|
|
855
|
+
<h3>Implementation Details</h3>
|
|
856
|
+
<p>This example demonstrates how to use Procaptcha in image mode with implicit rendering:</p>
|
|
857
|
+
<ol>
|
|
858
|
+
<li>Import the Procaptcha script</li>
|
|
859
|
+
<li>Add a div with the procaptcha class</li>
|
|
860
|
+
<li>Set data-* attributes to configure the CAPTCHA</li>
|
|
861
|
+
<li>Handle the verification result in the callback function</li>
|
|
862
|
+
</ol>
|
|
863
|
+
|
|
864
|
+
<h3>Key Code Example</h3>
|
|
865
|
+
<pre><div
|
|
866
|
+
class="procaptcha"
|
|
867
|
+
data-theme="light"
|
|
868
|
+
data-sitekey="%PROSOPO_SITE_KEY_IMAGE%"
|
|
869
|
+
data-failed-callback="onCaptchaFailed"
|
|
870
|
+
data-callback="onCaptchaVerified"
|
|
871
|
+
data-captcha-type="image"
|
|
872
|
+
data-size="invisible"
|
|
873
|
+
></div></pre>
|
|
874
|
+
|
|
875
|
+
<h3>Execution Flow</h3>
|
|
876
|
+
<ol>
|
|
877
|
+
<li>On page load, Procaptcha scans for elements with the procaptcha class</li>
|
|
878
|
+
<li>The CAPTCHA challenge is rendered only when needed</li>
|
|
879
|
+
<li>When the user completes the challenge, the callback function is called</li>
|
|
880
|
+
<li>On successful verification, the form can be submitted with the token</li>
|
|
881
|
+
</ol>
|
|
882
|
+
</div>
|
|
883
|
+
</body>
|
|
884
|
+
</html>
|