From 48e6e64535fedf2c616e77d14d09b4a0f79578d8 Mon Sep 17 00:00:00 2001 From: Riccardo Caroli Date: Thu, 5 Jan 2023 15:06:39 +0100 Subject: [PATCH 1/3] refactor v3 twig to support multiple recaptcha on the same page, and load recaptcha javascript only if form is visible, and support custom form submit listeners --- .../Form/v3/ewz_recaptcha_widget.html.twig | 65 ++++++++++++++----- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig b/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig index 1455721..7d24513 100644 --- a/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig +++ b/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig @@ -1,8 +1,6 @@ {% block ewz_recaptcha_widget %} {% apply spaceless %} {% if form.vars.ewz_recaptcha_enabled %} - - {% if form.vars.ewz_recaptcha_hide_badge %} {% endif %} @@ -11,19 +9,56 @@ {{ form_widget(form) }} - var grecaptchaInput = document.getElementById('{{ id }}'); - grecaptchaInput.value = ''; // Always reset the value to get a brand new challenge - var grecaptchaForm = grecaptchaInput.form; - grecaptchaForm.addEventListener('submit', function (e) { - e.preventDefault(); - - grecaptcha.ready(function () { - grecaptcha.execute('{{ form.vars.public_key }}', { action: '{{ form.vars.action_name|default(constant('EWZ\\Bundle\\RecaptchaBundle\\Form\\Type\\EWZRecaptchaV3Type::DEFAULT_ACTION_NAME')) }}' }).then(function (token) { - grecaptchaInput.value = token; - HTMLFormElement.prototype.submit.call(grecaptchaForm); - }); - }); - }, false); + (function(){ + var element = document.querySelector('#{{ id }}'); + var form = element.form; + + // recaptcha callback for this form + + window['recaptchaOnloadCallback_{{ id }}_done'] = false; + window['recaptchaOnloadCallback_{{ id }}'] = function() { + form.addEventListener('submit', function(e) { + if (!window['recaptchaOnloadCallback_{{ id }}_done']) { + e.preventDefault(); // stop form submit + e.stopPropagation(); // stop also events + grecaptcha.execute('{{ form.vars.public_key }}', { action: '{{ form.vars.action_name|default(constant('EWZ\\Bundle\\RecaptchaBundle\\Form\\Type\\EWZRecaptchaV3Type::DEFAULT_ACTION_NAME')) }}' }).then(function (token) { + element.value = token; + window['recaptchaOnloadCallback_{{ id }}_done'] = true; + form.querySelector('[type="submit"]').click(); // trigger also events + }); + } + }, true) // execute before other submit listeners + }; + + // recaptcha load for this form + + var loadJS = function () { + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = '{{ form.vars.ewz_recaptcha_api_uri }}?render={{ form.vars.public_key }}&onload=recaptchaOnloadCallback_{{ id }}'; + script.async = true; + document.body.appendChild(script); + }; + + // detect when form is visible + + if (!('IntersectionObserver' in window) || + !('IntersectionObserverEntry' in window) || + !('intersectionRatio' in window.IntersectionObserverEntry.prototype)) { + loadJS(); + } else { + var observer = new IntersectionObserver(function(entries, observer) { + entries.forEach(function(entry) { + if (entry.intersectionRatio > 0) { + observer.disconnect(); + loadJS(); + } + }); + }, { root: null }); + + observer.observe(form); + } + })(); {% endif %} {% endapply %} From db8f18f6926bf1ec7b919b5abe1e0638728891ac Mon Sep 17 00:00:00 2001 From: Riccardo Caroli Date: Mon, 20 Mar 2023 12:31:37 +0100 Subject: [PATCH 2/3] reset state and useCapture to make it work with ajax forms --- .../views/Form/v3/ewz_recaptcha_widget.html.twig | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig b/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig index 7d24513..224f4f9 100644 --- a/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig +++ b/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig @@ -17,7 +17,12 @@ window['recaptchaOnloadCallback_{{ id }}_done'] = false; window['recaptchaOnloadCallback_{{ id }}'] = function() { - form.addEventListener('submit', function(e) { + addEventListener('submit', function(e) { + var element = document.querySelector('#{{ id }}'); + var form = element.form; + if (e.target !== form) { + return + } if (!window['recaptchaOnloadCallback_{{ id }}_done']) { e.preventDefault(); // stop form submit e.stopPropagation(); // stop also events @@ -25,6 +30,7 @@ element.value = token; window['recaptchaOnloadCallback_{{ id }}_done'] = true; form.querySelector('[type="submit"]').click(); // trigger also events + window['recaptchaOnloadCallback_{{ id }}_done'] = false; }); } }, true) // execute before other submit listeners From a8a14df2564e816087373d9aa7281d8ab57c0370 Mon Sep 17 00:00:00 2001 From: Riccardo Caroli Date: Wed, 21 Feb 2024 12:58:08 +0100 Subject: [PATCH 3/3] fix: fix submit generic selector and no submit --- src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig b/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig index 224f4f9..dfaaa5d 100644 --- a/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig +++ b/src/Resources/views/Form/v3/ewz_recaptcha_widget.html.twig @@ -29,7 +29,11 @@ grecaptcha.execute('{{ form.vars.public_key }}', { action: '{{ form.vars.action_name|default(constant('EWZ\\Bundle\\RecaptchaBundle\\Form\\Type\\EWZRecaptchaV3Type::DEFAULT_ACTION_NAME')) }}' }).then(function (token) { element.value = token; window['recaptchaOnloadCallback_{{ id }}_done'] = true; - form.querySelector('[type="submit"]').click(); // trigger also events + if (e.submitter) { + e.submitter.click(); // trigger also events + } else { + form.submit(); + } window['recaptchaOnloadCallback_{{ id }}_done'] = false; }); }