Google recaptcha callback not working with multiple reCAPTCHA - javascript

I have multiple google captchas on page. Code:
<script>
var qqqq =function(captcha_response){
console.log('?')
}
var CaptchaCallback = function(){
$('.g-recaptcha').each(function(index, el) {
grecaptcha.render(el, {'sitekey' : '{{ recaptcha_key}}', 'callback': 'qqqq', 'theme': 'dark'});
});
};
</script>
<script src='https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit' async defer></script>
On the page there are several blocks for reCAPTCHA:
<div class="g-recaptcha"></div>
All reCAPTCHA's render well, all with dark theme, all do verifying work, but the callback function does not get called.
When I tried single reCAPTCHA with data-callback attribute, it worked well.

I was facing the same issue. After checking the documentation again I found my problem. Try to remove the single quotation marks around your function name.
Like this:
<script>
var qqqq =function(captcha_response){
console.log('?')
}
var CaptchaCallback = function(){
$('.g-recaptcha').each(function(index, el) {
grecaptcha.render(el, {'sitekey' : '{{ recaptcha_key}}', 'callback': qqqq });
});
};
</script>
Maybe this helps someone else as well :)

Steps to implement multimple recaptcha with a callback method for disable the submit button
1) Add the reference
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
2) Add the Code that will render the captcha widget
<script>
var CaptchaCallback = function () {
grecaptcha.render('RecaptchaField1', { 'sitekey': 'xxx', callback: 'recaptchaCallback1'});
grecaptcha.render('RecaptchaField2', { 'sitekey': 'xxx', callback: 'recaptchaCallback2' });
grecaptcha.render('RecaptchaField3', { 'sitekey': 'xxx', callback: 'recaptchaCallback3' });
};
</script>
3) Add the method to remove the disable property on the submit button
$('#GetHelpButton').prop('disabled', true);
function recaptchaCallback1()
{
$('#GetHelpButton').prop('disabled', false);
}
4) Add the widget inside a form
<form id="formContact" method="post" class="login-form margin-clear" action="Landing/SendContactForm">
<div class="form-group has-feedback">
<label class="control-label">Correo electronico</label>
<input name="EmailContact" value="" id="EmailContact" type="text" class="form-control" placeholder="">
<i class="fa fa-envelope form-control-feedback"></i>
</div>
<div id="RecaptchaField1"></div>
<button id="GetHelpButton" type="submit" data-sitekey="xxxx" class="btn btn-info col-md-12 g-recaptcha">Send</button>

Try setting a unique ID for each div and then use a for loop to iterate through them. Something like this:
window.onloadCallback = function() {
var captcha = ['recaptcha1' ,'recaptcha2', 'recaptcha3']; //put your IDs here
for(var x = 0; x < captcha.length; x++){
if($('#'+captcha[x]).length){
grecaptcha.render(captcha[x], {
'sitekey' : '{{ recaptcha_key}}',
'theme' : 'dark',
'callback': function() {
console.log("Woof");
}
});
}
}
};

Related

Invisible Google Recapthca two in Sweetalert2

