ReCaptcha v2 client side events - javascript

Does ReCaptcha v2 expose any client side events? I am looking specifically to identify when the Captcha response has been returned once the box is ticked, so I can reveal the "Continue" button below.
Without this it is possible for the user to click the checkbox then quickly click the submit button before the captcha response is back.
I could possible add my own click event handler to the class recaptcha-checkbox-checkmark and poll the visiblity of the tick, I just wondered if there was a simpler way to do this?
$(".recaptcha-checkbox-checkmark").click(function() {
//...Poll for visibility of tick
});

Another solution is to set data-callback directly on the g-recaptcha div, like this
<script type="text/javascript">
var imNotARobot = function() {
console.info("Button was clicked");
};
</script>
<div class="g-recaptcha" data-callback="imNotARobot" data-sitekey="key"></div>

You can configure reCAPTCHA to give a callback on successful validation using the data-callback attribute on the g-recaptcha tag or via the 'callback' parameter if using explicit rendering.
See
https://developers.google.com/recaptcha/docs/display#render_param
Example using explicit rendering:
var myCallback = function(val) { console.log(val); };
grecaptcha.render(
document.getElementsById('my-recaptcha-placeholder'),
{
callback: myCallback,
sitekey: mySiteKey
});

Related

Semantic-UI avoid form validation trigger for some button click events

So by default Semantic-ui doesn't have any way to prevent clicks which trigger the validation, once the form has been setup, as the validation is handled onsubmit directly. This is important if you have multiple buttons on the page and only want some to trigger the validation and the rest perhaps to be able to postback, or do other things minus triggering the form validation.
I checked some answers that talk about changing the input from a type=submit to a type=button, but you lose the design ability especially the ability to add an icon and is not the ideal solution.
Am posting this question, since my answer to this question, got deleted by the moderator, even though I have a working fiddle and a detailed answer on how to achieve this.
Reposting the entire answer here, incase anyone needs help on this.
I was able to implement this in a different way, as the button type=button control while ignoring the validations, did not submit, and if I did submit manually the default event handler of semanticui would intervene and show the validation errors.
My use case two buttons, one a save draft and the other a finalize (final save). The first one had to save the data as is, without triggering the validations, while the other would trigger validations and then save.
I am also implementing all the validators using data attributes that I custom implemented for this project, hence the form validator is inside a JS file.
In my form validation's failure method, I included a delegate function which I could set on my page and depending on which button clicked it, then be able to return true or false.
My form validator inside a JS file
$('.ui.form').form({
inline: true,
on: 'submit',
fields: formFields,
transition: 'fade',
keyboardShortcuts: false,
onFailure: function () {
var returnValue = false; //Default to false, since validations failed
//If the delegate is present, fire it to evaluate
if (typeof window.delegValidate == 'function') {
returnValue = window.delegValidate();
}
//Ignore the toast if the delegate evaluated to TRUE
if (!returnValue) {
$('body')
.toast({
title: 'Unable to save',
message: 'Please enter all required field data before saving.',
classProgress: 'red',
showProgress: 'top',
progressUp: true,
position: 'bottom right',
showIcon: 'red exclamation triangle'
});
}
return returnValue; // false is required if you don't want to let it submit
}
});
and on my page I attached a function to the window, since my form validation is inside a JS file.
Page function
//For all postback buttons, save the id value in a hidden field for use in the delegate
$('.postbackButton').bind('click', function (e) {
$('#ButtonClicked').val(this.id); // a hidden field on the page
});
//setting the delegate for use in the form validations
window.delegValidate = function () {
//For the save button, just ignore the validations and return true
//This in turn is invoked by the failure method of the form validation that is
//dynamically attached to the page, and hence this return value is respected
//over the false that is otherwise sent back for when we want to interrupt the page
//since there are errors normally.
if ($('#ButtonClicked').val() == 'Save')
return true;
else // if value is finalize, let it return false
return false;
}
For other pages where I don't want this functionality, I can simply not write the delegate method and the default validation fires as expected on the submit button.
Also posted here Ignore SemanticUI validation on some buttons
Hope this helps anyone looking for a better way of handling this scenario.

Warn user about unsaved changes to a form, when a form is being replaced during an AJAX call?

