Before you say this is a duplicate, hear me out. I followed this answer (jQuery Ajax POST example with PHP), but I am trying to send the data to a Google Sheet. I have already got the code working on the Google Sheet, as I can add data to it by running my code directly from the sheet.
However, getting it to work with my webpage is apparently the problem. Even though I have followed the answer to the question I posted above, I think there is something more at play here that has to do with my lack of experience working in this area.
The code below is to a floating footer and is contained within the code of the whole webpage (where jquery-1.11.0.min.js and jquery-migrate-1.2.1.min.js have already been called). When I click on the submit button, the page looks like it processes the request, but nothing ever appears on the Google Sheet, Sheet1 (https://docs.google.com/spreadsheets/d/19l2kSHdBKEWtIFX44FxLBdvCoKjy7VqPF4IW6C1xAZc/edit?usp=sharing).
#document
<html>
<body>
<div class="floater-footer" id="the-floater-footer">
<span id="myTestSpan"></span>
<div class="row">
<div class="col-md-1 col-sm-2 col-xs-3"><p>Newsletter</p></div>
<div class="col-md-8 col-sm-7 col-xs-9">
<form id="floater_footer" class="validate subscribe_form">
<div id="subscrive_group wow fadeInUp">
<!-- <input type="email" value="" name="EMAIL" class="form-control subscribe_mail" id="mce-EMAIL" placeholder="email address" required /> -->
<input type="text" class="form-control subscribe_mail" id="bar" name="bar" value="" placeholder="email address" required />
<!-- <input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="subscr_btn subscribe_btn"> -->
<input type="submit" value="Subscribe" class="subscr_btn subscribe_btn" />
</div>
</form>
</div>
<div class="col-md-3 col-sm-3 hidden-xs">
<div class="pull-right">
<!-- social media icons here -->
</div>
</div>
</div>
</div>
<script type="text/javascipt">
jQuery( document ).ready(function( $ ) {
// variable to hold request
var request;
// bind to the submit event of our form
$("#floater_footer").submit(function(event){
// abort any pending request
if (request) {
request.abort();
}
// setup some local variables
var $form = $(this);
// let's select and cache all the fields
var $inputs = $form.find("input, select, button, textarea");
// serialize the data in the form
var serializedData = $form.serialize();
// let's disable the inputs for the duration of the ajax request
// Note: we disable elements AFTER the form data has been serialized.
// Disabled form elements will not be serialized.
$inputs.prop("disabled", true);
//$('#result').text('Sending data...');
// fire off the request to /form.php
request = $.ajax({
url: "https://script.google.com/macros/s/AKfycbyQIDmSInumcrNmU4zxIa4pV8tIlN3A9zx5L5o1hH4qNdP9nDw/exec",
type: "post",
data: serializedData
});
// callback handler that will be called on success
request.done(function (response, textStatus, jqXHR){
// log a message to the console
//$('#result').html('Success - see Google Sheet');
console.log("Hooray, it worked!");
});
// callback handler that will be called on failure
request.fail(function (jqXHR, textStatus, errorThrown){
// log the error to the console
console.error(
"The following error occured: "+
textStatus, errorThrown
);
});
// callback handler that will be called regardless
// if the request failed or succeeded
request.always(function () {
// reenable the inputs
$inputs.prop("disabled", false);
});
// prevent default posting of form
event.preventDefault();
});
});
</script>
</body>
</html>
Any suggestions on what could be going wrong? I am quite inexperienced when it comes to web development, as compared to most on this site. So I'm sure it's something simple I am missing!
I don't completely understand why it worked, but taking out the script and putting it in the head of the page HTML seemed to work! Perhaps this was because having the script come after the elements was an issue, or perhaps having a $(document).ready() inside of an HTML that was inside the page's main HTML caused issue, or perhaps it was something else! No matter which one it is, the following solved the problem.
Up at the top of the code in the head of the page's HTML (but after the jQuery.js files were declared), I placed the script you saw already, but with some cosmetic changes. I'll put it here in the event I did indeed change something important that I didn't realize. I will also show the two jQuery files I included before the script:
<script type="text/javascript" src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script type="text/javascript">
//this is for writing the newsletter signup out to a spreadsheet for the floating footer
$( document ).ready(function( $ ) {
// variable to hold request
var request;
// bind to the submit event of our form
$("#floater_footer").submit(function(event){
// abort any pending request
if (request) {
request.abort();
}
// setup some local variables
var $form = $(this);
// let's select and cache all the fields
var $inputs = $form.find("input, select, button, textarea");
// serialize the data in the form
var serializedData = $form.serialize();
// let's disable the inputs for the duration of the ajax request
// Note: we disable elements AFTER the form data has been serialized.
// Disabled form elements will not be serialized.
$inputs.prop("disabled", true);
//$('#result').text('Sending data...');
if( $('#email1').val() == "Email Received!" ) {
//do nothing
//basically, they pressed the button again on accident
} else {
// fire off the request to the Google Sheet script
request = $.ajax({
url: "https://script.google.com/macros/s/AKfycbyQIDmSInumcrNmU4zxIa4pV8tIlN3A9zx5L5o1hH4qNdP9nDw/exec",
type: "post",
data: serializedData
});
}
// callback handler that will be called on success
request.done(function (response, textStatus, jqXHR){
// log a message to the console
//$('#result').html('Success - see Google Sheet');
$('#email1').val('Email Received!');
console.log("Newsletter signup complete!");
});
// callback handler that will be called on failure
request.fail(function (jqXHR, textStatus, errorThrown){
// log the error to the console
console.error(
"The following error occured: "+
textStatus, errorThrown
);
});
// callback handler that will be called regardless
// if the request failed or succeeded
request.always(function () {
// reenable the inputs
$inputs.prop("disabled", false);
});
// prevent default posting of form
event.preventDefault();
});
});
</script>
Further down into the body of the HTML was this code where my footer was to be placed:
#document
<html>
<body>
<div class="floater-footer" id="the-floater-footer">
<span id="myTestSpan"></span>
<div class="row">
<div class="col-md-1 col-sm-2 col-xs-3"><p>Newsletter</p></div>
<div class="col-md-8 col-sm-7 col-xs-9">
<form id="floater_footer" class="validate subscribe_form">
<div id="subscrive_group wow fadeInUp">
<input type="text" class="form-control subscribe_mail" id="email1" name="emailSignup" value="" placeholder="email address" required />
<input type="submit" value="Subscribe" class="subscr_btn subscribe_btn" />
</div>
</form>
</div>
<div class="col-md-3 col-sm-3 hidden-xs">
<div class="pull-right">
<!-- bunch of social media links/icons -->
</div>
</div>
</div>
</div>
</body>
</html>
Hopefully that will help somebody that has this problem in the future. You may see a reason this worked that I do not.
Big thanks to Jay Blanchard for making me question if my script was even triggering at all, which inspired me to pull the script out and put it somewhere else! The script almost certainly wasn't firing at all, and was the root of the problem. But WHY that was, I don't know. But I hope this helps someone else!
Related
I am using a Wordpress theme that unfortunately is duplicating the header HTML for desktop, mobile and tablet. As a result, a login form I have appears to be submitting multiple times even though "Login" is only clicked once.
Here is the HTML for the form:
<div id="user-login">
<div class="com_row">
<div class="com_panel_body">
<div id="error_message91" class="com_alert com_alert_danger" style="display: none;">
</div>
<form method="post" id="validation_form83">
<input type="hidden" name="login_form_flag" value="1">
<div class="login-username">
<label for="email" class="main_label">Email Address</label>
<input id="email68" type="email" name="email" required="required">
</div>
<div class="login-password">
<label for="password" class="main_label">Password:</label>
<input id="password82" type="password" name="password" required="required">
</div>
<ul class="login-links" style="margin-top:-30px"><li>Forgot Password?</li></ul>
<div class="login-submit" style="margin-top:-20px">
<input type="submit" value="Login"></div>
<div style="padding-top:20px"><a class="button green small borderd-bot" href="/client_account">Register</a></div>
</form>
</div>
</div>
</div>
Here is the relevant JS:
$("[id^='validation_form']").each(function(i) {
//necessary because there are 3 form duplicates on the page, so this button works on all
jQuery(document).on("submit", this, SubmitValidationForm);
});
function($) {
SubmitValidationForm = function (event) {
event.preventDefault();
var formk = "#"+event.target.id;
var k = $(formk).serialize();
k += "&action=wcap_requests&what=validate_login";
jQuery("input[type=email]",formk).prop("disabled", true);
jQuery("input[type=password]",formk).prop("disabled", true);
jQuery("input[type=submit]",formk).prop("disabled", true).val(WCAP_Working_text);
var childf = $(formk).closest('div','.com_alert').children( ".com_alert");
$(childf).hide();
var login_form_flag = jQuery("input[name=login_form_flag]",formk).val();
jQuery.post(wcap_ajaxurl, k, function (data) {
data = JSON.parse(data);
console.log(data);
if (data.status === "OK") {
//== if client login through wcap login form
if (login_form_flag === '1'){
window.location.href = client_area_url;
}
else {
if (redirect_login !== "0") {
window.location.href = redirect_login;
} else {
window.location.reload();
}
}
}
else {
jQuery("input[type=email]",formk).prop("disabled", false);
jQuery("input[type=password]",formk).prop("disabled", false);
jQuery("input[type=submit]",formk).prop("disabled", false).val('Login');
$(childf).html(data.message).show();
}
});
};
};
The problem is because there are 3 duplicate forms on the page HTML (with only 1 visible to the user), the SubmitValidationForm function is called 3 times every time. The issue is pronounced when there is a valid login submitted, but the error box still appears saying invalid email after a few seconds (even though the login is actually correct and the user gets automatically redirected properly to the client area ). This error seems caused by the fact the SubmitValidationForm function is called 2 subsequent times after the first 'valid' submission which makes it think it's invalid, when it's not... the interesting thing is it doesn't seem caused by the other duplicate forms in the HTML, as the form ID attribute that I display in browser console shows only the 'valid' form being submitted (albeit multiple times -- perhaps because of the jquery.on() for each function).
Any ideas how to fix?
Thanks!
I figured out the issue. If anyone else is looking at this in future the issue was with respect to the 'on' function, it was referencing the 'document' before instead of 'this'. So it should be changed to:
$("[id^='validation_form']").each(function(i) {
jQuery(this).on("submit", this, SubmitValidationForm);
});
I am writing code for page reload after getting response from button click event in javascript. But its not working page is not getting reload after button click event.
My form
<div class="form-group">
<label>My Label Name</label>
<select class="form-control my_select2_id" id="my_select2_id" name="my_select2_id" tabindex="-1">
<option></option>
<?php if($table_rows != '') {
foreach($table_rows as $each_row) {?>
<option value="<?=$each_row['id']; ?>"><?=$each_row['my_column']; ?></option>
<?php } }?>
</select>
</div>
<div class="form-group">
<input type="text" class="form-control second_field" id="second_field_id" name="second_field_id" placeholder="Enter second field ID">
</div>
<div class="form-group">
<input type="text" class="form-control my_third_field" id="my_third_field" name="my_third_field" placeholder="Enter Third Field">
</div>
<button type="button" id="my-button-id" class="btn btn-success float_left">Add Test Case</button>
My Select2 dropdown select box is:
$("#my_select2_id").select2({
placeholder: "Select One ID",
allowClear: true,
initSelection: function(element, callback) { }
});
My Ajax call is:
$('#my-button-id').click(function(){
---------
---------
---------
var data = $('#my_form').serialize();
$.ajax({
type:"POST",
url:"ajax/my_ajax_file.php",
data:data,
success:function(response)
{
if(response == 'error')
{
$('.failure-msg').text('Some problem occurred, please try again.');
$('.form_error').show();
}
else
{
$('.form_error').hide();
$('#my_form')[0].reset();
$("#my_select2_id").select2('data', null);
//$("#my_select2_id").val('').trigger('change');
$('.myData').html(response);
$('.success-msg').text('Data has been added.');
$('.my_form_success').show();
window.setTimeout(function(){location.reload()},1000)
}
}
});
})
My requirement here is I just want to reset the select2 box, for this I am following 2 ways that is I have to either reset select2 box which is not getting reset or reload the page so that select2 also will be reset. It is neither refreshed by window.setTimeout(function(){location.reload()},1000) nor the select2 box is getting reset by $("#my_select2_id").select2('data', null); Can anyone please help me in this. Thanks in advance.
As mentioned in the comments to your question there is no obvious syntactical error in your code but you lack to check for errors on your AJAX call by only checking the success() portion of the code. I would recommend to either add the complete() or error() functions to make sure you are also able to react to errors that may occur while submitting the data.
$.ajax({
type:"POST",
url:"ajax/my_ajax_file.php",
data:data,
success:function(response) {
},
error: function (jqXHR, status, message)
{
alert ("Submitting data failed with message: " + message);
}
});
On a page refresh all form elements will be reset to their original values, you therefor don't have to clear the SELECT field prior to reloading the data.
You can try with:
setTimeout(function(){ location.reload(); }, 1000);
I'm having a button, and when is clicked, it renders (with the help of ajax), the content of a php script (basically it's a contact form). My problem is that when the button is clicked, this calls the php script twice or more times. I've tried many solutions, but none worked.
HTML
<ul class="nav navbar-nav navbar-right">
<li>CONTACT</li>
</ul>
JavaScript
$(document).ready(function(){
$('#contact').off();
// the above line I've replaced it with:
// 1. $('#contact').off('click');
// 2. $('#contact').unbind();
// 3. $('#contact').unbind('click');
$('#contact').click(function(e){
$.ajax({
type: "POST",
url: "contact.php",
success: function(html){
$('#content').html(html);
}
});
e.preventDefault();
});
});
The response I get when I run the page which contains the HTML and JS:
The contact.php receives the data send with ajax (from index.php - the page which contains the above code), and then sends the new contact to another php script (which is a class), who stores the new contact in the database, and gives back (to contact.php) a response.
contact.php
<form id="form">
<div class="form-group col-xs-12 col-md-4">
<input type="text" class="form-control" id="nume" value="<?php echo Escape::esc($nume);?>" style="pointer-events:none;background:#EFEFEF;"/>
</div>
<div class="col-xs-12"></div>
<div class="form-group col-xs-12 col-md-4">
<input type="text" class="form-control" id="prenume" value="<?php echo Escape::esc($prenume);?>" style="pointer-events:none;background:#EFEFEF;"/>
</div>
<div class="col-xs-12"></div>
<div class="form-group col-xs-12 col-md-10">
<textarea class="form-control" id="mesaj" rows="20" data-toggle="mesaj" data-placement="bottom" title="Va rog introduceti mesajul dvs."></textarea>
</div>
<div class="col-xs-12"></div>
<div style="clear:both"></div>
<button class="btn btn-default" onclick="return validate();" style="margin-left:15px;">TRIMITE</button>
</form>
<script type="text/javascript">
function validate(){
var nume = $('#nume').val();
var prenume = $('#prenume').val();
var mesaj = $('#mesaj').val().trim();
if (mesaj == '' || mesaj.length < 3){
$(function(){
$('[data-toggle="mesaj"]').tooltip();
document.getElementById('mesaj').focus();
});
return false;
}
$('#form').off();// here I tried to unbind all the previous submit events too
$('#form').on('submit',function(e){
$.ajax({
type: "POST",
url: "../../app/classes/Contact.php",
data: {nume:nume, prenume:prenume, mesaj:mesaj},
success: function(html){
$('#content').html(html);
}
});
e.preventDefault();
});
}
</script>
Any tip is welcomed! Thank you!
From what I understand, JavaScript does not execute functions sequentially by nature. In your first jQuery snippet it looks like your code assumes that it will first unbind any events bound to $('#contact') and then create a new binding, but that's not necessarily true.
Also, the off() command only works if you bound the event to the element using a corresponding on() command, but your code uses click() instead of on().
You may want to try something like this instead:
$(document).ready(function(){
$('#contact').on('click', function(e){
$.ajax({
type: "POST",
url: "contact.php",
success: function(html){
$('#content').html(html);
}
});
e.preventDefault();
});
});
Using $('#contact').on('click', function(e) ... will allow you to call $('#contact').off() after the e.preventDefault(); if you want to try to use that to troubleshoot the double-posting problem.
I'm not sure that will fix your issue, but hopefully it's a step in the right direction.
I added to my form a special id which I would like to track. If this id is available in the form, an AJAX request should be initialised.
Form
{!! Form::open(['data-remote', 'action' => 'IncidentsController#store', 'id'=>'incidentEntryForm']) !!}
<div class="form-group">
{!! Form::label('city', 'Name:') !!}
{!! Form::text('city', null, ['class' => 'form-control']) !!}
</div>
(...)
Therefore I wrote this helper script:
Helper Script
(function() {
console.log("Helper OK");
var submitAjaxRequest = function(e) {
var form = $(this);
var method = form.find('input[name="_method"]').val() || 'POST';
$.ajax({
type: method,
url: form.prop('action'),
data: form.serialize(),
success: function() {
console.log("Submit OK");
$.publish('form.submitted', form);
}
})
e.preventDefault();
};
// forms marked with the "data-remote" attribute will submit, via AJAX.
$('form[data-remote]').on('submit', submitAjaxRequest);
})();
The $.publish is a short script for PubSub Functionality I included as well.
PubSub
(function($) {
console.log('PubSub OK');
var o = $({});
$.subscribe = function() {
o.on.apply(o, arguments);
};
$.unsubscribe = function() {
o.off.apply(o, arguments);
};
$.publish = function() {
o.trigger.apply(o, arguments);
};
}(jQuery));
But when I press the submit button, the last line of the helper script does not seem to react. The function submitAjaxRequest is never called.
The script is included in my head section. For checking if this is loaded, I included the console.log at the beginning. I see the output. So it is running I think. But it does not react to the submit press in the form.
Update 1
When I try calling submitAjaxRequest() I get the error: Uncaught TypeError: Cannot read property 'preventDefault' of undefined
Update 2
The Form Code that is generated is this:
<form method="POST" action="http://dev.server.com/incidents" accept-charset="UTF-8" data-remote="data-remote" id="incidentEntryForm"><input name="_token" type="hidden" value="<TOKEN>">
<div class="form-group">
<label for="city">Notrufort:</label>
<input class="form-control" name="city" type="text" id="city">
</div>
<!-- Latitude Form Input -->
<div class="form-group">
<label for="street">Straße:</label>
<input class="form-control" name="street" type="text" id="street">
</div>
<!-- Notruftyp Form Input -->
<div class="form-group">
<label for="type">Notruftyp:</label>
<select class="form-control" id="type" name="type"><option value="1">CPR</option></select>
</div>
<!-- Notruf erfassen Form Input -->
<div class="form-group">
<input class="btn btn-primary form-control" type="submit" value="Notruf erfassen">
</div>
</form>
Update 3
I inserted a console.log at the beginning of the closure:
var submitAjaxRequest = function(e) {
console.log("submitAjaxRequest OK");(...)
And the function is being called. The console prints the message. So I think something is wrong with the event.
Update 4
So I tried to use the pubSub System to listen to this event. Therefore I
function reverseGeoCode() {
$.subscribe('form.submitted', function() {
console.log("OK");
})
}
But there is no reaction when I hit the submit button in the console. I used this function in a different script somewhere else on the page. Shouldn't it still react to the publish?
I have the following problem:
2 forms that need to be submitted with one button. I will explain how it should work.
And of course my code so far.
#frmOne contains a url field where I need to copy the data from to my #frmTwo, this works.
(it forces the visitor to use www. and not http:// etc)
When I press 1 submit button
Verify fields #frmOne (only url works now, help needed on the others)
Call #frmTwo and show result in iframe. result shows progress bar (works)
But Div, modal or any other solution besides iframe are welcome.
Close #frmOne (does not work)
Finally process (submit) #frmOne if #frmTwo is done (does not work)
Process completed code of #frmTwo in iframe =
<div style='width' id='information'>Process completed</div>
<ol class="forms">
<iframe width="100%" height="50" name="formprogress" frameborder="0" scrolling="no" allowtransparency="true"></iframe>
<div id="txtMessage"></div>
</ol>
<div id="hide-on-submit">
<form id="frmOne" method="post">
<input type="text" name="company" id="company" >
<input type="text" name="url" id="url" >
<input type="text" name="phone" id="phone" >
<input type="text" name="occupation" id="occupation" >
<textarea rows="20" cols="30" name="summary" id="summary" >
<button type="submit" class="btn btn-danger">Submit</button>
</form>
</div>
<form id="frmTwo" method="post" target="formprogress"></form>
<script>
jQuery(document).ready(function(){
//Cache variables
var $frmOne = $('#frmOne'),
$frmTwo = $('#frmTwo'),
$txtMessage = $('#txtMessage'),
frmTwoAction = 'http://www.mydomainname.com/form.php?url=';
//Form 1 sumbit event
$frmOne.on('submit', function(event){
event.preventDefault();
var strUrl = $frmOne.find('#url').val();
//validation
if(strUrl === ''){
$txtMessage.html('<b>Missing Information: </b> Please enter a URL.');
}
else if(strUrl.substring(0,7) === 'http://'){
//Clear field
$frmOne.find('#url').val('');
$txtMessage.html('<b>http://</b> is not supported!');
}
else if(strUrl.substring(0,4) !== 'www.'){
//Clear field
$frmOne.find('#url').val('');
$txtMessage.html('<b>Invalid URL</b> Please enter a valid URL!');
}
else{
//set form action and submit form
$frmTwo.attr('action', frmTwoAction + strUrl).submit();
$('#hide-on-submit').hide(0).fadeIn(1000);
$('form#frmOne').submit(function(e) {
$(this).hide(1000);
return true; // let form one submit now!
}
return false;
});
});
</script>
read here https://api.jquery.com/jQuery.ajax/. basically you need to submit the first one with $.ajax and then, when you get the server response (in the success() function ) you need to send the second form, again width ajax().
Something like:
$form1.on('submit', function(e) {
e.preventDefault(); //don't send the form yet
$.ajax(
url: $(this).attr('action'),
type: $(this).attr('method'),
data: $(this).serialize()
).success(function(data) {
alert('form one sent');
$.ajax(
url: $('#form2').attr('action'),
type: $('#form2').attr('method'),
data: $('#form2').serialize()
).success(function(data) {
alert('form two sent');
})
});
});
This code isn't ready to be copy/pasted, it's just to give you a guideline of how I would solve it. It's a big question, try going with this solution and come back with smaller question if you find yourself blocked.