I am trying to use an invisible re-captcha v2 on a form that is submitted through JS. Every example I see online shows a regular plain HTML submitted form with a specified action and method, but I am using preventDefault() on my form to submit it with ajax. It seems like such a simple thing but I've been searching for hours and can't find a single person online who has ever done this.
HMTL:
<form id="form-login">
<!-- ...form fields... -->
<div
class="g-recaptcha"
data-sitekey="<site_key>"
data-size="invisible"
></div>
<button class="uk-button uk-button-primary" type="submit">Submit</button>
</form>
JS:
$('#form-login').submit(function(event) {
event.preventDefault();
console.log(grecaptcha.getResponse()); // <-- always comes back empty
});
I can see that the captcha is initializing because I can see the icon in the bottom right.
I've seen grecaptcha.execute() but it doesn't seem to do anything for me.
There are no errors in the console.
Recently I had a problem like you, making captcha invisible created a lot of issues for me e.g. https://github.com/google/recaptcha/issues/269 which is still an opened issue on GitHub.
I solved it with dynamically genarated captcha on each time form is submitted. Here is a bit of code I used. (commented code is a call to backend to verify response with Google API).
https://gist.github.com/ANTOSzbk/75ed7003e914162550f61399122a3bd4
Then you just use my function like this:
$('#form-login').submit(async function(event) {
event.preventDefault();
const response = await captchaVerification();
if (response) { } // proper submit code execution
else { } // on invalid captcha response
});
Related
Built a form with HTML, CSS, Javascript linked to a Google Sheet. Built in VSCode.
TWO QUESTIONS:
1/ A pop-up box is supposed to pop up on form submission saying "Application Submitted!" if filled out with required fields. The pop-up box is not showing up -- but the data is being processed into the linked Google Sheet. The application instead just reloads.
2/ If filled out incorrectly, a pop-up box is supposed to pop up saying "Error!". However, even if filled out incorrectly, the data is being processed into the linked Google Sheet without this pop-up (and then reloading the page like above). It's like the Javascript is overriding the HTML code such as requiring email to be in an email format, etc.?? The HTML worked prior to writing in the Javascript linking to the Google Sheet.
JAVASCRIPT:
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<script>
function SubForm (){
$.ajax({
url:'[NOTE: URL IS HERE]',
type:'post',
data:$("#survey-form").serializeArray(),
success: function(){
alert("Application Submitted!")
},
error: function(){
alert("Error!")
}
});
}
</script>
ALSO THE HTML FOR THE BUTTON:
<button onclick="SubForm()" class="btn submit" type="submit" value="Let's Bop!" />Let's Bop!</button>
I think there are two things to observe here.
First,
Let's see what is the form action? or the action="" part of your form? Since you are using a button type='submit' and assuming this is inside your form, the form will submit and perform the action part.
If this is the case then you need your form to stop doing default behavior on submit so that the page stays and give time to your ajax to finish up so that alert can appear.
Second,
Let the form handle onSubmit, and remove onClick from the button as it is a submit button let it submit the form, but handle the onsubmit event. Even in this case, we will have to stop the form to perform its default behavior.
Here is a codepen you can refer https://codepen.io/vbrmnd/pen/eYjbRgw
Ran into a small oddity here.
When I submit a form, I have a JS click event listener on the submit button - this is to remove the HTML values and add a thank you message (pretty simple stuff).
Oddly, however, it seems that the JS is acting before the PHP because all emails have blank values until I remove the JS that removes the HTML values.
The code is:
pretty simple HTML form (this has been cut down to show what the problem might be)
HTML:
<form method="post" action="contactForm.php" id="contact-form" target="hiddenForm">
<textarea class="form-control input-outline reqItem" rows="6" cols="50" name="message" form="contact-form" placeholder="Message" required></textarea>
<button type="submit" class="btn btn-outline rounded-0 d-block d-md-inline-block submit-button">Submit</button>
</form>
JS (has an event listener on the submit button for click):
if(document.querySelector('.submit-button')){
document.getElementById('contact-form').addEventListener('submit', function(e){
// Check that form is valid
if(document.querySelector('form').checkValidity()){
document.querySelectorAll('.checkbox').forEach(e => {
if(e.classList.contains('checked')){
e.classList.remove('checked')
}
})
// Change messagae to thank you
e.target.classList.add('submit-hide')
document.querySelector('.submit-thankyou').classList.add('submit-show')
// remove all field values <<<<< issue seems to be being caused here
document.querySelectorAll('.form-control').forEach(e => {
// this causes the form to lose all data
e.disabled = true;
})
}
})
}
The e.disabled = true;
Is going over each form input and making it disabled, I have also used e.value = "".
Both of these stop PHP action in the form of setting variables as the values of the inputs.
So the question is,
am I doing something wrong (maybe right.....?)
is there a way to allow the PHP to act first getting the values before removing them with the JS?
Feel free to ask any questions here.
Any insights are welcome.
The submit event as part of the browser's form submission algorithm, before the browser even looks at the form's fields, so any changes you make as part of that event will be submitted to the server and you'll have access to them from PHP.
In order to change the form without affecting the submission, you'll have to do that at some point after the browser's form submission finishes, but before the page navigates to the form's action:
document.getElementById('contact-form').addEventListener('submit', function(){
setTimeout(function() {
// Modify the form here.
}, 0);
});
Remember that setTimeout(func, msecs) means "run func whenever you have the chance, but no earlier than msec milliseconds". While the browser is running the form submission algorithm, no Javascript code (other than that for the synchronous events submit and formdata) can run, so the earliest chance for func to run will be after the form is submitted.
I'm trying to do something that seems easy but I cannot get it to work.
I'm using Braintree dropin UI and I have submit button.
I need to disable the button while processing and I cannot find a good event to attach to.
var ct = 'tokenhere';
var bt = braintree.setup(ct, 'dropin', {
container: 'braintreedropin',
});
<form id="PayByBrainTreeCheckout" method="post">
<div id="braintreedropin"></div>
<input type="submit" value="Pay">
</form>
I tried $('#PayByBrainTreeCheckout').submit(function(){/*disable button*/}) but this is also disabling the button if there is a validation error in the form.
Any ideas? Thanks
I work at Braintree as well. You're correct that the customer can hit the submit button twice while the transaction is being submitted, but you don't have to worry about the customer being charged twice, as the second transaction will fail (the nonce generated by the credit card can only be used once). Furthermore, the immediate visual feedback on the form after submission is designed to let customers know their button press is being processed.
If you do want to do more complex things (such as adding a custom callback to disable the submit button), our custom integration is a good option.
As Mat mentioned, feel free to reach out to support#getbraintree.com if you need further assistance with your integration!
Braintree is about to add such a callback. Here's the github issue: https://github.com/braintree/braintree-web/issues/38
Will result in something like this:
braintree.setup(TOKEN, 'dropin', {
container: 'my-container',
onError: function (payload) {
if (payload.type === 'validation:failed') {
// re-enable button
}
}
});
I made a working example of how to use Braintree with WebForms.
https://github.com/StavrosD/BrainTree-PayPal-DotNet
I describe on the README.md the workflow.
I have a strange issue with my code I can't seem to figure out. I'm relatively new to js and utilizing http requests to retrieve json data however I've been able to come up with code that works, for the most part.
Essentially the workflow is as follows: I have a user enter some form field values and select the submit button. Onsubmit the the apiCall() function is called which then calling the createXMLHttpRequestObject() and constructApiURL(searchtype) functions creates, populates, and sends the xmlHttpRequest Object via the proxy to the search api url. Once the result is returned the handleResults() function is called which then parses and displays the results in the apropriate div container using the handleResultsContainer() function.
Everything works when I step through the code via firebug. The object is created, sent via the proxy to the search api, the results are returned and displayed but once the focus returns to the function onsubmit(event) {callApi();} and the contents then clear!?! I don't know if the page is reloaded or something else is going on.
Now if I change the initial trigger from a form submit to a button onclick it works without issues. The user selects the button, the search results are retrieved and displayed until the user selects the button again at which point the results are cleared and the new results are displayed. The problem is that I have to hard code the parameters I would normally be getting from the form.
Has anyone experienced this or sees something with how the code is being read by the browser that could cause this? My Pseudo code is below.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function createXMLHttpRequestObject() {
-- code to create the XMLHttpRequestObject based on browser type --
}
function constructApiURL(searchtype) {
-- code to create the api url using the form values & proxy url --
}
function handleResultsContainer () {
-- code to create/remove search results display div
}
function handleResults(jsndata) {
-- code to parse and display results here --
}
function callApi() {
-- code to create XMLHttpRequestObject, populate it, and send it --
}
</script>
</head>
<body>
<form id="basicform" name="mashsearch" onsubmit="callApi()">
-- Code for user input fields which are then used by constructApiURL --
<input type="submit" id="searchbtn" value="Search!"/>
</form>
//Div displaying a Search Results Loading… message which is hidden/displayed//
<div id='loadingDiv' style="display:none">Search Results Loading...</div>
//Div used to display the search results
<div id='json'></div>
</body>
</html>
Change your onsubmit to :
onsubmit="callApi();return false;"
Alternatively you could add return false to the bottom of your callApi() method and change your onsubmit to be onsubmit="return callApi()"
If you do not the page will submit and reload as its normal behaviour would.
I have a form with a submit button and it works fine, but I now have a user request to make the form get saved (posted to save action) if a link on the page is clicked and the form is "dirty".
I've got the logic in place by having an isDirty JavaScript variable, now I would like to post the form from the JavaScript function when it is dirty.
My form declaration is as follows:
<form id="formSmart" action="<%= ResolveUrl("~/SmartForm/Proceed") %>"
method="post" enctype="multipart/form-data">
and my JavaScript is:
function checkLink() {
if (isDirty) {
$("#formSmart").submit();
}
}
The proceed action doesn't get called, yet when I click the submit button on the form it works fine. What am I doing wrong in the JavaScript?
Note: The call to checkLink() works fine, the ultimate problem is that $("#formSmart").submit(); is not posting to the Proceed action.
You have the correct way of submitting the form based on what you have posted and the names match up.
Are you sure you are calling checkLink and is isDirty equal to true?
Put and alert('Test'); right before you submit and in the if scope.
EDIT: To hookup your event you need to do the following:
$('#yourLinkID').click(checkLink(); return false;);
Note the return false which will cause your link to not execute a navigate. If you want the link to navigate, you can just remove that part.
Sounds like the requirement is that 'a link on the page is clicked'.
Perhaps attach this event to all the <a> tags on the page.
$(document).ready(function() {
// all <a> tags get the checkLink attached to them
$("a").click(checkLink());
});
your problem is that the browser navigate before the page performs your submit.
the solution is suspending the navigation till you save the form.
The UGLY solution:
you could do it buy saving the clicked url at a hidden field,
returning false to stop the navigation,
and after submit check for a value there and if it exists do navigation
A better solution:
post the form via ajax and after the ajax call completes(no need to check for success or error) perform the navigation(to make it really easy just use ajaxForm ajaxForm plugin)
the only problem with this solution is if the link has target="_blank" because then you have to use window.open which might be blocked by popup blockers
you can play with a simple jsbin sample i prepared showing this
this example post some values to an older version of this page + navigate to google, open fiddler and see that it first post and then navigate.
If you went to the jsbin page stop reading here
here is the Html:
<form id="formSmart" action="http://jsbin.com/oletu4/edit" method="post">
<input type="text" name="someLie" />
<input type="text" name="someLie2" />
<input type="submit" value="submit" />
<a id="lnkNavOut" href="http://www.google.com">www.google.com</a>
here is the JS:
$(document).ready(function(){
$("#lnkNavOut").click(function(){
var jqFormSmart = $("#formSmart");
//check here if the form is dirty and needs to be saved
var jqClickedLink = $(this);
$.ajax({
url: jqFormSmart.attr("action"),
type: "POST",
data:jqFormSmart.serialize(),
complete:function(){
location = jqClickedLink.attr("href");
}
});
return false;//stop navigation
});
});​