ReCaptcha3: How to call execute when user takes the action? - javascript

I managed to get ReCaptcha3 working when including it like this:
<script src="https://www.google.com/recaptcha/api.js?render=mykey"></script>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('mykey', {action: 'homepage'}).then(function(token) {
document.getElementById("googletoken").value= token;
});
</script>
However, in the docs I found the following note:
Note: reCAPTCHA tokens expire after two minutes. If you're protecting an action with reCAPTCHA, make sure to call execute when the user takes the action.
Since I use the reCAPTCHA on a contact form, its likely that a user will take more then two minutes to write something.
Therefore, I tried to execute the key on submit (the alerts are only for testing):
<script src="https://www.google.com/recaptcha/api.js?render=mykey"></script>
<script>
grecaptcha.ready(function() {
document.getElementById('contactform').addEventListener("submit", function(event) {
alert('hi');
grecaptcha.execute('mykey', {action: 'homepage'}).then(function(token) {
alert('Iam invisible');
document.getElementById("googletoken").value= token;
});
}, false);
});
</script>
Now "Hi" is promted, but "Iam invisible" won't show up. Thus, it I get a missing-input-response on the server side. Why is then not fired inside addEventListener?

The problem is that the form is submitted before the async call grecaptcha.execute is complete. To fix the issue, one need to submit it manually:
<script src="https://www.google.com/recaptcha/api.js?render=mykey"></script>
<script>
grecaptcha.ready(function() {
document.getElementById('contactform').addEventListener("submit", function(event) {
event.preventDefault();
grecaptcha.execute('mykey', {action: 'homepage'}).then(function(token) {
document.getElementById("googletoken").value= token;
document.getElementById('contactform').submit();
});
}, false);
});
</script>

Related

Refreshing Captcha on Ajax call

I have the following code with which I used to refresh a captcha image via JavaScript. Is there anyway I can also achieve that using an AJAX request?
<script>
function refreshCaptcha() {
$("#captcha_code").attr('src','captcha_code.php');
}
</script>
<button name="submit" onClick="refreshCaptcha();">Refresh Captcha</button>
Yes it's possible, but then you need to handle session manually!
<script>
$(".RefreshCaptcha").click(function () {
$.post('captcha_code.php', function(data, status){
$("#captcha_code").attr('src', data);
console.log("ajax log: " + status);
});
});
</script>
<button class="RefreshCaptcha">Refresh Captcha</button>
w3shcools ajax.post
You can use the following code.
<script>
$(document).ready(function() {
setInterval(function() {
$.post('captcha_code.php', function(data) {
$('#captcha_code').html(data);
});
}, 1000);
});
</script>
Yes AJAX can be used to update the update the image via Javascript. Because the code already uses jQuery, a simple way would be to use $.post() to post to the PHP script. Presuming that captach_code.php merely returns the image source (e.g. base-64 encoded string), you can set the src attribute to the response value (e.g. in the function updateImage() below).
function refreshCaptcha() {
$.post('captcha_code.php', updateImage);
}
function updateImage(response) {
$("#captcha_code").attr('src',response);
}
See it in action in this phpfiddle. Note - there is no control of the filenames so PHP_SELF is used instead of captcha_code.php.
$.post() returns a jqXHR object, which implements the Promise interface. Because of this, .done() and other similar functions can be used instead of specifying the success callback:
function refreshCaptcha() {
$.post('captcha_code.php')
.done(function(response) {
$("#captcha_code").attr('src',response);
})
.fail(function() {
//fail handler...
})
.always(function() {
//handler for all cases
});
}
See it in action in this phpfiddle.

Explicitly Rendering ReCaptcha - Onload Function Not Firing