I'm new to Javascript and JQuery, and I'm implementing a warning to users that displays when they have made unsaved changes to a form's input/select/textarea elements if they navigate away from a page. I currently have the following which works fine when they leave a static form page:
/*
* Warn users when leaving a page with unsaved content, watches elements: (input, textarea, select) unless
* they are tagged with the "noWarning" class
*/
$(document).ready(function() {
$(document).on('change', 'input:not(.noWarning),textarea:not(.noWarning),select:not(.noWarning)', function () {
window.onbeforeunload = function(e) {
return 'You have unsaved changes';
};
});
});
The only page where it does not work, is in our main editing page. This page, unlike the others, has multiple tabs for editing different aspects of an item, which when clicked, trigger an AJAX call which replaces the content div with the appropriate form for editing the different aspect.
No warning dialog is displayed when a user clicks on a tab though, so any unsaved changes to the input are lost.
My intuition is that because the url is not changing, onBeforeUnload() is not executing. So I would have to check for any changes directly in the function which handles the AJAX call for replacing the form when a tab is clicked:
function clickedTabbedMenu() {
// This function replaces the content div with a new div and form
}
So my question is, how do I go about checking if any changes have been made to the elements in the current form before I replace the content div with another??? Can I directly call the "change" event listener for a true/false??? Or perhaps a different approach to handle this page's warning messages?
Any help is appreciated
Attach a change event handler to all the elements of the form. Have a variable outside the handler's scope dirty (or even a data on the form element) be set to false when a form is loaded, and true on every change event. Then, before replacing the form, check if dirty.
This would also be a good strategy for your non-AJAX pages as well - instead of setting the whole onBeforeUnload each time an element changes, just set onBeforeUnload once, and check if dirty inside it. This makes handling your AJAX and non-AJAX pages very similar.
EDIT: Untested because it's late and I need bed, but basically:
$(document).ready(function() {
var dirty = false;
$(document).on('change', 'input:not(.noWarning),textarea:not(.noWarning),select:not(.noWarning)', function () {
dirty = true;
});
function checkDirty() {
if (dirty) {
alert('You have unsaved changes');
return false;
}
return true;
}
// for non-AJAX pages
window.onbeforeunload = function(e) {
return checkDirty();
};
// for AJAX pages
$('.ajax_navigation_tab').on('click', function() {
if (!checkDirty()) {
// do the ajax thing
dirty = false;
}
});
});
I would try checking for and calling window.onbeforeunload() in your ajax script.
If it exists and returns a string, use it as an error message and halt the operation :)

isDirty check not working as desired

