I want to implement reCAPTCHA 2 on my form in the same way as this demo from Google:
but I can't find the source code. As with this demo, I don't want to submit the form and do the verification check via POST parameter as then I have to figure out how to navigate the user back to the form page; rather, I want to prevent submit until the user has clicked the 'I'm not a robot' checkbox successfully. I've gone over the Google documentation and searched the web for examples but haven't been able to figure this out - any help would be appreciated.
Edit The examples in the comments appear to be reCAPTCHA v1 examples, although I specifically asked for v2. I don't think you need to include a php library with v2, and what I'm really looking for is a way to ensure the user has answered the reCAPTCHA challenge before it will submit (I already have a onsubmit JS function to validate other inputs), NOT whether it validates (I'm doing that on the server php file). As I mentioned in my original post, I have searched for an answer but have not been able to find one that replicates Google's demo that I linked to.
Edit 2 I was able to implement a client-side check on whether the user had completed the reCAPTCHA widget with this JavaScript on my HTML page:
<body>
<form id="entryForm" name="entryForm" method="post" action="php/formSubmit.php" onsubmit="return validateForm();">
...
</form>
<script type="text/javascript">
function validateForm() {
// User has to check reCAPTCHA
if(grecaptcha.getResponse() == '') {
alert("Please complete the I'm-not-a-robot widget before submitting your entry.");
//document.forms["entryForm"]["acceptAgrmt"].focus();
return false;
}
}
</script>
</body>
This is what worked for me:
<form id="entryForm" name="entryForm" method="post" action="php/formSubmit.php" onsubmit="return validateForm();">
. . .
<script type="text/javascript">
function validateForm() {
// User has to check reCAPTCHA
if(grecaptcha.getResponse() == '') {
alert("Please complete the I'm-not-a-robot widget before submitting your entry.");
//document.forms["entryForm"]["acceptAgrmt"].focus();
return false;
}
. . .
This is custom google reCAPTCHA Example done by js and HTML/CSS. Check with fiddle
jQuery('#save_default_color').on('change',function(){
if(jQuery(this).is(':checked')){
jQuery(this).attr("disabled", true);
jQuery('.box_layer').addClass('hide_border');
jQuery('.circle_1').addClass('show_cir_1');
setTimeout(function(){
jQuery('.circle_2').addClass('show_cir_2');
},700);
setTimeout(function(){
jQuery('.load_cir').addClass('show_load_cir');
},1500);
setTimeout(function(){
jQuery('.circle_1').addClass('show_cir_1_hide');
},2000);
setTimeout(function(){
complete();
},5000);
}
});
function complete(){
$(".complete_save").toggleClass("drawn");
setTimeout(function(){
jQuery('.load_cir').removeClass('show_load_cir');
},200);
}
input#save_default_color {
display: none;
}
body {
margin: 0;
background-color: #0e0e0e;
}
.set_as_default_color {
display: block;
width: 250px;
background-color: #f9f9f9;
padding: 20px;
margin: 100px auto 0 auto;
border-radius: 4px;
}
p.lbl_text {
display: inline-block;
vertical-align: middle;
margin: 0 0 0 20px;
font-size: 20px;
font-family: sans-serif;
color: #333;
position: relative;
top: 2px;
}
.set_as_default_color label {
width: 30px;
height: 30px;
display: inline-block;
vertical-align: middle;
position: relative;
transform: scale(1.5);
}
.box_layer {
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
border: 2px solid #999;
border-radius: 15%;
transition: all .5s;
transform: scale(.8);
}
.box_layer.hide_border {
transition: all .5s;
transform: scale(0);
transform-origin: center;
}
.circle_1 {
position: absolute;
display: block;
width: 20px;
height: 20px;
transform: scale(0);
transform-origin: center center;
border: 6px solid rgba(61, 182, 228, 0.68);
border-radius: 100%;
transition: all .5s;
opacity: 1;
background-color:rgba(61, 182, 228, 0.50);
}
.circle_1.show_cir_1 {
transition: all .5s;
transform: scale(.9);
opacity: .3;
}
.circle_1.show_cir_1.show_cir_1_hide{
opacity:0;
}
.circle_2{
position: absolute;
display: block;
width: 100%;
height: 100%;
transform: scale(0);
transform-origin: center center;
background-color:#f9f9f9;
border-radius: 100%;
transition: all .5s;
opacity: 1;
top: 1px;
left: 1px;
}
.circle_2.show_cir_2{
transition: all .7s;
transform: scale(.5);
}
.load_cir {
position: absolute;
top: -3px;
left: -3px;
width: 100%;
height: 100%;
transform: scale(.8);
transform-origin: center center;
opacity:0;
transition: all .5s;
}
.load_cir.show_load_cir{
opacity:1;
transition: all .5s;
}
svg.spinner {
width: 40px;
height: 40px;
x: 0px;
y: 0px;
viewBox: 0 0 40 40;
}
svg.spinner circle {
fill: transparent;
stroke: #4389f2;
stroke-width: 6;
stroke-linecap: round;
stroke-dasharray: 110.6;
-webkit-transform-origin: 20px 20px 0;
-moz-transform-origin: 20px 20px 0;
-ms-transform-origin: 20px 20px 0;
-o-transform-origin: 20px 20px 0;
transform-origin: 20px 20px 0;
-webkit-animation: spinner 2s linear infinite;
-moz-animation: spinner 2s linear infinite;
-ms-animation: spinner 2s linear infinite;
-o-animation: spinner 2s linear infinite;
animation: spinner 2s linear infinite;
}
@-webkit-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
stroke-dashoffset: 26.4;
}
50% {
-webkit-transform: rotate(540deg);
stroke-dashoffset: 110.6;
}
100% {
-webkit-transform: rotate(1080deg);
stroke-dashoffset: 26.4;
}
}
@-moz-keyframes spinner {
0% {
-moz-transform: rotate(0deg);
stroke-dashoffset: 26.4;
}
50% {
-moz-transform: rotate(540deg);
stroke-dashoffset: 110.6;
}
100% {
-moz-transform: rotate(1080deg);
stroke-dashoffset: 26.4;
}
}
@-ms-keyframes spinner {
0% {
-ms-transform: rotate(0deg);
stroke-dashoffset: 26.4;
}
50% {
-ms-transform: rotate(540deg);
stroke-dashoffset: 110.6;
}
100% {
-ms-transform: rotate(1080deg);
stroke-dashoffset: 26.4;
}
}
@-o-keyframes spinner {
0% {
-o-transform: rotate(0deg);
stroke-dashoffset: 26.4;
}
50% {
-o-transform: rotate(540deg);
stroke-dashoffset: 110.6;
}
100% {
-o-transform: rotate(1080deg);
stroke-dashoffset: 26.4;
}
}
@keyframes spinner {
0% {
transform: rotate(0deg);
stroke-dashoffset: 26.4;
}
50% {
transform: rotate(540deg);
stroke-dashoffset: 110.6;
}
100% {
transform: rotate(1080deg);
stroke-dashoffset: 26.4;
}
}
p.ajax_complate {
background-color: #3e13ea;
color: #fff;
margin: 50px 0 0 0;
padding: 5px;
display: block;
position: relative;
width: 100px;
cursor:pointer;
}
.tick{
stroke-dasharray: 50;
stroke-dashoffset: 50;
-webkit-transition: stroke-dashoffset 1s 0.5s ease-out;
-moz-transition: stroke-dashoffset 1s 0.5s ease-out;
-ms-transition: stroke-dashoffset 1s 0.5s ease-out;
-o-transition: stroke-dashoffset 1s 0.5s ease-out;
transition: stroke-dashoffset 1s 0.5s ease-out;
}
.drawn svg .path{
opacity: 1;
stroke-dashoffset: 0;
}
.complete_save {
position: absolute;
width: 100%;
height: 100%;
transform: scale(1.5);
top: -8px;
left: -2px;
}
.complete_save svg {
width: 30px;
height: 30px;
x: 0px;
y: 0px;
viewBox: 0 0 40 40;
}
<div class="set_as_default_color">
<label>
<input type="checkbox" name="save_default_colors" id="save_default_color">
<div class="box_layer"></div>
<div class="circle_1"></div>
<div class="circle_2"></div>
<div class="load_cir">
<svg class="spinner">
<circle cx="20" cy="20" r="15"></circle>
</svg>
</div>
<div class="complete_save">
<svg>
<polyline class="tick path" style="fill:none;stroke:green;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:10;" points="
11.6,20 15.9,24.2 26.4,13.8 "/>
</svg>
</div>
</label>
<p class="lbl_text">i am not a robot</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</div>