From the documentation I understood that in order to change the language of the recaptcha I have to render it explicitly.
The problem is, however, that it's not really showing up, and the onload is not even called.
When I try to render it automatically it does work.
Here's the code:
In the HTML head: (I have also tried putting this at the end of the body tag)
<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit&hl=iw" async defer></script>
In the HTML form:
<div id="recaptcha"></div>
Javascript:
var recaptchaCallback = function() {
console.log('recaptcha is ready'); // not showing
grecaptcha.render("recaptcha", {
sitekey: 'My Site Key',
callback: function() {
console.log('recaptcha callback');
}
});
}
I just copied your code, used my own Site Key and it works.
The code I used is:
<html>
<body>
<p>ReCaptcha Test</p>
<div id="recaptcha"></div>
<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit&hl=iw" async defer></script>
<script type="text/javascript">
var recaptchaCallback = function () {
console.log('recaptcha is ready'); // showing
grecaptcha.render("recaptcha", {
sitekey: 'SITE_KEY',
callback: function () {
console.log('recaptcha callback');
}
});
}
</script>
</body>
</html>
Check your code carefully, as just a single character typo can stop things from working.
Make sure that your onload method is defined before the recaptcha script. Otherwise you will have a race condition where the recaptcha script could be attempting to call your method before it is defined (especially if the recaptcha script is cached).
From the documentation for onload https://developers.google.com/recaptcha/docs/display
Note: your onload callback function must be defined before the
reCAPTCHA API loads. To ensure there are no race conditions:
order your scripts with the callback first, and then reCAPTCHA
use the async and defer parameters in the script tags
For example:
<div id="recaptcha"></div>
<script type="text/javascript">
var recaptchaCallback = function () {
console.log('recaptcha is ready'); // not showing
grecaptcha.render("recaptcha", {
sitekey: 'SITE_KEY',
callback: function () {
console.log('recaptcha callback');
}
});
}
</script>
<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit&hl=iw" async defer></script>
My problem was that I did not realise that the second callback is only fired upon submission of the form - whereas the first callback is executed on page load.
HTML
<div id="captcha"></div>
<script src='https://www.google.com/recaptcha/api.js?onload=recaptchaReadycallback&render=explicit' async defer'></script>
JavaScript
// Render captcha and set call back function on api.js load finish
function recaptchaReadycallback(){
grecaptcha.render('captcha', {
'callback' : recaptchaCheckedCallback,
'expired-callback': recaptchaExpiredCallback,
'sitekey': 'YOUR-SITE-KEY'
});
}
// On expiry do stuff. E.g. show error
function recaptchaExpiredCallback(){
grecaptcha.reset();
// Show 'check the bloody box' error
};
// On not a robot confirmation do stuff. E.g. hide error
function recaptchaCheckedCallback(){
// Hide 'check the bloody box' error
}

Interplay between <form> and .ajax()

Folks,
I'm learning Ajax by tinkering. At first, I had a form with button, which made an Ajax call to a dummy controller action. The HTML and JavaScript on the client side.1
<form method="post">
<button name="btnSaveProject" title="When you save this project, it willl be available for 30 days.">
Save
</button>
</form>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.1.min.js"></script>
<script>
$(document).ready(function () {
$("button[name='btnSaveProject']").click(function () {
console.log("make ajax call");
$.ajax({
url: "/Project/Save",
type: "GET",
timeout: 8000,
cache: false
}).done(function () {
console.log("ajax call successful");
}).fail(function (jqXHR, textStatus) {
console.log("something went awry. " + textStatus);
}).then(function () {
console.log("always just in case");
});
});
});
</script>
A strange thing was happening when I clicked the button. The Ajax call would reach the server (I know thins because I had a break point in the controller action, which triggered). But neither neither .done(), nor .fail(), nor .always() was getting called back on the client-side.
Then I have moved the <button> out of the <form>, and now .done(), and .always() get called back as expected. There seems to be some interplay between the can Ajax call. What is this interplay? Where can I learn more about it? What do I have to do to be able to use Ajax inside a <form>?
Here's the server-side code, but I suspect that it's a non-factor.
// AJAX: /Project/Save
public ActionResult Save() {
System.Threading.Thread.Sleep(600); /// <bring-up>A bit of latency to make the Ajax call more noticeable.</bring-up>
return Json("lorem ipsum", JsonRequestBehavior.AllowGet);
}
1 I have stripped down the code and kept only the parts that I think are applicable to the question. If I have stripped down too much, please let me know: I'll post more code.
You can add a type to your button:
<button type="button" name="btnSaveProject"
or just prevent the defaults of button to submit the form with event.preventDefault():
$("button[name='btnSaveProject']").click(function (e) {
e.preventDefault();
// other code as is
});
Since the button is in a form its default click action is to submit the form, So in your case as soon as the ajax request is sent the actual page is submitted which I think is reloading the page causing the callback handler to unload that is why those are not getting called
One solution is to prevent the default action of the click event by calling event.preventdefault()
$(document).ready(function () {
$("button[name='btnSaveProject']").click(function (e) {
//prevent the default action of the button click which is to submit the form
e.preventDefault()
console.log("make ajax call");
$.ajax({
url: "/Project/Save",
type: "GET",
timeout: 8000,
cache: false
}).done(function () {
console.log("ajax call successful");
}).fail(function (jqXHR, textStatus) {
console.log("something went awry. " + textStatus);
}).then(function () {
console.log("always just in case");
});
});
});
But since you are using a form, instead of a button click event it will be better to use a form submit event like
$(document).ready(function () {
$("form").submit(function (e) {
//prevent the default action of the button click which is to submit the form
e.preventDefault()
console.log("make ajax call");
//your ajax code
});
});
Another option is to set the type of the button to button so that the form submit will not be triggered like
<button type="button" name="btnSaveProject" title="When you save this project, it willl be available for 30 days.">Save</button>

