Skip to content

Instantly share code, notes, and snippets.

@Convincible
Last active June 7, 2019 14:50
Show Gist options
  • Save Convincible/aade715f852be7d61915e3d9d3cab7c1 to your computer and use it in GitHub Desktop.
Save Convincible/aade715f852be7d61915e3d9d3cab7c1 to your computer and use it in GitHub Desktop.
Multiple reCAPTCHAs (v2 Invisible) that run after validation, then send form data over AJAX, using jQuery
<head>
<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaLoad&render=explicit" async defer></script>
</head>
<body>
<form action="?" method="POST" class="form form-ajax">
<label for="form-1-field-message">Message</label>
<textarea name="form-1-field-message" id="form-1-field-message" placeholder="How can we help?" required="required" autocomplete="off" minlength="20" rows="5"></textarea>
<button type="submit" id="form-1-submit" class="form-submit">Send</button>
<p class="form-info">Fill out the form to send us an email.</p>
<div class="g-recaptcha">
Loading reCAPTCHA...
</div>
</form>
</body>
$('form.form').each(function(i, el) {
// Run over all forms on the page, and set some data on them to retrieve later
var form = $(el);
var info = $('.form-info', form).first()[0];
var submit = $('.form-submit', form).last()[0];
form.data('id', i);
form.data('info', info);
form.data('submit', submit);
});
// Bind our logic to each form's submit function
// This will only actually run if HTML5 validation passes first
$('from.form').submit(function(e) {
e.preventDefault(); // Don't submit immediately
var form = $(this);
widget = form.data('grecaptcha-widget'); // This is set by the recaptchaLoad function below
formMessage(form, 'Checking you\'re not a robot...', 0);
grecaptcha.execute(widget); // Now execute this specific CAPTCHA – recaptchaResponse will be called
});
// Called once the external JS from reCAPTCHA has loaded
function recaptchaLoad() {
console.log('Loading reCAPTCHAs...');
// Form each form
$('form.form').each(function(i, el) {
var form = $(el);
// Find the (first – there should be only 1 per form anyway) captcha div
var captcha = form.find('.g-recaptcha').first()[0];
var id = form.data('id');
// Render the recaptcha but do not bind it to anything – at this point it won't actually run
widget = grecaptcha.render(captcha, {
'sitekey': '***************************************',
'callback': function(token) {
recaptchaResponse(form[0], token); // Essential to be able to identify the specific form/widget
},
'badge': 'inline',
'size': 'invisible'
});
// Save the id of this reCAPTCHA widget against the form itself
form.data('grecaptcha-widget', widget);
console.log('Form ' + id + ': Loaded');
});
}
// Called after the reCAPTCHA has been executed
function recaptchaResponse(form, token) {
// Get the widget id from the form that executed this captcha
widget = $(form).data('grecaptcha-widget');
response = grecaptcha.getResponse(widget);
if (response) {
formMessage(form, 'Thanks for confirming you\'re human.', 1);
// CAPTCHA has passed – now send the form data
formSendAjax(form);
} else {
formMessage(form, 'Please complete the reCAPTCHA in order to submit the form.', -1);
}
// Reset the widget in any case so it's ready for a further submission
grecaptcha.reset(widget);
}
// Send data to the action defined in the form, over AJAX
function formSendAjax(form) {
form = $(form);
formMessage(form, 'Sending...', 0);
$.ajax({
type: form.attr('method'),
url: form.attr('action'),
dataType: 'json',
data: form.serialize(),
success: function(data) {
formMessage(form, 'Thanks, your message has been sent. We\'ll respond ASAP.', 1);
form.trigger('reset');
},
error: function(data) {
formMessage(form, 'Sorry, something went wrong. Please email us manually instead.', -1);
}
});
}
// Just a helpful info message that is updated as the form goes through different stages
function formMessage(form, msg, state = 0) {
form = $(form);
id = form.data('id');
info = $(form.data('info'));
console.log('Form ' + id + ': ' + msg);
info.text(msg);
switch (state) {
case 1:
info.addClass('form-info-success');
info.removeClass('form-info-error');
info.removeClass('form-info-fyi');
break;
case -1:
info.addClass('form-info-error');
info.removeClass('form-info-success');
info.removeClass('form-info-fyi');
break;
default:
info.addClass('form-info-fyi');
info.removeClass('form-info-success');
info.removeClass('form-info-error');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment