UndefinedOffset / silverstripe-nocaptcha

A spam protector and form field using Google's reCAPTCHA v2 or optionally a foundation v3 implementation
BSD 3-Clause "New" or "Revised" License
31 stars 37 forks source link

Can't see 'Please answer the captcha' message on a multi-step form #58

Open noizyboy opened 4 years ago

noizyboy commented 4 years ago

If you put a recaptcha on the final page of a multi-step userforms, and the user doesn't check the recaptcha, the form reloads back at step one with no indication as to what has gone wrong (or, indeed, that anything has gone wrong at all).

Obviously, not an ideal user interface experience. I can imagine a lot of users working under the assumption that since there's no error message that their form has submitted correctly.

Is there any way to let the user know that there's been an error in this scenario and/or to push the user through to the step that has the recaptcha on it?

1

2

noizyboy commented 4 years ago

Needing a solution for this in short-order, I over-rode the default template for the norecaptcha widget, adding the data-expired-callback and data-callback attributes, so...

app/templates/UndefinedOffset/NoCaptcha/Forms/NocaptchaField.ss

<div data-expired-callback="recaptcha_callback" data-callback="recaptcha_callback" class="g-recaptcha" id="Nocaptcha-$ID" data-sitekey="$SiteKey" data-theme="$CaptchaTheme.ATT" data-type="$CaptchaType.ATT" data-size="$CaptchaSize.ATT" data-form="$FormID" data-badge="$CaptchaBadge.ATT"></div>
<noscript>
    <p><%t UndefinedOffset\\NoCaptcha\\Forms\\NocaptchaField.NOSCRIPT "You must enable JavaScript to submit this form" %></p>
</noscript>

I added this script to the relevant page, which uses the callback functions to set the RECAPTCHA_IS_VALID to the appropriate value, which in turn stops the form from submitting if the value remains false (so, no jump back to the first step).

var RECAPTCHA_IS_VALID = false;

(function ($) {
    $(document).ready(function () {
        $('.userform input[type="submit"]').on('click', function (e) {
            if (!RECAPTCHA_IS_VALID) {
                alert('Please confirm you\'re not a robot');
                e.preventDefault();
            }
        });
});

// gets called by Google callback when recaptcha is successfully checked
function recaptcha_callback() {
    RECAPTCHA_IS_VALID = true;
}

// gets called by Google callback if recaptcha expires and needs to be re-checked
function recaptcha_expired() {
    RECAPTCHA_IS_VALID = false;
}

This is entirely fine for my circumstances, but not sure if it'd be worth having a more 'out-of-the-box' solution as well?

UndefinedOffset commented 4 years ago

I do like the idea, I think support for setting these two callbacks on the field makes the most sense, then devs could easily set it on a per-field basis.