I'm trying to use google invisible recaptcha on my web form (php and codeigniter 3). but somehow whenever I click on the Submit button, the google recaptcha keeps generating questions as if ignoring all the other codes before the execute command. so none of the console.log and alert ever appear. what is wrong with my code?
my code looks like this:
HTML
<form id="form_signup" method="post" action="/signup">
<input type="text" name="username"/>
<div class="g-recaptcha"
id="form_signup-recaptcha"
data-size="invisible"
data-sitekey="<?php echo $mysitekey; ?>"
data-callback="onSubmitFormSignupUser">
</div>
<button type="button" id="formSignup-btnSubmit">
Submit
</button>
</form>
JS
var widgetId = '';
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render('formSignup-btnSubmit', {
'sitekey' : $('#form_signup-recaptcha').attr('data-sitekey'),
'callback' : $('#form_signup-recaptcha').attr('data-callback'),
});
};
var onSubmitFormSignupUser = function(response) {
console.log('response', response);
if ($('[name="username"]').val()) {
alert('yes');
grecaptcha.execute(widgetId);
doSubmitFormToServer('#form_signup');
}
else {
alert('no');
grecaptcha.reset(widgetId);
}
}
var doSubmitFormToServer = function(selector) {
var myData = $(selector).serializeArray();
console.log('send form data', myData);
}
Well, you had a typo in the id, at least, here id="form_signup-recaptcha" and here: 'sitekey' : $('#formSignup-recaptcha').attr('data-sitekey'),, other than that, it is not clear, was it invoked at all, or not, as you've not provided the part of including the script, which should contain ?onload=onLoadRecaptcha parameter.
The code is below, but it won't work here, because of null origin. Check Codepen instead: https://codepen.io/extempl/pen/abOvBZv
sitekey used is one is for testing purposes only, as described here: https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha-v2-what-should-i-do
var widgetId = "";
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render("formSignup-btnSubmit", {
sitekey: $("#form_signup-recaptcha").attr("data-sitekey"),
callback: $("#form_signup-recaptcha").attr("data-callback")
});
};
var onSubmitFormSignupUser = function(response) {
console.log("response", response);
if ($('[name="username"]').val()) {
grecaptcha.execute(widgetId);
doSubmitFormToServer("#form_signup");
} else {
$(".status").text("failed");
grecaptcha.reset(widgetId);
}
};
var doSubmitFormToServer = function(selector) {
var myData = $(selector).serializeArray();
$(".status").text("submitted");
console.log("send form data", myData);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js?onload=onLoadRecaptcha"></script>
<body>
<form id="form_signup" method="post" action="/signup">
<input type="text" name="username" />
<div
class="g-recaptcha"
id="form_signup-recaptcha"
data-size="invisible"
data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
data-callback="onSubmitFormSignupUser">
</div>
<button type="button" id="formSignup-btnSubmit">
Submit
</button>
<span class="status"></span>
</form>
</body>
it turns out that the solution is so simple.
this code
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render("formSignup-btnSubmit", { // wrong element ID
sitekey: $("#form_signup-recaptcha").attr("data-sitekey"),
callback: $("#form_signup-recaptcha").attr("data-callback")
});
};
should be like this
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render("form_signup-recaptcha", { // corrent element ID
sitekey: $("#form_signup-recaptcha").attr("data-sitekey"),
callback: $("#form_signup-recaptcha").attr("data-callback")
});
};
because the recaptcha element is like this
<div
class="g-recaptcha"
id="form_signup-recaptcha"
data-size="invisible"
data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
data-callback="onSubmitFormSignupUser">
</div>
so basically the parameters for grecaptcha.render should follow the properties in the element that has g-recaptcha class. my mistake was that I used the button id, even though the element with g-recaptcha class was the div.
I don't remember reading about this particular thing in the documentation. I guess I'm too stupid to realize that before this.. I hope this makes things clear for others with the same problem.
Related
this is my javascript code the onclick functions do not trigger when i push the button I have tried with an event listener that listen only for the parent of the button aka the form but nothing in that case it fires once and it does not keep listening for further button clicks:
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
document.addEventListener('DOMContentLoaded', () =>{
const room__message = Handlebars.compile(document.querySelector('#room__message').innerHTML);
document.querySelector('#send__button').onclick = () =>{
console.log('hola el boton fue pulsado')
let message = document.querySelector('#message__input').value
let user = localStorage.getItem('user')
let channel = localStorage.getItem('channel')
console.log(message)
socket.emit('send message', {'message':message, 'user':user, 'room':channel})
document.querySelector('#message__input').value = '';
}
socket.on('connect', () =>{
socket.emit('join', { 'channel':localStorage.getItem('channel'), 'user':user })
load__list();
load_messages(localStorage.getItem('channel'))
});
document.querySelector('#add__room').onclick = () => {
let list = JSON.parse(localStorage.getItem('channel__list'));
let name_ = prompt("Please enter you'r new Channel's name", "");
while (name_ in list || name != null){
name_ = prompt("this name is already in the database", "");
}
if (name_ != null){
list.push(name_)
}
socket.emit('new room', {'name':name_})
};
socket.on('broadcast', data =>{
let message = data.message;
let user = data.user;
let timestamp = data.timestamp;
const msj = room__message({'message':message, 'user':user, 'timestamp':timestamp})
document.querySelector('.message__cont').innerHTML += msj;
});
});
the html looks like this:
<body>
<ul id="channel__list">
<li>
<button id="add__room">+</button>
</li>
</ul>
<div id="chanel__container">
<form id="channel__form" action="" >
<input type="text" id="message__input" autocomplete="off" placeholder="message">
<input type="submit" id="send__button" value="send">
</form>
</div>
</body>
it does run in a flask server I dont know if that may be an issue
First of all, there are quite a few syntax errors in your code.
Inside your HTML code
<from> tag is to be changed to <form>
Inside your JS code
ID room__message is not declared hence this will never return anything.
You have opened a function socket.io('connect') function but never closed.
Coming back to why the on click buttons are not getting triggered *
The possible reason this could be happening is that by the time your document readyState is already completed in this case the event DOMContentLoaded will not be fired at any point in time. This can be avoided by providing/checking document ready state.
Below are two sample codes (I am still not sure why you are using on click function inside a listener while you can use JS shorthand and directly use it)
Proper HTML code
<body>
<ul id="channel__list">
<li>
<button id="add__room">+</button>
</li>
</ul>
<div id="chanel__container">
<form id="channel__form">
<input
type="text"
id="message__input"
autocomplete="off"
placeholder="message"
/>
<input type="submit" id="send__button" value="send" />
</form>
</div>
</body>
Your actual JS code (a bit modification)
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", loadDomContent());
} else {
console.log("Current document load state: ", document.readyState);
loadDomContent();
}
function loadDomContent() {
const room__message = Handlebars.compile(
document.querySelector("#room__message").innerHTML
);
document.querySelector("#send__button").onclick = () => {
/* do something */
};
socket.on("connect", () => {
socket.emit("join", {
/* do other stuff }); */
});
});
document.querySelector("#add__room").click = () => {
console.log("I am working");
/* do something else */
};
socket.on("broadcast", data => {
/* send some stuff over */
});
}
Also, you can write something like this
<button onclick="addNewRoom()" id="add__room">+</button>
An declaring that as:
function addNewRoom(){
// do something
}
My Solution
the issue was in deed in the html, because it was changing the position of th ebutton by adding more elements to its container im guessing it changed the address to which the event was pointing at, thanks everybody for their input.
Hello I am at my wit's end and I've been stuck creating a more complex version of the form than the example I provide.
I have JS object that is representation of the form. I use parsley's "isValid" on the form itself (checkAll and checkGroup function). These methods are fired on every input that is marked with data-parsley-required attribute. The reason for this is I need to know the state of the whole form and it's parts so I can enable/disable step buttons.
Everything works fine but I also need to call external API when all validations have successed, see line 35. The methods checkAll and checkGroup are basically firing the events again, thus making more AJAX calls (we have limit on calls to the API). Is there a way to force method isValid to just check if the field has been validated and get true/false value out of it?
The whole thing is coded and depends on this structure so the best way would be to have similar functionality. I'm not so experienced so I make lot of mistakes. My example is very simplified version of my actual form but when you open console window you can see what I mean. Uncomment lines 32 and 33 to see the difference and you will know what I mean.
Example code
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<form action="" id="myform">
<div id="section1">
<input type="text" id="field1" data-parsley-required data-parsley-trigger="input" data-parsley-group="group1" data-parsley-lengthvalidator data-parsley-remote="http://pokeapi.co/api/v2/pokemon/1" data-parsley-remote-validator="remotevalidator" /><br />
<button id="next" disabled>Next</button><br />
</div>
<div id="section2">
<input type="text" id="field2" data-parsley-required data-parsley-trigger="input" data-parsley-group="group2" />
</div>
<input type="submit" id="submit-button" disabled />
</form>
</body>
</html>
JS:
function Form(form) {
this.form = form;
this.validations = {};
this.formValid = false;
this.checkAll = function() {
var result = $(form).parsley().isValid();
if (result) {
$('#submit-button').removeAttr('disabled');
console.log('form validated');
} else {
$('#submit-button').attr('disabled', true);
}
this.formValid = result;
};
this.checkGroup = function(e) {
var group = $(e.target).attr('data-parsley-group');
var result = $(form).parsley().isValid({group: group});
if (result) {
$('#next').removeAttr('disabled');
console.log('group validated');
} else {
$('#next').attr('disabled', true);
}
this.validations[group] = result;
};
this.initialize = function() {
var self = this;
$(this.form).parsley();
$('*[data-parsley-required]').on('input', function(e) {
self.checkAll();
self.checkGroup(e);
});
$('#field1').parsley().on('field:success', function() {
console.log('calling another API')
})
Parsley.addValidator('lengthvalidator', {
validateString: function(value) {
console.log('local validator');
return value.length > 0;
}
});
Parsley.addAsyncValidator('remotevalidator', function(response) {
console.log('remote validator');
return response.responseJSON.name === 'bulbasaur';
})
}
}
var form = new Form('#myform');
form.initialize();
First of all , I have no idea of javascript, I got this code from a tutorial.
I am developing a website in ruby , and to do that I need to make a form of payment. I'm currently using the API Mango.
I have the following code:
<form id="form" action="/pay" method="POST">
<fieldset>
<div>
<label for="ccv">Código de seguridad</label>
<input type="text" id="ccv" required>
</div>
</fieldset>
<input type="submit" value="Pagar ahora!">
</form>
<div id="errores">
</div>
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://js.getmango.com/v1/mango.js"></script>
<script>
var PUBLIC_API_KEY = 'public_test_u3wbj4jctik1k2u8qtnajhvn82h590ue';
Mango.setPublicKey(PUBLIC_API_KEY);
var submission = false;
var $form = $('#form');
$form.on('submit', function(event) {
if (submission) {
return false;
}
submission = true;
var cardInfo = {
'ccv': $('#ccv').val()
};
Mango.token.create(cardInfo, handleResponse);
return false;
});
function handleResponse(err, data) {
submission = false;
//Here I put an error message that's displayed in html
if (err) {
...
}
var token = data.uid;
var $hidden = $('<input type="hidden" name="token">');
$hidden.val(token);
$form.append($hidden);
$form[0].submit();
}
</script>
How I can capture that error and show it in html ?
function handleResponse(err, data) {
submission = false;
//Here I put an error message that's displayed in html
if (err) {
...
}
var token = data.uid;
var $hidden = $('<input type="hidden" name="token">');
$hidden.val(token);
$form.append($hidden);
$form[0].submit();
}
this function - is an event handler for Response,obviously. First param is error and if this will be passed your if(err) code block will be executed.
As i see - you use JQuery, so in this place you can Insert some code, which will show error into your form.
For example $('form').append('<div class="error">Some error occurs</div>');
You could try something like
$('body').append($errorp);
I am stuck in passing the multiple value through AJAX call in Codeigniter.
My View is :
<script>
$( document ).ready(function() {
var current_id = 0;
$('#btn').click(function(){
nextElement($('#Outer_00'));
})
function nextElement(element){
var newElement = element.clone()
.find("input:text").val("").end();
var id = current_id+1;
current_id = id;
if(id <10)id = "0"+id;
$('input', newElement).attr("id", id );
newElement.appendTo($("#elements"));
if($('#elements').find('div').length=='5')
{
$('#btn').prop('disabled',true);
}
}
$('#exercises').on('click', '.remove', function() {
if($('#elements').find('div').length<'6')
{
$('#btn').prop('disabled',false);
}
if($('#elements').find('div').length=='1')
{
$('.remove').addAttr("disabled",true);
}
$(this).parent().remove();
return false; //prevent form submission
});
});
</script>
/******************************
<script>
var base_url = '<?=base_url()?>';
$(document).ready(function()
{
$('#Edit').click(function()
{
$('#Name').removeAttr("disabled");
});
$('#Add').click(function()
{
$('#Name').attr("disabled","disabled");
$('#Phone').attr("disabled","disabled");
$('#email').attr("disabled","disabled");
$('#CurrentlyLocated').attr("disabled","disabled");
$('#KeySkills').attr("disabled","disabled");
//var queryString = $('#form1').serialize();
$.ajax({
url: '<?php echo site_url('PutArtistProfile_c/formDataSubmit');?>',
type : 'POST', //the way you want to send datas to your URL
data: {Name:$("#Name").val(), Phone: $("#Phone").val(), email: $("#email").val(),
birthday: $("#birthday").val(), bornIn: $("#bornIn").val(),
CurrentlyLocated: $("#CurrentlyLocated").val(), KeySkills: $("#KeySkills").val(),
Audio1: $("#00").val(), Audio2: $("#01").val(), Audio3: $("#02").val(),Audio4: $("#03").val(), Audio5: $("#04").val(),
},
success : function(data)
{ //probably this request will return anything, it'll be put in var "data"
$('body').html(data);
}
});
});
});
</script>
<p>
<div id="elements">
<div id="Outer_00">
Audio: <input type="text" id="00" value="">
<input type="button" class="remove" value="x"></button>
</div>
</div>
<div id="count"></div>
<input type="button" id="btn" value="Add Audio"></button>
</p>
My Controller is :
public function formDataSubmit()
{
$queryAudio1 = $this->input->post('Audio1');
$queryAudio2 = $this->input->post('Audio2');
$queryAudio3 = $this->input->post('Audio3');
$queryAudio4 = $this->input->post('Audio4');
$queryAudio5 = $this->input->post('Audio5');
}
How can I pass Multiple Values of text box? The above code is passing the values to the controller. But on clicking 'x' Button the value of text box is been getting deleted, but the id of the textbox is getting Incremented, Thus I am not able to pass the further values of textbox to controller via AJAX. Please help me over here.
instead of doing :
data: {Name:$("#Name").val(), Phone: $("#Phone").val(), email: $("#email").val(),
birthday: $("#birthday").val(), bornIn: $("#bornIn").val(),
CurrentlyLocated: $("#CurrentlyLocated").val(), KeySkills: $("#KeySkills").val(),
Audio1: $("#00").val(), Audio2: $("#01").val(), Audio3: $("#02").val(),Audio4: $("#03").val(), Audio5: $("#04").val(),
},
You can do as
data:$("#Form_id").serialize(); // all form data will be passed to controller as Post data.
If you have a remove button then getting the value by id may result in a js error, Why don't you make use of html element array:
<div id="elements">
<div id="Outer_00">
Audio: <input type="text" name="audio[]" value="">
<input type="button" class="remove" value="x"></button>
</div>
</div>
IT is very simple:
Consider you want to pass: user name, surname, and country. These are
three input boxes then:
using Jquery do so:
Javascript side
$.post("url",{name:name,surname:surname,country:country},
function(data){
console.log("Query success");
});
In your Model or controller where your Query will be handled
$name=$this->input->post("name");
$surname=$this->input->post("surname");
$country=$this->input->post("country");
in your case just pass parameters that YOU need. I use codignitter and
this method works fine!
I'm working on a project where I'd place an search box with a default set of results, over the layout using Prototype which is triggered from a click event.
When the output is set, that new page has it's own Javascript which is uses, to dynamically filter the results.
Now the new set of results do not work with the Javascript set previously.
How can I maintain a persistent event with calling new events each time?
Or is that what I am supposed to do.
Here is a bit of code which is loaded in 'loaded_page.php'
<script language="javascript">
var o = new Compass_Modal('add_button', 'history');
var placetabs = new Tabs('tabs', {
className: 'tab',
tabStyle: 'tab'
});
$$('.add_button').each(function(s, index){
$(s).observe('click', function(f) {
loadData();
});
});
function loadData() {
new Ajax.Request('/sponsors/search', {
onComplete: function(r) {
$('overlay').insert({
top:'<div id="search_table">'+r.responseText+'</div>'
});
}
})
}
</script>
Then in the included page which is inserted via javascript:
<div id="search_overlay">
<div id="form_box">
<img src="/images/closebox2.png" class="closebox" />
<form method="post" id="search_form" class="pageopt_left">
<input type="text" name="search_box" id="search_box" value="search" />
</form>
</div>
<div id="table_overlay">
<table class="sortable" id="nf_table" cellpadding="0" border="0" cellspacing="0">
<tr>
<th id="name_th">Name</th><th id="amount_th">Amount</th><th id="tax_letter_th">Tax Letter</th><th id="date_th">Date</th><th id="add_th">Add</th></tr>
<tr>
<td>Abramowitz Foundation (The Kenneth & Nira)</td><td><input type="text" name="amount" value="" id="amount_111" /></td><td><input type="checkbox" name="tax_letter" value="1" id="tax_letter_111" /></td><td><input type="text" name="date" value="" id="date_111" /></td><td><img src="/images/icons/add.png" title="add contact" /></td></tr>
... more rows
</table>
</div>
</div>
<script language="javascript">
var c = new Compass_Search('contacts', 'table_overlay');
c.set_url('/sponsors/sponsor_search');
$$('.add_button').each(function(s, index) {
$(s).observe('click', function(e) {
$(e).stop();
var params = $(s).href.split("/");
var userid = params[5];
var amount = 'amount_'+params[5];
var date = 'date_'+params[5];
var tax = 'tax_letter_'+params[5];
if(!Form.Element.present(amount) || !Form.Element.present(date)) {
alert('your amount or date field is empty ');
} else {
var add_params = {'amount':$F(amount), 'date':$F(date), 'tax':$F(tax), 'id':userid};
if(isNaN (add_params.amount)) {
alert('amount needs to be a number');
return false;
} else {
new Ajax.Request('/sponsors/add', {
method: 'post',
parameters: add_params,
onComplete: function(e) {
var post = e.responseText;
var line = 'amount_'+add_params.id;
$(line).up(1).remove();
}
})
}
}
});
});
this.close = $$('.closebox').each(function(s, index) {
$(s).observe('click', o.unloader.bindAsEventListener(this));
})
</script>
You'll notice in the inserted portion, a new Javascript which also, updated its own content with yet new observers. When the content gets updated, the observers do not work.
Use event delegation.
Besides making it possible to replace "observed" elements, this approach is also faster and more memory efficient.
document.observe('click', function(e){
var el = e.findElement('.add_button');
if (el) {
// stop event, optionally
e.stop();
// do stuff... `el` now references clicked element
loadData();
}
});
As you're calling Element#insert, I suppose String#evalScripts should be automatically called (as having looked in the implementation of those methods)
Maybe you can try to do some console.log()/alert() messages before the Element#observe calls, to see where it is going wrong. It may be because the Javascript is not evaluated at all, or that there is something wrong with your code or something like that.
As a tip: check the documentation on Array#invoke, with that method you can rewrite something like:
$$('.add_button').each(function(s, index){
$(s).observe('click', function(f) {
loadData();
});
});
into this:
$$('.add_button').invoke('observe', 'click', function(event){
loadData();
});
// $$('.add_button').invoke('observe', 'click', loadData);