$.getScript('https://www.google.com/recaptcha/api.js', function () { const siteKey = window.recaptchaVars.siteKey; if (!siteKey) { console.error('Missing reCaptcha siteKey'); } const captchas = document.querySelectorAll('.captcha'); captchas.forEach((captcha) => { grecaptcha.ready(() => { try { captcha.classList.add('g-recaptcha'); // get reference to containing form const parentForm = captcha.closest('form'); if (!parentForm) { console.error('reCaptcha must be within a form element.'); return; } const CAPTCHA_EMELEMENT_WIDTH = 304; const captchaResponsive = captcha.classList.contains('captcha-responsive') && parentForm.width < CAPTCHA_EMELEMENT_WIDTH; grecaptcha.render(captcha, { 'sitekey': siteKey, 'callback': function (e, formEl = parentForm) { // get reference to #recaptchaConfirmedHidden within containing form and update value to 1 const recaptchaConfirmedHidden = formEl.querySelector('#recaptchaConfirmedHidden'); if (recaptchaConfirmedHidden) { // Flag the recaptcha response as valid. recaptchaConfirmedHidden.value = 1; } // once confirmed, remove the error if present if ($('.js-grecaptcha-error').length) { $('.js-grecaptcha-error').remove(); } }, 'size': captchaResponsive ? 'compact' : 'normal' }); } catch (error) { // error likely due this Captcha element being previously rendered. } }); }); }); /** * @pre The recaptchaConfirmedHidden element must be present on the indicated form at the top level, no nesting. * @param $form jquery wrapped form instance * @param errorMessageSelector Selector used to target error message area. Defaults to .js-section-error. * @return TRUE if validated, FALSE if validation failed */ function handle_grecaptcha_presubmit($form, errorMessageSelector) { const captchaConfirmed = $form.find('#recaptchaConfirmedHidden').val(); if (!errorMessageSelector) { errorMessageSelector = '.js-section-error' } if (captchaConfirmed !== "1") { $(errorMessageSelector).html('' + '