I have a form downloaded from http://reusableforms.com/ that works great on desktop. But the submit button changes to "sending ..." and gets stuck on mobile devices. An error message doesn't display and the page just stops working. What would cause this problem? I am putting my javascript code below. Here is the site for reference: http://jasminew.xyz/flash
$(function()
{
$.ajaxSetup({ cache: false }); // or iPhones don't get fresh data
function after_form_submitted(data)
{
if(data.result == 'success')
{
$('#carouselExampleIndicators').hide();
$('form#reused_form').hide();
$('#success_message').show();
$('#error_message').hide();
}
else
{
$('#error_message').append('<ul></ul>');
jQuery.each(data.errors,function(key,val)
{
$('#error_message
ul').append('<li>'+key+':'+val+'</li>');
});
$('#success_message').hide();
$('#error_message').show();
//reverse the response on the button
$('button[type="button"]', $form).each(function()
{
$btn = $(this);
label = $btn.prop('orig_label');
if(label)
{
$btn.prop('type','submit' );
$btn.text(label);
$btn.prop('orig_label','');
}
});
}//else
}
$('#reused_form').submit(function(e)
{
e.preventDefault();
$form = $(this);
//show some response on the button
$('button[type="submit"]', $form).each(function()
{
$btn = $(this);
$btn.prop('type','button' );
$btn.prop('orig_label',$btn.text());
$btn.text('Sending ...');
});
var formdata = new FormData(this);
$.ajax({
type: "POST",
url: 'handler.php',
data: formdata,
success: after_form_submitted,
dataType: 'json' ,
processData: false,
contentType: false,
cache: false,
});
});
});
EDIT
I have opened remote Safari dev tools and the XHR Post is timing out. I'm not sure what that means.
EDIT
Okay, the problem is that the form stops working if the two upload fields in the form aren't used on iOS. Does anyone know a workaround?
I reviewed your code and would suggest some minor updates:
$(function() {
$.ajaxSetup({
cache: false
}); // or iPhones don't get fresh data
function after_form_submitted(data) {
if (data.result == 'success') {
$('#carouselExampleIndicators').hide();
$('form#reused_form').hide();
$('#success_message').show();
$('#error_message').hide();
} else {
$('#error_message').append('<ul></ul>');
$.each(data.errors, function(key, val) {
$("<li>").html(key + ": " + val).appendTo($('#error_message ul'));
});
$('#success_message').hide();
$('#error_message').show();
//reverse the response on the button
$('button[type="button"]', $form).each(function() {
var $btn = $(this);
var label = $btn.data('orig-label');
if (label) {
$btn.prop('type', 'submit');
$btn.text(label);
$btn.data('orig-label', null);
}
});
}
}
$('#reused_form').submit(function(e) {
e.preventDefault();
var $form = $(this);
//show some response on the button
$('button[type="submit"]', $form).each(function() {
var $btn = $(this);
$btn.prop('type', 'button');
$btn.data('orig-label', $btn.text());
$btn.text('Sending ...');
});
var formdata = new FormData($form[0]);
$.ajax({
type: "POST",
url: 'handler.php',
data: formdata,
success: after_form_submitted,
dataType: 'json',
processData: false,
contentType: false,
cache: false,
});
});
});
I see nothing that is "wrong", just some syntax cleanup. Also this was sort of ambiguous in the creation of FormData, so I switched to a more specific element: $form[0].
I adjusted a few other things to be more jQuery like. All functions the same.
Also, make sure that Ajax URL path is correct. You have:
url: 'handler.php'
Make sure that your can browse to this directly. If the path is not correct, the form will not post properly. It may be better to use a Direct URL Path instead of a relative path.
If you have access to your Web Server or PHP Logs, you can also check there to see if POSTs to your handler.php script are failing in some way. In Safari, you may want to check Network results and see if it provide more response details.
Test it, let me know if it works any better.
Related
I have been struggling with a problem for some time. I cannot understand the reason as it happens in a specific case, not with the others.
I have a javascript function that calls a PHP script to upload a file to the server (standard code, have been using it and works perfectly normally).
function upload_picture(fieldID, success, error) {
var folderName;
switch (fieldID) {
case "pop_drawing":
folderName = "pop_dwg";
break;
case "pop_installation":
folderName = "pop_inst";
break;
case "pop_picture":
folderName = "pop_pict";
break;
}
var file_data = $('#' + fieldID).prop('files')[0];
var form_data = new FormData();
form_data.append('folder', folderName);
form_data.append('file', file_data);
$.ajax({
url: 'dbh/upload.php',
dataType: 'text',
type: 'POST',
cache: false,
contentType: false,
processData: false,
data: form_data,
success: function (response) {
event.preventDefault();
console.log (response); // display success response from the PHP script
if (response.indexOf("yüklendi") > 0) {
success();
}
},
error: function (response) {
event.preventDefault();
console.log (response); // display success response from the PHP script
error(response);
}
});
}
The function is called from several points in the code and it works OK except one point. At this particular point when it returns it changes the page URL from
http://localhost/pop/#
to
http://localhost/pop/?pop_drawing=&pop_installation=&pop_picture=Compelis-Logo.jpg&pop_need_special_prod=Hay%C4%B1r&pop_need_application=Hay%C4%B1r&pop_order_made=Evet&pop_approval=4&pop_cost_visible=Hay%C4%B1r#
due to a reason I could not understand. This string in the URL line are some parameters on the web page where I press the button to call the function.
The code which call the function is:
function uploadPopPicture () {
if ($('#pop_picture_label').html() !== 'Seçili dosya yok...') {
upload_picture('pop_picture',
function(){
console.log('Görsel yüklendi...');
},
function(error){
console.log('Error:', error);
});
}
}
Same code (obviously with different parameters) is used elsewhere in the program and works OK.
Any ideas what I might be missing.
Many thanks in advance
A button's default behaviour is "submit". If you don't specify any particular behaviour then that's what it will do. So when clicked it will submit your form, regardless of any JavaScript.
Add the attribute type="button" to your button HTML and that will stop it from automatically submitting the form.
I'm sure there's a simple explanation for this but I haven't been able to find the right words to use when searching for answers.
When users fill out the form .InvoiceForm it submits via Ajax. After it's submitted remove the .InvoiceForm class and add .UpdateInvoice. When a user submits a .UpdateInvoice form it explains that they are about to make a change and they have to click to say "Yes I want this to be updated".
The issue is that unless I refresh the page so that the form is loaded with the .UpdateInvoice form, I don't get the confirmation which means it's still submitting as a .InvoiceForm form. Is there anything I can do to fix this?
Edit to show code:
Code that runs if there's no record
$('.InvoiceForm').submit(function(e) {
$.ajax({
url: $(this).attr('action'),
type: 'POST',
cache: false,
dataType: 'json',
context: this,
data: $(this).serialize(),
beforeSend: function() {
$(".validation-errors").hide().empty();
},
success: function(data) {
$(this).removeClass('InvoiceForm');
$(this).addClass('UpdateInvoice');
$(this).find('.btn').val('Update');
$(this).find('.id').val(data.invoice_id);
$(this).find('.btn').removeClass('btn-default');
$(this).find('.btn').addClass('btn-danger');
$(this).find('.AddRow').removeClass('hide');
$(this).find('.invoiceDetails').html(data.returnedData);
$(this).parent().next().find('.grade').focus();
}
});
return false;
};
Code that runs if there is a record being updated
$('.UpdateInvoice').submit(function(){
var r = confirm("Are you sure you want to make this update?");
if (r == true) {
$.ajax({
url: $(this).attr('action'),
type: 'POST',
cache: false,
dataType: 'json',
context: this,
data: $(this).serialize(),
beforeSend: function() {
$(".validation-errors").hide().empty();
},
success: function(data) {
alert('This row has been updated');
$(this).find('.total').html(data);
}
});
} else {
}
return false;
});
The function for .UpdateInvoice doesn't run unless I refresh the page.
Thanks for your help.
You bind a click event on '.UpdateInvoce' before it even being created, hence it'll not work. I think you need to use .live() in order to make it works. See document here: jQuery's live()
HTML:
<button id="click_me" class="new">Click Me</button>
<div class="result" />
Script:
$(function () {
$('.new').click(function (e) {
$('.result').text("Im new !");
$(this).removeClass("new");
$(this).addClass("update");
// Bind UpdateInvoice's click event on the fly
$('.update').live(bindUpdate());
});
function bindUpdate() {
$('.update').click(function (e) {
$('.result').text("Update me !");
});
}
});
jsfiddle's demo
I have a one-page design, where I set a main div to hold and show the current "page" content (with jquery)
Then I have this in a js file:
$(document).on("submit", "#kontaktform", function(){
$theform = $(this);
$.ajax({
url: "kontakt_val.php",
type: "POST",
cache: false,
timeout: 5000,
data: $theform.serialize(),
success: function(data) {
if (!data OR data=="ok") {
// AJAX ERROR OR OK: Continue to php validation
$("input[type=submit]",$theform).attr("disabled", "disabled");
$theform.unbind("submit").submit();
} else {
$("#jserrors").html('<p class="error">' + data + '</p>');
$("#jserrors").slideDown(150);
}
},
error: function(e) {
// AJAX ERROR: continue to php validation
$("input[type=submit]", $theform).attr("disabled", "disabled");
$theform.unbind("submit").submit();
}
});
return false;
});
$theform.unbind("submit").submit(); does not seem to submit the form
I'm thinking, it's because the form is in content that is dynamically added with js/jquery
How to fix this?
This seems to work:
document.forms["kontaktform"].submit();
Don't know how to do it Jquery style though
I have a javascript function that is called when the user clicks on a button and performs an AJAX query that adds some data to my database. However, I've been getting complaints that a lot of data hasn't been getting through, and I've isolated the problem to be the time between clicks. When they wait long enough between clicks, the data always gets through, but if they don't wait long enough it's a crapshoot.
So I'm pretty much settled that the problem is that the javascript function is being called again while it is already running, which I shouldn't allow. Is there a way I can lock the user's browser at the beginning of the function and unlock it at the end after the AJAX? I know this may irritate my users, but I can't see any other solution.
It's not totally necessary, but here's what my javascript function looks like:
function addtolist(thisform, sdata)
{
var scntDiv = $('#p_data');
var request = $.ajax({ async: false, url: "php_addtolist.php", type: "POST", data: {data:sdata}, dataType: "html" });
request.done(function(msg) { outdata = parseInt(msg); });
$(outdata).appendTo(scntDiv);
}
You can disable the button when the function is called, then re-enable it with the complete callback:
function addtolist(thisform, sdata)
{
$('#submit_btn').prop('disabled', true);
var scntDiv = $('#p_data');
var request = $.ajax({
async: false,
url: "php_addtolist.php",
type: "POST",
data: {data:sdata}, dataType: "html" },
complete: function() { $('#submit_btn').prop('disabled', false); }
);
request.done(function(msg) { outdata = parseInt(msg); });
$(outdata).appendTo(scntDiv);
}
Basically it seems like the outdata is async. the following should resolve.
function addtolist(thisform, sdata)
{
var scntDiv = $('#p_data');
var request = $.ajax({ async: false, url: "php_addtolist.php", type: "POST", data: {data:sdata}, dataType: "html" });
request.done(function(msg) {
outdata = parseInt(msg);
$(outdata).appendTo(scntDiv);
});
}
i have written a basic commenting system which is a simple write to database form and it uses ajax as well.
The issue is that if i enter my message, and then spam send / the enter key it seems to stack up and then everything is written to the database multiple times.
My ajax is like so:
$(document).ready(function(){
$(document).on('submit', '.addcomment', function() {
var $targetForm = $(this);
$.ajax({
type: "POST",
url: "process/addcomment.php",
data: $targetForm.serialize(),
dataType: "json",
success: function(response){
if (response.databaseSuccess == true) {
$("#container").load("#container");
$targetForm.find('#addcommentbutton').attr("disabled", true);
}
else {
$ckEditor.after('<div class="error">Something went wrong!</div>');
}
}
});
return false;
});
});
The submit button does become disabled, but the form can still be entered via the enter keyboard button or even still with a mass spam of the submit button (which is supposed to be disabled)
Is there a way to 100% disable this form with jquery, until the success JSON message is received?
Anymore code just let me know!
In this case, i would not use delegation. I would instead bind the event directly to the form using .one since each form should submit only once (if that's the case.) If you instead only have one addComment form, then i question why you are using delegation in the first place.
$(commentForm).appendTo(selector).one("submit",function(e){
e.preventDefault(); // prevent this submit
$(this).submit(false); // prevent future submits
// submit data to server
})
Just keep track of if a request is in progress:
$(document).ready(function(){
var isSubmitting = false;
$(document).on('submit', '.addcomment', function() {
var $targetForm = $(this);
if (!isSubmitting) {
isSubmitting = true;
$.ajax({
...
success: function(response){
...
},
complete: function() { isSubmitting = false; }
});
}
});
There are lots of ways to handle this, but the best involves validating the data on the server end. You want to prevent people from overloading the database inadvertently (the "fat finger" problem) or deliberately (the bored script kiddie who decides to crash your server or fill your database with garbage).
The best solution:
Generate a one-time token when the page is requested (called a "nonce")
Post that nonce when you post the data
Only accept it on the server side if the nonce has never been used
This obviously requires you to keep track of a list of valid nonces, but it prevents any glitches or abuse of the send button.
Also, as others have pointed out, disable the button much earlier and only run the submit action handler once. That will help with the inadvertent double-clicks and so on, but you also need the nonce to prevent compulsive clickers or intentional misuse.
Can you do it like below:
$(document).ready(function(){
var isAjaxInProgress = null;
$(document).on('submit', '.addcomment', function() {
var $targetForm = $(this);
if(isAjaxInProgress === null || !$isAjaxInProgress ){
isAjaxInProgress = true;
$.ajax({
type: "POST",
url: "process/addcomment.php",
data: $targetForm.serialize(),
dataType: "json",
success: function(response){
if (response.databaseSuccess == true) {
$("#container").load("#container");
$targetForm.find('#addcommentbutton').attr("disabled", true);
}
else {
$ckEditor.after('<div class="error">Something went wrong!</div>');
}
isAjaxInProgress = false;
}
});
}
return false;
});
});
// declare a global ajax request variable
var is_request_sent = false;
function send_msg()
{
if(is_request_sent == false)
{
$.ajax({
type: "POST",
url: "process/addcomment.php",
data: $targetForm.serialize(),
dataType: "json",
success: function(result){
//alert(result);
is_request_sent = false;
},
error: function(a,b,c)
{
is_request_sent = false;
},
beforeSend: function(jqXHR, plain_jqXHR){
// set request object
is_request_sent = jqXHR;
// Handle the beforeSend event
},
complete: function(){
// update global request variable
is_request_sent = false;
// Handle the complete event
}
});
}
}