From 6822504d8431d1a0884591f9efaaf75c459196ad Mon Sep 17 00:00:00 2001 From: "vivi-the-going-merry[bot]" <308115520+vivi-the-going-merry[bot]@users.noreply.github.com> Date: Wed, 16 Sep 2026 12:36:10 -0600 Subject: [PATCH] Disable submit button while an invisible reCAPTCHA check runs submitFormManual() only called showLoadingIndicator() on the invisible reCAPTCHA path, so disableSubmitButton() (only reached via showSubmitLoading()) never ran and the button stayed clickable for the whole duration of the check, allowing duplicate submissions. Switches that branch to showSubmitLoading() like the non-captcha path, and adds a 10s fallback that re-enables the button only if the reCAPTCHA check itself never resolved - the widget has no error/expired callback wired up, so a stalled check would otherwise leave the button disabled with no way to retry. Fixes Strategy11/formidable-pro#3368 Co-Authored-By: Claude Sonnet 5 --- js/formidable.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/js/formidable.js b/js/formidable.js index 41c018a4bd..7a95c7aab9 100644 --- a/js/formidable.js +++ b/js/formidable.js @@ -757,6 +757,24 @@ function frmFrontFormJS() { grecaptcha.execute( recaptchaID ); } + /** + * The invisible reCAPTCHA widget has no error/expired callback wired up, so a + * stalled or failed check would otherwise leave the submit button disabled + * with no way to retry. Only re-enable if the check itself never resolved - + * once it has, the form is submitting for real and its own ajax lifecycle + * owns the button state. + * + * @param {HTMLElement} object Form object. + * @return {void} + */ + function reenableSubmitIfRecaptchaStalls( object ) { + setTimeout( function() { + if ( object.classList.contains( 'frm_loading_form' ) && hasInvisibleRecaptcha( object ) ) { + removeSubmitLoading( jQuery( object ), 'enable' ); + } + }, 10000 ); + } + function validateRecaptcha( form, errors ) { const formEl = form instanceof jQuery ? form.get( 0 ) : form; if ( ! formEl ) { @@ -2434,12 +2452,12 @@ function frmFrontFormJS() { const invisibleRecaptcha = hasInvisibleRecaptcha( object ); + showSubmitLoading( jQuery( object ) ); + if ( invisibleRecaptcha ) { - showLoadingIndicator( jQuery( object ) ); executeInvisibleRecaptcha( invisibleRecaptcha ); + reenableSubmitIfRecaptchaStalls( object ); } else { - showSubmitLoading( jQuery( object ) ); - frmFrontForm.submitFormNow( object ); } },