I saw the code snippets at Google reCaptcha within SweetAlert modal window , particularly the one without the jquery (the 1st answer)
But that solution makes the captcha box visible.
How do i make it invisible within Sweetalert? I will do a server backend validation
I looked at https://github.com/prathameshsawant7/multiple-invisible-recaptcha and included the entire code from init_recaptcha.js along with the "onOpen" feature of SWAL... but no luck. The captcha is not set in the form.
Any help will be appreciated> I need the invisible captcha as I will triggering several SWAL forms within the HTML tag of the sweetalert (needed for multiple inputs at time)
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/cover.css">
<script src="js/jquery1.11.1.min.js" type="text/javascript"></script>
<script src="js/sweetalert2#10.js"></script>
<script>
$(document).ready(function() {
$(document).on('click', '#comment_button', function(e) {
e.preventDefault();
//var M_user = "";
Swal.fire({
title: 'Add a comment to the page',
titleText: 'Add a comment to the page',
//included dynamically... :-)
width: '75%',
position: 'center',
showCancelButton: true,
showConfirmButton: false,
showCloseButton: true;
allowOutsideClick: false,
focusConfirm: false,
//grow: 'fullscreen',
allowEscapeKey: true,
html: '<div class="card"><form name="form2" id="form2" method="post" action="process3.php"><div class="form-group"><label for="InputText2">Enter Text (Recaptcha 2)</label><input type="text" class="form-control" id="text2" name="textmsg" placeholder="Enter random text" value="this_is_textmsg"></div><div class="form-group"><label for="InputText3">Enter Text :</label><input type="text" class="form-control" id="textv3" name="textmsg3" placeholder="Enter random text" value="this_is_textmsg3"></div><div id="recaptcha-form-2" style="display:none;"></div><input type="button" class="btn btn-primary" onclick="formSubmit(\'2\')" value="Submit" /></form></div>',
footer: 'We reserve the right to moderate your comments if we feel the need.',
onOpen: function() {
console.log('setting initial values, if any on onOpen');
/***
* #Created by: Prathamesh Sawant (prathameshsandeepsawant#gmail.com)
* #Date : 24/07/2017
* #description To handle Multiple Google Invisible reCaptcha Implementation
*/
/**************************************************************************\
* Step 1 - Initialize reCaptcha Site Key and Widget eg: widget_1 for Form 1
* Step 2 - In init function add code to create form submit callback action.
* Step 3 - Call renderInvisibleReCaptcha function by passing reCaptcha ID
* and createCallbackFn Response.
***************************************************************************/
"use strict";
var PS = PS || {};
var widget_1;
var widget_2;
var widget_3;
var recaptcha_site_key = 'my Real Site Key Goes here....removed for stackoverflow';
if (typeof PS.RECAPTCHA === 'undefined') {
(function(a, $) {
var retryTime = 300;
var x = {
init: function() {
if (typeof grecaptcha != 'undefined') {
//For Form 1 Initialization
if ($('#form1 #recaptcha-form-1').length > 0) {
var callbackFn = {
action: function() {
saveData('1'); //Here Callback Function
}
}
/*--- 'recaptcha-form-1' - reCaptcha div ID | 'form1' - Form ID ---*/
widget_1 = x.renderInvisibleReCaptcha('recaptcha-form-1', x.createCallbackFn(widget_1, 'form1', callbackFn));
}
//For Form 2 Initialization
if ($('#form2 #recaptcha-form-2').length > 0) {
var callbackFn = {
action: function() {
saveData('2'); //Here Callback Function
}
}
/*--- 'recaptcha-form-2' - reCaptcha div ID | 'form2' - Form ID ---*/
console.log('defining widget 2');
widget_2 = x.renderInvisibleReCaptcha('recaptcha-form-2', x.createCallbackFn(widget_2, 'form2', callbackFn));
}
//For Form 3 Initialization
if ($('#form3 #recaptcha-form-3').length > 0) {
var callbackFn = {
action: function() {
saveData('3'); //Here Callback Function
}
}
/*--- 'recaptcha-form-3' - reCaptcha div ID | 'form3' - Form ID ---*/
widget_3 = x.renderInvisibleReCaptcha('recaptcha-form-3', x.createCallbackFn(widget_3, 'form3', callbackFn));
}
} else {
setTimeout(function() {
x.init();
}, retryTime);
}
},
renderInvisibleReCaptcha: function(recaptchaID, callbackFunction) {
return grecaptcha.render(recaptchaID, {
'sitekey': recaptcha_site_key,
"theme": "light",
'size': 'invisible',
'badge': 'inline',
'callback': callbackFunction
});
},
createCallbackFn: function(widget, formID, callbackFn) {
return function(token) {
$('#' + formID + ' .g-recaptcha-response').val(token);
if ($.trim(token) == '') {
grecaptcha.reset(widget);
} else {
callbackFn.action();
}
}
}
}
a.RECAPTCHA = x;
})(PS, $);
}
$(window).load(function() {
PS.RECAPTCHA.init();
});
},
preConfirm: function(login) {
//run any stuff to do before login here
console.log('doing before preConfirm stuff....');
//let s_user_name = Swal.getPopup().querySelector('#s_user_name').value;
//M_user= s_user_name;
},
}).then(function(result) {
console.log('then function result initial');
if (result.value) {
console.log('Doing if result.value here...');
}
}) //swal.fire end
}); //function(e) ends
}); //doc ready ends
</script>
</head>
<body>
<div class="site-wrapper">
<div class="site-wrapper-inner">
<div class="cover-container">
<div class="masthead clearfix">
<div class="inner">
<center>
<h3 class="">Handle Multiple Invisible Recaptcha</h3>
</center>
</div>
</div>
<div class="inner cover">
<hr>
<form id="comment_form" name="comment_form_name"><button id="comment_button" class="coach_button">Leave a Comment...</button></form>
</hr>
<div class="mastfoot">
<div class="inner">
<p>Sample template by #Prathamesh-Sawant to implement multiple invisible recaptcha on single page dynamically.</p>
</div>
</div>
</div>
</div>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=explicit"></script>
<script src="js/form.js" async defer></script>
</body>
</html>
I figured it out
Basically, inside sweetalert2, captcha doesn't render...
I was anyway using multiple fields in SWAL... so I had to use fields inside the HTML parameter.
To address the invisible captcha, I took an idea from Invisible reCaptcha AJAX Call . From within sweetalert, using Swal.getPopup().querySelector('#field').value, in pre-confirm, I will populate hidden fields in the form that is outside of sweetalert and submit it via Ajax
Not a brilliantly clean solution but, hey, it works!