Independent jquery functions execute consecutively when one is called

My problems seems basic, yet I have tried a lot of different ways of putting these functions on one html file to no avail. The problem is that, when the 1st function is called, the second also runs, leaving me with the results of the second function all the time. I have no idea what I am doing wrong, please help. Here is the code in question.
<script>
$(document).ready(function () { // Make sure the elements are loaded on the page
// Listen for a click event on the button
$('#buttonON').click(funct);
$('#buttonOFF').click(funct2);
});
// Now define the function
function favfunct(e) {
// Stop the page from "following" the button (ie. submitting the form)
e.preventDefault();
e.stopPropagation();
// Insert AJAX call here...
$.ajax("carstatusupd.php", {
// Pass our data to the server
data: { "username" : "sibusiso", "caron" : "1", "caroff" : "0"},
// Pass using the appropriate method
method: "POST",
// When the request is completed and successful, run this code.
success: function (response) {
// Successfully added to favorites. JS code goes here for this condition.
}
});
function funct2(e) {
// Stop the page from "following" the button (ie. submitting the form)
e.preventDefault();
e.stopPropagation();
// Insert AJAX call here...
$.ajax("carstatusupd.php", {
// Pass our data to the server
data: { "username" : "sibusiso", "caron" : "0", "caroff" : "1"},
// Pass using the appropriate method
method: "POST",
// When the request is completed and successful, run this code.
success: function (response) {
// Successfully added to favorites. JS code goes here for this condition.
}
});
}
</script>
You have omitted the closing brace from the function favfunct().
Please use this,
<script>
$(document).ready(function () {
function funOne(){
};
function funTwo(){
};
$('#buttonON').live('click',function(){
funOne();
});
$('#buttonOFF').live('click',function(){
funTwo();
});
});
NOte: initialize function before use and initialize them into document ready.

Form submit using jquery & passing values

I want to accomplish the following using jQuery:
frm_rooms.action="create_rooms.php?action=Save";
frm_rooms.submit();
I tried following jQuery but it doesn't work:
$('#frm_rooms').submit(function(event) <br/>{
$.post("create_rooms.php", { action: "Save" } );
});
Do it like this:
$('#frm_rooms').submit(function(event){
$.post("create_rooms.php", {action: "Save" }, function(){
alert("Data saved");
});
return false; //This is vital
});
If you want the parameters to be passed in the query string (GET method) use $.get instead of $.post.
EDIT: Thinking better, if you have fields inside your form that you want to be submitted, you should do:
$('#frm_rooms').submit(function(event){
$.post("create_rooms.php?action=Save", $(this).serialize(), function(){
alert("Data saved");
});
return false; //This is vital
});
Hope this helps. Cheers
Have you tried to use preventDefault() in your submit-function?
$('#frm_rooms').submit(function(event)
{
event.preventDefault();
$.post("create_rooms.php", { action: "Save" } );
});
Also be aware that if you also have an input-element within your form, which name is 'submit'. The submit-method of jQuery won't work.
Add return false; after $.post() to avoiding page reloading.
Try this -
$('#frm_rooms').submit(function(event)
{
$.post("create_rooms.php", {action: "Save" } );
event.preventDefault();
});
If you have an input element of type submit inside that form, then this method won't work. In that case, you will have to do something like following -
$('#mySubmitButton').click(function(event) // Suppose the id of that
// submit button is mySubmitButton
{
$.post("create_rooms.php", {action: "Save" } );
event.preventDefault();
});
If you want to provide success/failure message to the user, then modify the $.post method like this -
$.post("create_rooms.php", {action: "Save" }, function(data)
{
// data contains server response.
});
You can add .click() method to your button:
$('#button').click(function() {
//...
$('#form').attr('action', 'action.php');
return false;
})

Categories