I'm using the following script to check if the forms content has changed to prevent the user from browsing away without saving their changes.
<script type="text/javascript">
var isDirty = false;
var msg = 'You have unsaved changes.';
$(document).ready(function(){
$(':input').change(function(){
if(!isDirty){
isDirty = true;
}
});
window.onbeforeunload = function(){
if(isDirty){
return msg;
}
};
});
</script>
The Save button currently looks like this:
<input type="submit" name="frmProjectAction" value="Save" onclick='selectAll(frmProjectResources,true);' />
This is working for the most part but I have two issues:
1. It fires even when the user clicks the Save button on my form. How can I prevent this?
2. It isn't detecting changes in the TinyMCE text box I have on my form. How can I detect changes in the TinyMCE text box as well as all the other fields on my form?
Thanks in advance - Dave
1: use a click() jquery function on the save button that sets isDirty to false. You need to add an id or a class to your save button first so you can target it with jquery. Let's say that you set the save button id to "savebutton" then you do the following:
$('#savebutton').click(function(){
selectAll(frmProjectResources,true); // <-- from your onclick="" attribute
isDirty = false;
})
you can notice that we have moved the selectAll(...) part from the onclick attribute of the save button to the jquery. Hence, you should remove the onclick attribute from the button.
2: TinyMCE has onchange_callback which you can use fire a function which sets isDirty to true. The onchange_callback is set when you initialize TinyMCE, and you give it the name of the function you want to fire whan the form is changed.
//first define the function
function setIsDirty(){
isDirty = true;
}
// then init the tinyMCE
tinyMCE.init({
... // some parameters
onchange_callback : "setIsDirty"
});
This way, you can control precicely what happens when editor is changed. If you just need to check if it has been edited or not before leaving the page, you can also use TinyMCE's own isDirty method
This is really only a solution to question number 1:
You would need one additional event handler, the one for onsubmit on your form.
In that event handler, you update isDirty to false (since you are saving the form now.. so it's no longer "dirty")
I can't comment on tinyMCE, as I've never worked with that.
plugins: "autosave"
autosave_ask_before_unload: true
toolbar: "restoredraft"

Can't refresh reCaptcha on JQuery Ajax return

I'm having a devil of a time trying to get Ajax to automatically refresh on a JQuery AJAX callback. I have a comment box with the messages being refreshed posted immediately upon validation of reCaptcha and it would be nice if the reCaptcha could refresh automatically in case someone wants to add another comment immediately afterward. Here's my return function:
$.post(url, formData, function(data) {
if (returnString.match(/^Error:/)) {
$("#interactionResults").html(data).show().fadeOut(6000);
}
else if (postNumber == 0) {
$('#newCommentDisplay').html(returnString).show();
$.post("http://www.google.com/recaptcha/api", "Recaptcha:reload()");
}
When I use:
$.post("http://www.google.com/recaptcha/api", "Recaptcha:reload()");
I get an error:
XMLHttpRequest cannot load http://www.google.com/recaptcha/api. Origin http://localhost:8888 is not allowed by Access-Control-Allow-Origin.
Fair enough, so I try to change that line with this one:
$('#recaptcha_reload_btn').trigger('click');
and still nothing is happening. Does anyone know what's going on?
in my html I have :
<div class="g-recaptcha" id='recaptcha' data-sitekey="xxxxxxxxxx"></div>
I use grecaptcha.reset();
example:
if (typeof $('#recaptcha') != "undefined") {
grecaptcha.reset();
}
Use
jQuery("#recaptcha_reload").click();
"#recaptcha_reload", the image itself, is the trigger. #recaptcha_reload_btn will NOT work, because the a-tag is NOT the trigger.
Recaptcha.reload();
( Recaptcha is already loaded )
if you are using new recaptcha 2.0 use this:
for code behind:
ScriptManager.RegisterStartupScript(this, this.GetType(), "CaptchaReload", "$.getScript(\"https://www.google.com/recaptcha/api.js\", function () {});", true);
for simple javascript
<script>$.getScript(\"https://www.google.com/recaptcha/api.js\", function () {});</script>
You have not bound a click handler to your element. From the jQuery docs:
.trigger( eventType [, extraParameters] )
Description: Execute all handlers and behaviors attached to the
matched elements for the given event type.
If you have not attached a handler to your element before calling trigger, there is no click handler to execute.
edit:
When you write $('#recaptcha_reload_btn').bind('click'); you actually set up a click handler, but one that does nothing. You have to tell that clickhandler what to do:
$('#recaptcha_reload_btn').bind('click',function() {
alert('you just clicked me');
};
If you do not set up a callback handler, the event is just registered but does not trigger any action. Combine this with the solution from this question Reload an iframe with jQuery and you should have your recaptcha doing what you want:
$('#recaptcha_reload_btn').bind('click',function() {
var iframe = document.getElementById('#recaptcha'); //use your own selector here!
iframe.src = iframe.src;
};
$( "#recaptcha_reload_btn" ).click();

Is there a way to delete a form element without using jQuery .remove()?

Using .remove() so that the select all check box is not submitted to the server.
However, it is visible to the user as the select all checkbox is "physically" removed from the web page, upon submit.
Instead, I would like removing the select all check box to appear seamless but NOT on the server side. i.e. - I would like to keep the input on the page but remove the element in the form array before it is sent.
Can I manipulate the element[] array of the form before it is sent to the server and delete it there?
Thank you.
If you disable the checkbox, it won't be sent along with the rest of the form:
$('#myInp').attr("disabled", true);
Using this method, you could disable the element during submit and enable it again immediately after:
$('#myForm').submit(function()
{
var $myInp = $('#myInp');
$myInp.attr("disabled", true);
window.setTimeout(function ()
{
$myInp.attr("disabled", false);
}, 0);
});
both Andy E and munch have viable solutions. Here's another:
Replace it with another, inert checkbox
$('#select-all-checkbox').replaceWith( '<input type="checkbox"/>' );
Of course, this can create issues if the form submission fails for some reason.
At the moment, it's not possible to manipulate the form data set (and it's something that I want to see in future versions of HTML too), but you can fake it by temporarily disabling the input during the submit:
$form.submit(function(){
$input.attr('disabled', true);
setTimeout(function(){
$input.removeAttr('disabled');
}, 0);
});

Categories