Ajax search doesn't work the second time (ASP.NET MVC)

I have a problem changing items after searching.
I looked at similar threads but found no solution there :(
It looks like the first time the page loads well - the first time the entire Index.cshtml page is loaded which contains a collection of books in the selected category.
There is a search engine on the page - after searching for "manual" - ajax correctly replaces elements with those containing "manual" in the name.
Then when I enter something into the search engine a second time (for example "exercises") - the content of the page does not change any more.
I tried to debug and I see that new items are correctly downloaded from the database - the condition "if (Request.IsAjaxRequest ())" is true and the items are passed to partial view - there the "foreach" loop goes through them. Unfortunately, after _Partial, nothing happens.
I can't find a mistake - the strangest thing is that the first ajax call works fine - only the second (and subsequent) bad.
CatalogController.cs
public ActionResult Index(string categoryName = null, string searchQuery = null)
{
if (categoryName == null)
categoryName = (db.Categories.Find(1)).Name;
var category = db.Categories.Include("Books").Where(x => x.Name.ToLower() == categoryName).Single();
var books = category.Books.Where(x => (searchQuery == null || x.Title.ToLower().Contains(searchQuery.ToLower()) || x.SubTitle.ToLower().Contains(searchQuery.ToLower()) || x.Level.ToLower().Contains(searchQuery.ToLower())) && !x.Inaccessible);
if (Request.IsAjaxRequest())
return PartialView("_PartialBooksList", books);
else
return View(books);
}
Index.cshtml
<form class="o-search-form" id="search-form" method="get" data-ajax="true" data-ajax-target="#booksList">
<input class="o-search-input" id="search-filter" type="search" name="searchQuery" data-autocomplete-source="#Url.Action("SearchTips")" placeholder="Search" />
<input class="o-search-submit" type="submit" value="" />
</form>
<div class="row" id="booksList">
#Html.Partial("_PartialBooksList")
</div>
#section Scripts
{
<script src="~/Scripts/jquery-3.5.0.js"></script>
<script src="~/Scripts/jquery-ui-1.12.1.js"></script>
<script>
$(function () {
var setupAutoComplete = function () {
var $input = $(this);
var options =
{
source: $input.attr("data-autocomplete-source"),
select: function (event, ui) {
$input = $(this);
$input.val(ui.item.label);
var $form = $input.parents("form:first");
$form.submit();
}
};
$input.autocomplete(options);
};
var ajaxSubmit = function () {
var $form = $(this);
var settings = {
data: $(this).serialize(),
url: $(this).attr("action"),
type: $(this).attr("method")
};
$.ajax(settings).done(function (result) {
var $targetElement = $($form.data("ajax-target"));
var $newContent = $(result);
$($targetElement).replaceWith($newContent);
$newContent.effect("slide");
});
return false;
};
$("#search-filter").each(setupAutoComplete);
$("#search-form").submit(ajaxSubmit);
});
</script>
}
_PartialBooksList
#model IEnumerable<ImpressDev.Models.Book>
#using ImpressDev.Infrastructure
<div class="row">
#foreach (var book in Model)
{
<div class="col-12 col-xl-4">
<a class="o-shop-link" href="#Url.Action("Details", "Catalog", new { bookId = book.BookId })">
<div class="o-shop-item">
<img class="o-shop-img" src="#Url.BookPhotoSourcePath(book.PhotoSource)" />
<div class="o-shop-text">
<h2>#book.Title</h2>
<h6>#book.SubTitle - #book.Level - <b>#book.Price zł.</b></h6>
+ Add to cart
</div>
</div>
</a>
</div>
}
</div>
Please help
I am not sure if this is the case, but try to change this code:
$($targetElement).replaceWith($newContent);
To this:
$($targetElement).html($newContent);
I think the problem is the div element with id="booksList" is replaced after first search. So you don't have this element in the second search.
I looked through the code step by step and found a solution to my problem.
In the first search, replace id="booksList"
<div class="row" id="booksList">
#Html.Partial("_PartialBooksList")
</div>
partial view in which there was only without id = booksLists.
In the next search there was no ID in this place and there was nothing to replace.

.on('mouseover') did not feedback info

I have such a snippet of ajax request:
<div>
<h4>Comments</h4>
<!-- <form action="/article/comment/create/{{ article.id }}" method='post'> -->
<form action="#">
<textarea class="form-control" rows="5" name='comment' id="commentContent"></textarea>
<br>
<button class="btn btn-primary" id="commentBtn">Post Your Comment</button>
</form>
</div>
</div><!--/class="col-xs-8 col-md-8">-->
</div><!-- row -->
<script src="/static/js/jquery-3.3.1.js"></script>
<script src="/static/js/jquery-csrf.js"></script>
<script>
$(document).ready(function(){
var article_id = article.id;
var num_pages = {{ page.num_pages }};
$("#commentBtn").on('mouseover', function(e){
e.preventDefualt();
alert("clicked")
var comment = $("#commentContent").val();
var param = {
"article_id": article.id
"content": comment};
$post("/comment/create/", param, function(data){
var ret = JSON.parse(data);
if (ret["status"] = "ok") {
$("#commentConent").val("");
window.location.href = "/article/detail/{{ article.id }}?page_number=" + num_pages;
} else {
alert(ret["msg"]);
}
});
});
});
</script>
I set the event type as mouseover,
However, when I place my mouse over the button "#commentBtn",
nothing occurs.
What's the problem it might be with my codes?
You have many syntax errors and typos in your code , and that's the cause of your problem , you write every thing correct , but I suggest you should use IDE like vscode to help you find this errors , IDEs help in finding undefined variables , or any syntax errors , to help you avoid this kind of problems and bugs , if you look at your code you'll see that ,
var num_pages = {{ page.num_pages }}; this code should be like this
var num_pages = page.num_pages ; if you try to extract num_pages into variable , also you can use destructuring which is ES6 feature
also you should change $post to $.post and e.preventDefualt(); to e.preventDefault();
I suggest that you should learn about ES6 features which will make your code better and enhance your development with JavaScript , things like const let and arrow functions and many great features , you can take an overview of this features here
es6-features
$(document).ready(function() {
// var article_id = article.id;
// var num_pages = {{ page.num_pages }};
$('#commentBtn').on('mouseover', function(e) {
e.preventDefault();
alert('clicked');
var comment = $('#commentContent').val();
var param = {
// "article_id": article.id
content: comment,
};
$.post('/comment/create/', param, function(data) {
var ret = JSON.parse(data);
if ((ret['status'] = 'ok')) {
$('#commentConent').val('');
window.location.href =
'/article/detail/{{ article.id }}?page_number=' + num_pages;
} else {
alert(ret['msg']);
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h4>Comments</h4>
<!-- <form action="/article/comment/create/{{ article.id }}" method='post'> -->
<form action="#">
<textarea class="form-control" rows="5" name='comment' id="commentContent"></textarea>
<br>
<button class="btn btn-primary" id="commentBtn">Post Your Comment</button>
</form>
</div>
</div><!--/class="col-xs-8 col-md-8">-->
</div><!-- row -->
Typo, use:
e.preventDefault();
Also:
$.post
And, at the end:
$("#commentContent")

javascript auto complete function

Hello i have the following code with problems, i'm trying to make it when you click on the output to insert it into the input field. Can you help me please, been trying for hours without any luck.
<script type="text/javascript">
var input = $('#CompanyName');
var output = $('#output');
var timer;
input.on('keyup', function() {
delaySearch(this.value);
});
function delaySearch(keywords) {
clearTimeout(timer);
timer = setTimeout(function() {
performSearch(keywords);
}, 1000);
}
function performSearch(keywords) {
$.ajax({
type: "POST",
url: "/print/order/search",
data: { query: keywords },
cache: false,
dataType: "json",
async: true,
success: function(data) {
for(var key in data) {
output.append('<li onclick="fill('+ data[key].ClientName +')">' + data[key].ClientName) + '</li>';
}
}
});
}
function fill(thisValue) {
input.val(thisValue);
clearTimeout(timer);
}
</script>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="CompanyName">Firma</label>
<div class="col-md-5">
<input id="CompanyName" onblur="fill();" name="CompanyName" type="text" placeholder="Firma" class="form-control input-md">
<ul id="output"></ul>
<span class="help-block"></span>
</div>
</div>
Uncaught ReferenceError: somevalue is not defined
Update:
After adding jquery ready function i noticed some errors around and fixed them here is an update on the code
<div class="form-group">
<label class="col-md-4 control-label" for="CompanyName">Firma</label>
<div class="col-md-5">
<input id="CompanyName" name="CompanyName" type="text" placeholder="Firma" class="form-control input-md">
<ul id="output"><li onclick="fill(Ionut)">Ionut</li></ul>
<span class="help-block">Nume Firma</span>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
var input = $('#CompanyName');
var output = $('#output');
var timer;
input.on('keyup', function() {
delaySearch(this.value);
});
function delaySearch(keywords) {
clearTimeout(timer);
timer = setTimeout(function() {
performSearch(keywords);
}, 1000);
}
function fill(thisValue) {
input.val(thisValue);
}
function performSearch(keywords) {
$.ajax({
type: "POST",
url: "/print/order/search",
data: { query: keywords },
cache: false,
dataType: "json",
async: true,
success: function(data) {
for(var key in data) {
output.append('<li onclick="fill(' + data[key].ClientName + ')">' + data[key].ClientName) + '</li>';
}
}
});
}
});
</script>
onclick the error persists
Uncaught ReferenceError: fill is not defined
realseanp is onto the correct answer. I'll try to explain it a little better for you. When a browser starts processing and rendering a page, it loads top down. So your javascript scripts are being ran and evaluated before the DOM is created.
So your jquery selectors: var input = $('#CompanyName'); if you were to inspect them are going to be an empty array. They cannot find the #CompanyName element because it has not yet been rendered.
If you use jQuery's $(document).ready() function, then you can be assured that your code will not run until the dom is finished rendering, and therefore will find the elements as you intend them to. So in the end, your code will need to change to this:
$(document).ready(function(){
//Put your code in here.
//It will then fire once the dom is ready.
});
UPDATE:
Additionally, with your update. I'm noticing that the error is that 'fill' is not defined. fill being your onclick method. You have your js script evaluating after the dom is rendered. So at the time that the dom is rendered, and the tag with the onclick is rendered, no fill method yet exists. Two solutions:
Move the script above the dom, and place a var fill; outside of the $(document).ready so essentially this:
var fill;
$(document.ready(function(){
//your code
});
Don't use the onclick dom attribute, and instead use jquery to bind the event. So change
Ionut
to this:
<ul id="output"><li>Ionut</li></ul>
and inside the document.ready, add:
$('#output li').click(function(e) {
fill(/*your value/*)
});
You need to put your script below your HTML. That or wrap it in the jQuery Document ready function. And make sure you have jQuery loaded on the page, before your script

Change page not working in jquery mobile

I find lot of posts here like same,sorry for asking again but no post is solved my issue. In my phonegap application when load the index page my init function will be called after depend upon the init my action are performed. After submitting the form i want to go index page but it is not possible.
function init() {
document.addEventListener("deviceready", phoneReady, false);
$(document).on("submit", '#addEditForm', function(e) {
var data = {
firstname: $("#mFirstname").val(),
lastname: $("#mLastname").val(),
id: $("#mId").val()
};
saveDatas(data, "#homePage", function() {
**$.mobile.changePage("index.html");** //here i need to go index page
});
e.preventDefault();
});
$(document).on("pageshow", function() {
getDatas();
});
$(document).on("pageshow", "#editPage", function() {
var loc = $(location).attr('href');
if (loc.indexOf("?") >= 0) {
var qs = loc.substr(loc.indexOf("?") + 1, loc.length);
var detailId = qs.split("=")[1];
$("#editFormSubmitButton").attr("disabled", "disabled");
dbShell.transaction(function(tx) {
tx.executeSql("select id,firstname,lastname,gender,dob,email from nameDetail where id=?", [detailId], function(tx, results) {
$("#mId").val(results.rows.item(0).id);
$("#mFirstname").val(results.rows.item(0).firstname);
$("#editFormSubmitButton").removeAttr("disabled");
});
}, dbErrHandler);
} else {
$("#editFormSubmitButton").removeAttr("disabled");
}
});
}
and index.html like:
<body onload="init();">
<div data-role="page" id="homePage">
and addEdit.html like:
<div data-role="page" id="editPage">
<form id="addEditForm" method="post">
<div data-role="fieldcontain">
<input type="submit" id="editFormSubmitButton" value="Save">
</div>
</form>
<div data-role="footer" class="ui-bar">
<a href="index.html" data-role="button" data-icon="home" >Return Home</a>
</div>
</div>
tied this also
//$.mobile.path.parseUrl("index.html");
// $.mobile.changePage($('#homePage'), 'pop', false, true);
Please suggest some idea to do this...
window.location.href won't grant you the page transitions from jQuery mobile. Try these instead:
$.mobile.navigate("#bar", {transition: "slide", info: "info about the #bar hash"});
$.mobile.pageContainer.pagecontainer("change", "target", {transition: "flow", changeHash: false, reload: true})
Also, $.mobile.changePage() is now deprecated and should no longer be used. http://api.jquerymobile.com/jQuery.mobile.changePage/

Categories