I have implemented new Google's INVISIBLE reCaptcha on several sites successfully, however, it conflicts with jQuery validate(), in such a way that the js validation is no longer executed on button/form submit, and reCaptcha instantly kicks-in. If user forgets to fill-in a requried form field, it will have to wait for server response, and get back to it next time.
jQuery .validate() supports callback, but because of the fact that it is hard-coded inside an internal class of a CMS, is there a way I can modify it somehow outside (e.g. from front-end theme, on document load, when validation code is already rendered)?
Or, another idea would be to postpone captcha's callback somehow, so that validation step can get a chance to run.
Thanks!
jQuery Validate form: (hard-coded in the core, can't be modified, unless I edit core file or extend class/clone function - not optimal)
<script type="text/javascript">
$(document).ready(function(){
$("form[name=comment_form]").validate({
rules: {
body: {
required: true,
minlength: 1
},
authorEmail: {
required: true,
email: true
}
},
wrapper: "li",
errorLabelContainer: "#comment_error_list",
invalidHandler: function(form, validator) {
$('html,body').animate({ scrollTop: $('#comment_error_list').offset().top }, { duration: 250, easing: 'swing'});
},
submitHandler: function(form){
$('button[type=submit], input[type=submit]').attr('disabled', 'disabled');
form.submit();
}
});
});
</script>
reCaptcha explicit render:
<script type='text/javascript'>
var renderInvisibleReCaptcha = function() {
for (var i = 0; i < document.forms.length; ++i) {
var form = document.forms[i];
var holder = form.querySelector('.invisible-recaptcha');
if (null === holder) continue;
(function(frm){
var holderId = grecaptcha.render(holder, {
'sitekey': 'my-key-here',
'badge': 'inline',
'size': 'invisible',
'callback': function (recaptchaToken) {HTMLFormElement.prototype.submit.call(frm);},
'expired-callback': function(){grecaptcha.reset(holderId);}
});
frm.onsubmit = function (evt){evt.preventDefault();grecaptcha.execute(holderId);};
})(form);
}
};
</script>
I had the same problem, I finally found the right way to integrate jquery validate with invisible reCaptcha. It's a mix of some of the proposed solutions here.
First of all, the the HTML part:
<div class="g-recaptcha" data-sitekey="<your key here>"
data-size="invisible"
data-callback="formSubmit">
</div>
Then, you must implement the reCaptcha callback in that way:
function formSubmit(response) {
// submit the form which now includes a g-recaptcha-response input
$("#orderform").submit();
return true;
}
And finally, the tricky part is in the jquery validate's submitHandler:
submitHandler: function (form) {
if (grecaptcha.getResponse()) {
// 2) finally sending form data
form.submit();
}else{
// 1) Before sending we must validate captcha
grecaptcha.reset();
grecaptcha.execute();
}
}
The sequence is as follows:
Hope this helps.
I was having the similar problem and validated the form before executing invisible reCaptcha with the help of this link provided by Terry.
Here are the steps:
Add this div before the submit button in your form
<div id='recaptcha' class="g-recaptcha"
data-sitekey="your_site_key"
data-callback="onSubmit"
data-size="invisible"></div>
Update your key as well. After the form closure add this method
<script>onload();</script>
Before your form add this code
<script>
function validate(event) {
event.preventDefault();
if (!document.getElementById('field').value) {
alert("You must add text to the required field");
} else {
grecaptcha.execute();
}
}
function onload() {
var element = document.getElementById('submit');
element.onclick = validate;
}
</script>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
Do all the validations in validate method and if all the validations are successful then execute captcha.
Technically all we "really" want to do is Programmatically bind the challenge to a button. For example:
Add this method, which we want only to execute the invisible grecaptcha instead of "real" validation
jQuery.validator.addMethod("iv_recapcha_valid", function(value, element) {
return grecaptcha.execute();
}, 'No message needed, grecaptcha excecuted');
Then add this rule to your existing rules
rules: { gRecaptchaResponse: { iv_recapcha_valid: true } }
add a hidden field
<input type="hidden" name="gRecaptchaResponse" value="" >
Now, "technically" the submit button is bound to the user's click action
https://developers.google.com/recaptcha/docs/invisible
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With