PageSourceSearch

https://www.ville-pontarlier.fr/assets/js/recaptcha-v3.js?v=1790282225

js ville-pontarlier.fr collected 2026-09-24 20:37:14 UTC 6,082 bytes, 191 lines download raw bytes

1/**
2 * reCAPTCHA v3 Integration
3 * Invisible reCAPTCHA v3 implementation for forms
4 * Version: 1.2.0
5 * Last Updated: 2025-09-29
6 */
7
8if (typeof window.RecaptchaV3 !== 'undefined') {
9} else {
10
11function RecaptchaV3(siteKey) {
12    this.siteKey = siteKey;
13    this.isLoaded = false;
14    this.init();
15}
16
17RecaptchaV3.prototype.init = function() {
18
19    if (document.querySelector('script[src*="recaptcha/api.js"]')) {
20        this.isLoaded = true;
21    } else {
22        var self = this;
23        var checkLoaded = function() {
24            if (typeof grecaptcha !== 'undefined') {
25                self.isLoaded = true;
26            } else {
27                setTimeout(checkLoaded, 100);
28            }
29        };
30        checkLoaded();
31    }
32};
33
34RecaptchaV3.prototype.execute = function(action) {
35    var self = this;
36    return new Promise(function(resolve, reject) {
37        if (!self.isLoaded) {
38            reject(new Error('reCAPTCHA v3 not loaded yet'));
39            return;
40        }
41
42        if (typeof grecaptcha === 'undefined') {
43            reject(new Error('grecaptcha is not available'));
44            return;
45        }
46
47        try {
48            grecaptcha.execute(self.siteKey, { action: action }).then(function(token) {
49                resolve(token);
50            }).catch(function(error) {
51                console.error('reCAPTCHA v3 execution failed:', error);
52                reject(error);
53            });
54        } catch (error) {
55            console.error('reCAPTCHA v3 execution failed:', error);
56            reject(error);
57        }
58    });
59};
60
61RecaptchaV3.prototype.addToForm = function(formSelector, action, onSuccess, onError) {
62    var self = this;
63    var form = document.querySelector(formSelector);
64
65    if (!form || !(form instanceof HTMLFormElement)) {
66        console.error('Form not found or invalid:', formSelector, form);
67        return;
68    }
69
70    var recaptchaInput = form.querySelector('input[name="g-recaptcha-response"]');
71    if (!recaptchaInput) {
72        recaptchaInput = document.createElement('input');
73        recaptchaInput.type = 'hidden';
74        recaptchaInput.name = 'g-recaptcha-response';
75        form.appendChild(recaptchaInput);
76    }
77
78    var isSubmitting = false;
79    form.addEventListener('submit', function(event) {
80        if (isSubmitting) return;
81        isSubmitting = true;
82
83        event.preventDefault(); // pour éviter double submit
84
85        self.execute(action).then(function(token) {
86            recaptchaInput.value = token;
87
88            if (onSuccess) onSuccess(token);
89
90            setTimeout(function() {
91                try {
92                    HTMLFormElement.prototype.submit.call(form);
93                } catch (e) {
94                    console.warn('Native submit failed, fallback to click:', e);
95                    var submitButton = form.querySelector('input[type="submit"], button[type="submit"]');
96                    if (submitButton) {
97                        submitButton.click();
98                    } else {
99                        var tempSubmit = document.createElement('input');
100                        tempSubmit.type = 'submit';
101                        tempSubmit.style.display = 'none';
102                        form.appendChild(tempSubmit);
103                        tempSubmit.click();
104                        form.removeChild(tempSubmit);
105                    }
106                }
107            }, 50);
108
109        }).catch(function(error) {
110            console.error('reCAPTCHA v3 error:', error);
111            isSubmitting = false;
112
113            if (onError) {
114                onError(error);
115            } else {
116                if (typeof swal !== 'undefined') {
117                    swal({
118                        title: 'Erreur',
119                        text: 'Vérification de sécurité échouée. Veuillez réessayer.',
120                        icon: 'error'
121                    });
122                }
123            }
124        });
125    });
126};
127
128
129RecaptchaV3.prototype.addToForms = function(forms) {
130    var self = this;
131    forms.forEach(function(config) {
132        self.addToForm(
133            config.selector,
134            config.action || 'submit',
135            config.onSuccess,
136            config.onError
137        );
138    });
139};
140
141window.RecaptchaV3 = RecaptchaV3;
142
143document.addEventListener('DOMContentLoaded', function() {
144    var currentVersion = '1.2.0';
145    var loadedVersion = document.querySelector('meta[name="recaptcha-v3-version"]');
146    
147    if (loadedVersion && loadedVersion.content === currentVersion) {
148        console.warn('reCAPTCHA v3 version ' + currentVersion + ' already loaded');
149        return;
150    }
151
152    var meta = document.createElement('meta');
153    meta.name = 'recaptcha-v3-version';
154    meta.content = currentVersion;
155    document.head.appendChild(meta);
156
157    var getSiteKeyFromScript = function() {
158        var script = document.querySelector('script[src*="recaptcha/api.js"]');
159        if (script) {
160            var match = script.src.match(/render=([^&]+)/);
161            return match ? match[1] : null;
162        }
163        return null;
164    };
165    
166    var siteKey = getSiteKeyFromScript();
167    
168    var checkGrecaptcha = function() {
169        return typeof grecaptcha !== 'undefined';
170    };
171    
172    if (siteKey && checkGrecaptcha()) {
173        window.recaptchaV3 = new RecaptchaV3(siteKey);
174        
175        var forms = document.querySelectorAll('form[data-recaptcha]');
176        forms.forEach(function(form) {
177            var action = form.dataset.recaptchaAction || 'submit';
178            window.recaptchaV3.addToForm('#' + form.id, action);
179        });
180    } else {
181        var forms = document.querySelectorAll('form[data-recaptcha]');
182        forms.forEach(function(form) {
183            form.addEventListener('submit', function(event) {
184                event.preventDefault();
185                return false;
186            });
187        });
188    }
189});
190
191} // End of double loading protection

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.