PageSourceSearch

https://www.saertex.com/wp-content/plugins/lwd_security_enhancements/assets/js/honeypot.js?ver=7.1.2

js saertex.com collected 2026-10-02 17:04:26 UTC 7,923 bytes, 162 lines download raw bytes

1jQuery(document).ready(function ($) {
2    // Function to dynamically inject honeypot into any form containing a password field
3    function injectHoneypots() {
4        let forms = $('form').filter(function () {
5            // Only target forms that contain a password field (likely login/registration)
6            return $(this).find('input[type="password"]').length > 0;
7        });
8
9        forms.each(function () {
10            let form = $(this);
11            // If we haven't secured this form yet
12            if (form.find('.lwd-honeypot-container').length === 0) {
13                // Dynamically build the honeypot fields so they exist even if PHP hook didn't fire
14                let honeypotHTML = `
15                    <div class="lwd-honeypot-container" style="position: absolute; opacity: 0; top: 0; left: 0; height: 0; width: 0; z-index: -1; overflow: hidden;" aria-hidden="true">
16                        <input type="email" class="lwd-customer-email" name="customer-email" tabindex="-1" autocomplete="off">
17                        <input type="text" class="lwd-captcha-response" name="captchaResponse" tabindex="-1" autocomplete="off">
18                    </div>
19                `;
20                form.prepend(honeypotHTML);
21
22                // Initialize the strength bar on standard WP login
23                let pwdField = form.find('input[type="password"]');
24                if (pwdField.length && form.is('#loginform')) {
25                    if (form.find('.strength-bar').length === 0) {
26                        pwdField.after('<div class="strength-bar" style="height:5px; width:0%; background-color:red; transition:all 0.5s ease-in-out 0s; margin-top:-15px; margin-bottom:15px; border-radius: 25px;"></div>');
27                    }
28                }
29            }
30        });
31    }
32
33    // Run injection on initial load
34    injectHoneypots();
35
36    // Observe body for dynamically loaded forms (e.g. Elementor popups)
37    const observer = new MutationObserver(function (mutations) {
38        let shouldInject = false;
39        mutations.forEach(function (mutation) {
40            if (mutation.addedNodes.length) shouldInject = true;
41        });
42        if (shouldInject) injectHoneypots();
43    });
44    observer.observe(document.body, { childList: true, subtree: true });
45
46    // Intelligently populate the valid captcha response upon user interaction, 
47    // instead of waiting a rigid 3.5 seconds (which breaks autofill!).
48    // This allows legitimate users to log in instantly.
49    $(document).on('submit focus mouseover touchstart', 'form', function (e) {
50        let form = $(this);
51        if (form.find('input[type="password"]').length > 0) {
52            let captchaField = form.find('.lwd-captcha-response');
53            let emailField = form.find('.lwd-customer-email');
54
55            // If it exists and the bot hasn't touched the email field
56            if (captchaField.length && emailField.val() === "") {
57                captchaField.val('Captcha_akzeptiert');
58            }
59
60            // Also handle forms that were rendered by PHP where IDs are used instead of classes
61            let phpCaptchaField = form.find('#captchaResponse');
62            let phpEmailField = form.find('#customer-email');
63            if (phpCaptchaField.length && phpEmailField.val() === "") {
64                phpCaptchaField.val('Captcha_akzeptiert');
65            }
66        }
67    });
68
69    // Password strength logic
70    $(document).on('input', 'form input[type="password"]', function (e) {
71        let passwordField = e.target;
72        let strongRegex = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\\$%\\^&\\*])(?=.{8,})");
73        let mediumRegex = new RegExp("^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})");
74        let strengthBar = $(this).siblings('.strength-bar');
75
76        if (strengthBar.length) {
77            if (passwordField.value.length === 0) {
78                strengthBar.css({ width: '0%' });
79            } else if (strongRegex.test(passwordField.value)) {
80                strengthBar.css({ width: '100%', backgroundColor: 'green' });
81            } else if (mediumRegex.test(passwordField.value)) {
82                strengthBar.css({ width: '60%', backgroundColor: 'orange' });
83            } else {
84                strengthBar.css({ width: '20%', backgroundColor: 'red' });
85            }
86        }
87    });
88
89    // Prevent double form submissions (double-submits) for AJAX/generic forms
90    var formSubmittingSelector = 'button[type="submit"], input[type="submit"]';
91    $(document).on('submit', 'form.elementor-form, form.wpcf7-form', function(e) {
92        var $form = $(this);
93        
94        // If another handler has already called preventDefault, do nothing
95        if (e.isDefaultPrevented()) {
96            return;
97        }
98        
99        // HTML5 Form Validation check
100        if (this.checkValidity && !this.checkValidity()) {
101            return;
102        }
103        
104        // Skip web-to-lead forms as they are synchronous and have their own custom blocker
105        if ($form.attr('id') === 'webtolead-form' || $form.hasClass('webtolead-form') || $form.find('#submitValue').length > 0) {
106            return;
107        }
108        
109        // If form is already in the process of submitting, prevent the submission
110        if ($form.data('lwd-submitting') === true) {
111            e.preventDefault();
112            return false;
113        }
114        
115        // Mark form as submitting
116        $form.data('lwd-submitting', true);
117        
118        // Disable submit button after a tiny delay so the submit event finishes bubbling to internal handlers
119        var $submitBtns = $form.find(formSubmittingSelector);
120        setTimeout(function() {
121            $submitBtns.prop('disabled', true);
122            $submitBtns.each(function() {
123                var $btn = $(this);
124                if ($btn.find('.lwd-spinner').length === 0) {
125                    var $btnText = $btn.find('.elementor-button-text');
126                    if ($btnText.length > 0) {
127                        $btnText.prepend('<i class="fas fa-spinner fa-spin lwd-spinner" style="margin-right: 8px;"></i>');
128                    } else {
129                        $btn.prepend('<i class="fas fa-spinner fa-spin lwd-spinner" style="margin-right: 8px;"></i>');
130                    }
131                }
132            });
133        }, 10);
134        
135        // Fallback: Re-enable the button after 10 seconds in case of silent failure or network timeout
136        setTimeout(function() {
137            if ($form.data('lwd-submitting') === true) {
138                $form.data('lwd-submitting', false);
139                $submitBtns.prop('disabled', false).find('.lwd-spinner').remove();
140            }
141        }, 10000);
142    });
143
144    // Global AJAX completion listener to re-enable button when request ends
145    $(document).ajaxComplete(function(event, xhr, settings) {
146        // Only trigger if the completed AJAX request was actually our form submission
147        var isElementorSubmit = settings.data && typeof settings.data === 'string' && settings.data.indexOf('action=elementor_pro_forms_send_form') !== -1;
148        var isCF7Submit = settings.url && typeof settings.url === 'string' && settings.url.indexOf('/contact-form-7/') !== -1;
149        
150        if (isElementorSubmit || isCF7Submit) {
151            setTimeout(function() {
152                $('form').each(function() {
153                    var $form = $(this);
154                    if ($form.data('lwd-submitting') === true) {
155                        $form.data('lwd-submitting', false);
156                        $form.find(formSubmittingSelector).prop('disabled', false).find('.lwd-spinner').remove();
157                    }
158                });
159            }, 500);
160        }
161    });
162});

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.