PageSourceSearch

https://www.drvason.com/assets/js/recaptcha.js

js drvason.com collected 2026-10-06 12:13:48 UTC 6,341 bytes, 180 lines download raw bytes

1/* ---- reCAPTCHA v3 for multiple forms ---- */
2(function ()
3{
4    var recaptchaKey = '6Lf6t1slAAAAAIRVDKc1ncTpnksULIq8YNNh7-n4'; // your site key
5    var recaptchaReady = false;
6
7    function loadRecaptchaScript()
8    {
9        if (document.getElementById('recaptcha-v3')) return; // don't double-load
10
11        var script = document.createElement('script');
12        script.id = 'recaptcha-v3';
13        script.src = 'https://www.google.com/recaptcha/api.js?render=' + recaptchaKey;
14        script.async = true;
15        script.defer = true;
16        script.onload = function () {
17            recaptchaReady = true;
18        };
19
20        document.head.appendChild(script);
21    }
22
23    // Attach a submit handler to a single form (idempotent)
24    function attachRecaptchaToForm(form)
25    {
26        if (!form || form.__recaptchaAttached) return;
27
28        form.__recaptchaAttached = true; // mark as attached
29
30        form.addEventListener('submit', function onSubmit(e)
31        {
32            // If we're already in the "token acquired" pass-through, let it submit
33            if (form.dataset.recaptchaSubmitting === '1')
34            {
35                return;
36            }
37
38            // Optional: let the browser validate first (remove if using custom validation)
39            if (!form.checkValidity || form.checkValidity())
40            {
41                // Ensure grecaptcha is available; if not, load and retry shortly
42                if (!recaptchaReady || typeof grecaptcha === 'undefined')
43                {
44                    e.preventDefault();
45                    loadRecaptchaScript();
46
47                    setTimeout(function ()
48                    {
49                        // Re-trigger submit after the script likely loaded
50                        if (typeof form.requestSubmit === 'function')
51                        {
52                            form.requestSubmit();
53                        }
54
55                        else
56                        {
57                            HTMLFormElement.prototype.submit.call(form);
58                        }
59                    }, 300);
60                    return;
61                }
62
63                // We have grecaptcha?get a fresh token before submitting
64                e.preventDefault();
65                grecaptcha.ready(function ()
66                {
67                    grecaptcha.execute(recaptchaKey,
68                    {
69                        action: 'submit'
70                    }).then(function (token)
71                    {
72                        var tokenField = form.querySelector('input[name="token_generate"]');
73
74                        if (!tokenField)
75                        {
76                            // Create the field if missing
77                            tokenField = document.createElement('input');
78                            tokenField.type = 'hidden';
79                            tokenField.name = 'token_generate';
80                            form.appendChild(tokenField);
81                        }
82
83                        tokenField.value = token;
84
85                        // Mark as pass-through so our submit handler doesn't intercept again
86                        form.dataset.recaptchaSubmitting = '1';
87
88                        // Bypass event listeners to avoid recursion
89                        HTMLFormElement.prototype.submit.call(form);
90                    }).catch(function ()
91                    {
92                        alert('Unable to verify reCAPTCHA. Please try again.');
93                    });
94                });
95            }
96
97            else
98            {
99                // If invalid, let browser show messages
100                // Some browsers need this to display the native UI
101                if (typeof form.reportValidity === 'function')
102                {
103                    form.reportValidity();
104                }
105            }
106        });
107    }
108
109    document.addEventListener('DOMContentLoaded', function ()
110    {
111        // Load reCAPTCHA a moment after page load
112        setTimeout(loadRecaptchaScript, 200);
113
114        // Attach to all existing forms matching the class
115        Array.prototype.forEach.call(
116            document.querySelectorAll('form.recaptcha-form'),
117            attachRecaptchaToForm
118        );
119
120        // If forms are added dynamically later, observe and attach automatically
121        var mo = new MutationObserver(function (mutations)
122        {
123            mutations.forEach(function (m)
124            {
125                Array.prototype.forEach.call(m.addedNodes || [], function (node)
126                {
127                    if (node && node.nodeType === 1)
128                    {
129                        if (node.matches && node.matches('form.recaptcha-form'))
130                        {
131                            attachRecaptchaToForm(node);
132                        }
133
134                        // Also check inside containers
135                        var innerForms = node.querySelectorAll ? node.querySelectorAll('form.recaptcha-form') : [];
136                        Array.prototype.forEach.call(innerForms, attachRecaptchaToForm);
137                    }
138                });
139            });
140        });
141
142        mo.observe(document.documentElement,
143        {
144            childList: true,
145            subtree: true
146        });
147
148        // Optional: preload when a form is near viewport (nice for performance)
149        try
150        {
151            var observer = new IntersectionObserver(function (entries, obs)
152            {
153                entries.forEach(function (entry)
154                {
155                    if (entry.isIntersecting || entry.intersectionRatio >= 0.1)
156                    {
157                        loadRecaptchaScript();
158                        obs.unobserve(entry.target);
159                    }
160                });
161            },
162            {
163                root: null,
164                rootMargin: '0px',
165                threshold: 0.1
166            });
167
168            document.querySelectorAll('form.recaptcha-form').forEach(function (f)
169            {
170                observer.observe(f);
171            });
172
173        }
174
175        catch (_)
176        {
177            /* older browsers */
178        }
179    });
180})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.