Ajax post not working in window beforeunload - javascript

i have multiple identical forms (one for each month) that sit on multiple sections using this script :
http://www.jquery-steps.com/Examples
no problems there.
When i hit the next or previous buttons, i post the data on the form with this :
var tsf = $('.tsf-wizard-1').tsfWizard({
stepEffect: 'basic',
stepStyle: 'style1',
validation: false,
navPosition: 'top',
manySteps: true,
stepTransition: true,
showButtons: true,
showStepNum: true,
height: '500px',
prevBtn: '<i class="fa fa-chevron-left"></i> Vorige Maand',
nextBtn: 'Volgende Maand <i class="fa fa-chevron-right"></i>',
finishBtn: '<i class="fa fa-table"></i> Overzicht',
onNextClick: function (e, from, to, validation) {
var stap = from+1;
var formstep = '#'+stap.toString()+'_form';
var pathname = window.location.pathname; // Returns path only
var url = window.location.href;
$.ajax({
type: 'post',
url: 'user_settings/add_data',
data: $(formstep).serialize(),
success: function () {
console.log($(formstep).serialize());
},
error: function (){
$( "#remarks").html("<span class=\"label label-danger\">ERROR !</span> Problem saving..");
}
});
},
onPrevClick: function (e, from, to, validation) {
var stap = from+1;
var formstep = '#'+stap.toString()+'_form';
$.ajax({
type: 'post',
url: 'user_settings/add_data',
data: $(formstep).serialize(),
success: function () {
console.log($(formstep).serialize());
},
error: function (){
$( "#remarks").html("<span class=\"label label-danger\">ERROR !</span> Problem saving..");
}
});
}
});
But, when the user leaves the page i want to have all of the forms posted with an ajax call. So i tried this (The hold.open and .close is busy indicator)
$(window).on('beforeunload', function ()
{
//this will work only for Chrome
pageSave();
});
$(window).on("unload", function ()
{
//this will work for other browsers
pageSave();
});
function pageSave()
{
if (!_wasPageSaved)
{
HoldOn.open({
theme:'sk-cube-grid',
message:"<h4>Savig data..</h4>"
});
var goodsaves=0;
for (i = 1; i <= 12; i++) {
var formstep = '#'+i.toString()+'_form';
$.ajax({
type: 'post',
url: '<?php echo base_url();?>user_settings/add_data',
data: $(formstep).serialize(),
success: function () {
goodsaves=goodsaves+1;
},
error: function (){
console.log('error saving data :');
}
});
}
HoldOn.close();
if (goodsaves=>11) {
_wasPageSaved = true;
console.log('all forms saved');
}
}
}
Problem is that sometimes the data is saved, sometimes not. I can't put my finger on it why it doesn't always work . I see the busy indicator, i don't get any alerts in my console and the next page is loaded. But my data isn't saved...
hope anyone can clear this out , thanks allot in advance.

Related

Bootbox dialog.modal('hide') doesn't hide modal

I have a problem with bootbox.js modals. I wanted to use bootbox.dialog for pausing UI while Ajax is being executed and waiting for response. Everything works cool if I use dialog.modal('hide'); inside bootbox.alert with confirm (after clicking OK it hides dialog.modal), but I'd not like to confirm it every time. When I'm using dialog.modal('hide'); outside the bootbox.alert with confirm it doesn't hide dialog.modal... Where is the problem? Working code (hiding modal) is inside success and not working is inside error
var dialog = bootbox.dialog({
message: '<p class="text-center mb-0"><i class="fa fa-spin fa-cog"></i> Please wait while we do something...</p>',
closeButton: false
});
var checkboxId = "#" + $(this).attr('id');
var checked = $(this).is(":checked");
if (checked) {
$.ajax({
url: url,
type: "POST",
data: { estimatedCostId: #Model.EstimatedCostID },
success: function (data) {
if (!data.Success)
{
bootbox.alert(data.ErrorMessage, function () {
dialog.modal('hide');
});
$(checkboxId).prop('checked', !checked);
}
},
error: function (request, status, error) {
dialog.modal('hide');
bootbox.alert("Błąd serwera");
$(checkboxId).prop('checked', !checked);
}
});
}
Most likely, this is a timing issue. If your AJAX call is "too quick", the success/fail callbacks are being called before the bootbox.dialog function has resolved. So, this:
dialog.modal('hide');
winds up being called on an undefined object. I was running into a similar issue on a recent project, and solved it by putting the AJAX call into the shown.bs.modal event, like so:
var checkboxId = "#" + $(this).attr('id');
var checked = $(this).is(":checked");
var dialog = bootbox.dialog({
message: '<p class="text-center mb-0"><i class="fa fa-spin fa-cog"></i> Please wait while we do something...</p>',
closeButton: false
})
// this is the change
.on('shown.bs.modal', function(){
if (checked) {
$.ajax({
url: url,
type: "POST",
data: { estimatedCostId: #Model.EstimatedCostID },
success: function (data) {
if (!data.Success)
{
bootbox.alert(data.ErrorMessage, function () {
dialog.modal('hide');
});
$(checkboxId).prop('checked', !checked);
}
},
error: function (request, status, error) {
dialog.modal('hide');
bootbox.alert("Błąd serwera");
$(checkboxId).prop('checked', !checked);
}
});
}
});
You can use this also in a simple way
bootbox.hideAll();

How to make a progress loading in Ajax function while the function is inserting the data in the database?

I have problem regarding inserting the data in the database. I have a function which inside the function has a 4 ajax, so to make story short.
I want to make a progress loading inside of on click function to determine that my 4 ajax inserting data already done or finish. after already insert the data in the database. It will automatically redirect my page to the other page. Is it possible to make it on the on click function? if so can you help me guys to make that kind of progress bar.
Goal: If I click the submit button, the progress bar will load automatically until the storing the data in the database finish, and after loading the progress bar it will automatically redirect to the other page.
I have here my on click function for submitting all the ajax function.
var orderNumber;
var orders = [];
var menu;
var customer_id = $('#hidden_customer_id').val();
$('#add_to_cart').on('click', function() {
orders = [];
menu = undefined;
$('.tbody_noun_chaining_order').children('tr').each(function() {
$row = $(this);
if ($row.hasClass('condimentParent')) {
// store a previous menu to the orders array if exists.
if (menu) {
orders.push(menu);
}
menu = {
'total': $row.find('.total').text(),
'name': $row.find('.parent_item').text(),
'customer_id': customer_id,
'condiments': {
'Item': [],
'Qty': [],
'Total': []
}
};
} else if ($row.hasClass('editCondiments')) {
menu.condiments.Item.push($row.find('.child_item').text());
menu.condiments.Qty.push($row.find('.condiments_order_quantity').text());
menu.condiments.Total.push($row.find('.total').text());
}
});
if (menu) {
orders.push(menu);
}
storeOrder(orders);
$('table#noun_chaining_order').find('.tbody_noun_chaining_order').empty();
$('.append_customer_noun_order_price').text('0.00');
$('.total_amount').text('0.00');
$('.total_amount').text('0.00');
$('.rate_computation').text('0.00');
});
This is my function inside of this are the ajax inserting data in the database.
function storeOrder(data) {
var customer_id = $('#hidden_customer_id').val();
var place_customer = $('#place_customer').text();
// reset
$id = "";
$total_amount = $('.total_amount').text();
$append_customer_noun_order_price = $('.append_customer_noun_order_price').text();
$tax_rate = $('.rate_computation').text();
$delivery_rate = $('.del_rate').text();
var sessionTransactionNumber_insert = localStorage.getItem('sessionTransactionNumber');
$.ajax({
url:'/insert_customer_order_properties',
type:'POST',
data:{
'hidden_customer_id': customer_id,
'hidden_customer_address': place_customer,
'sessionTransactionNumber': sessionTransactionNumber_insert
},
success:function(data) {
$id = data[0].id;
$.ajax({
url:'/insert_customer_payment_details',
type:'POST',
data:{
'hidden_customer_id': customer_id,
'total_amount': $total_amount,
'customer_sub_total': $append_customer_noun_order_price,
'tax_rate': $tax_rate,
'id_last_inserted': $id
},
success:function(data) {
localStorage.removeItem('sessionTransactionNumber');
}
})
}
})
for (var num in orders) {
// simulate storing the order
$.ajax('/insert_wish_list_menu_order', {
type: 'POST',
// as the call is asynchronous, make sure to provide all required reference data along with the call.
context: orders[num].condiments,
data: {
// 'json': '{"orderNumber":' + (orderNumber++) + '}',
'append_customer_noun_order_price': orders[num].total,
'append_customer_noun_order': orders[num].name,
'customer_id': customer_id
},
success: function(orderNumber) {
$order_number = orderNumber[0].id; // meron na tayong kuha ng main item..
$.ajax({
url:'/insert_customer_order_details_properties',
type:'POST',
data:{
'order_number': $order_number,
'data_attribute_wish_order_id': $id,
},
success:function(data) {
console.log(data);
}
})
if (orderNumber !== undefined) {
$.ajax('/insert_wish_list_menu_belong_condiments', {
context: orderNumber,
type: 'POST',
data: {
'ParentId': orderNumber,
'Item': this.Item,
'Qty': this.Qty,
'Total': this.Total
},
success: function(result) {
console.log(result);
// setTimeout(function () {
// swal({
// title: "Wow!",
// text: "Message!",
// type: "success",
// confirmButtonText: "OK"
// },
// function(isConfirm){
// if (isConfirm) {
// window.location.href = "//stackoverflow.com";
// }
// }); }, 1000);
},
})
}
}
})
}
}
There's functions in javascript namely .ajaxStart and .ajaxStop which you can work around. Typical example:
$(document).ready(function(){
$( document ).ajaxStart(function() {
//start progress bar
});
$( document ).ajaxStop(function() {
//stop progress bar and redirect
});
//other code here with you ajax calls
...
})
in this case $(document).ajaxStart() and $(document).ajaxStop() listen for any ajax call in the entire document
Read more about ajaxStart and ajaxStop
You could declare a variable to store the loading progress and in every ajax success calback you can increment this variable:
// declare inside click handler
var loadingPercentage = 0; // percentage
// in every success handler
loadingPercentage += 25;
When all 4 ajax calls were successful, you would have the variable set to 100%.
Depending on loadingPercentage you could display a progressbar.

Show Gif on click and Hide after Ajax Success

I found lots os posts with the solution to my problem, but no one works to me...
I tried like:
<div class="ibox-content">
<div id="carregando" class="text-center" style="display:none">
<img src="~/Imagens/logo.png" />
</div>
<div id="container" style="height: 460px; margin: 0 auto"></div>
</div>
My JS is called on a button clink who calls a funcion like bellow:
$("#atualiza").click(function () {
$(document).ajaxStart(function () {
$("#carregando").show();
});
$.ajax({
url: '/Portaria/AtendOperador',
dataType: "json",
type: "GET",
data: { 'data1': data1, 'data2': data2, 'evento': evento, 'cuc': cuc, 'conta': conta },
async: false,
cache: false,
delay: 15,
success: function (data) {
var Categories = new Array();
var Series = new Array();
for (var i in data) {
Categories.push(data[i].Operador);
Series.push(data[i].Fechados);
}
var CategArray = JSON.parse(JSON.stringify(Categories));
atendOperador(CategArray, Series);
$(document).ajaxStop(function () {
$("#carregando").hide();
});
},
error: function (xhr) {
alert('error');
$(document).ajaxStop(function () {
$("#carregando").hide();
});
}
});
});
function atendOperador(CategArray, Series) {
var chart2 = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar'
}
});
}
Even I put the code:
$( document ).ajaxStart(function() {
$( "#carregando" ).show();
});
The image appear only after ajax finishing. Using the two blocks, show and Hide, the image not appear, so, i tried to remove the hide block and i could see that the problem is: Show and Hide happens together when ajax is loaded like:
I cliked on button and noting happened like: http://prntscr.com/ars97n
And after few seconds, Ajax load data and show icon and data together: http://prntscr.com/ars9xq
Try $("#carregando").hide(); instead of $(document).ajaxStop(function ()$("#carregando").hide();});
edit: ajaxStart and ajaxEnd are event handlers. I think they should be registered outside of the click function. Something like this:
$(document).ready(function(){
$(document).ajaxStart(function () {
$("#carregando").show();
});
$(document).ajaxStop(function () {
$("#carregando").hide();
});
$("#atualiza").click(function () {
/* all your code here except for the ajaxStart/ajaxStop portion */
});
});
As Karl stated, the best way to do it is without using ajaxStart/ajaxStop event handlers, or even better, without using jQuery at all.
document.querySelector('.get-data').addEventListener('click', function() {
document.querySelector('.display-data').textContent = null;
document.querySelector('.loading').style.display = 'block';
var request = new XMLHttpRequest();
request.open('GET', 'http://jsonplaceholder.typicode.com/photos', true);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
// Success!
var data = JSON.parse(this.response);
document.querySelector('.loading').style.display = 'none';
document.querySelector('.display-data').textContent = JSON.stringify(data[0]);
} else {
// We reached our target server, but it returned an error
document.querySelector('.loading').style.display = 'none';
}
};
request.onerror = function() {
// There was a connection error of some sort
document.querySelector('.loading').style.display = 'none';
};
request.send();
});
<button class="get-data">Get Data</button>
<div class="loading" style="display: none">
<img src="https://upload.wikimedia.org/wikipedia/commons/2/28/InternetSlowdown_Day.gif" width="50px">
</div>
<div class="display-data"></div>
Finally! I found the problem here! All ways I tried before works now, with this modification I did.
Just:
$("#carregando").show();
Or:
$(document).ajaxStart(function () {
$("#carregando").show();
});
$(document).ajaxStop(function () {
$("#carregando").hide();
});
Or:
beforeSend: function() {
$("#carregando").show();
},
complete: function() {
$("#carregando").hide();
},
All my problem were here: http://prntscr.com/asbxbk!!!
So, I commented that async and works!!!
$("#atualiza").click(function () {
$(document).ajaxStart(function () {
$("#carregando").show();
});
$(document).ajaxStop(function () {
$("#carregando").hide();
});
$.ajax({
url: '/Portaria/AtendOperador',
dataType: "json",
type: "GET",
data: { 'data1': data1, 'data2': data2, 'evento': evento, 'cuc': cuc, 'conta': conta },
//async: false, COMMENTED!!!
success: function (data) {
var Categories = new Array();
var Series = new Array();
for (var i in data) {
Categories.push(data[i].Operador);
Series.push(data[i].Fechados);
}
var CategArray = JSON.parse(JSON.stringify(Categories));
atendOperador(CategArray, Series);
},
error: function (xhr) {
alert('error');
}
});
});
Karl's answer is correct if you want to show the same git for all ajax request on the page
But if you want to do it for this particular AJAX the follow this
$("#atualiza").click(function () {
$.ajax({
beforeSend: function() { $("#carregando").show(); }, //It will show the gif just before sending the request
url: '/Portaria/AtendOperador',
dataType: "json",
type: "GET",
data: { 'data1': data1, 'data2': data2, 'evento': evento, 'cuc': cuc, 'conta': conta },
async: false,
cache: false,
delay: 15,
success: function (data) {
var Categories = new Array();
var Series = new Array();
for (var i in data) {
Categories.push(data[i].Operador);
Series.push(data[i].Fechados);
}
var CategArray = JSON.parse(JSON.stringify(Categories));
atendOperador(CategArray, Series);
$("#carregando").hide(); //this will hide the gif in case of AJAX success
},
error: function (xhr) {
alert('error');
$("#carregando").hide(); //this will hide the gif in case of AJAX failure
}
});
});
Hope this will help you

Ajax, prevent multiple request on click

I'm trying to prevent multiple requests when user click on login or register button. This is my code, but it doesn't work. Just the first time works fine, then return false..
$('#do-login').click(function(e) {
e.preventDefault();
if ( $(this).data('requestRunning') ) {
return;
}
$(this).data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
});
Any ideas? Thanks!
The problem is here:
complete: function() {
$(this).data('requestRunning', false);
}
this no longer points to the button.
$('#do-login').click(function(e) {
var me = $(this);
e.preventDefault();
if ( me.data('requestRunning') ) {
return;
}
me.data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
me.data('requestRunning', false);
}
});
});
Use on() and off(), that's what they are there for :
$('#do-login').on('click', login);
function login(e) {
e.preventDefault();
var that = $(this);
that.off('click'); // remove handler
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize()
}).done(function(msg) {
// do stuff
}).always(function() {
that.on('click', login); // add handler back after ajax
});
});
In your ajax callbacks the context (this) changes from the outer function, you can set it to be the same by using the context property in $.ajax
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this, //<-----
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
You can disable the button.
$(this).prop('disabled', true);
I have also faced a similar problem.
Just adding $('#do-login').attr("disabled", true); gives me the solution.
$('#do-login').click(function(e) {
e.preventDefault();
$('#do-login').attr("disabled", true);
.........
.........
Here do-login is button id.
I've tried this and worked very fine for me, I was having trouble that $.ajax send more request until results return,
var settings = {
"url": "/php/auth/login.php",
"method": "POST",
"timeout": 0,
"async": false,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"data": jsondata, //data pass here is in JSON format
};
$.ajax(settings).done(function (ress) {
try{
console.log(ress, "Result from Ajax here");
}
catch(error){
alert(error);
console.log(ress);
}
});
async : false worked for me.
Thanks.
Or you can do it by $(this).addClass("disabled"); to you button or link and after click is performed, you can $(this).removeClass("disabled");.
// CSS
.disabled{
cursor: not-allowed;
}
// JQUERY
$('#do-login').click(function(e) {
e.preventDefault();
$(this).addClass("disabled");
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this,
success: function(msg) {
//do more here
$(this).removeClass("disabled");
},
});
});
P.S. If you use bootstrap css, you do not need the css part.
I found the approach useful. I've implemented it as a general purpose function for jQuery with ES6.
export default function (button, promise) {
const $button = $(button);
const semaphore = 'requestRunning';
if ($button.data(semaphore)) return null;
$button.data(semaphore, true);
return promise().always(() => {
$button.data(semaphore, false);
});
}
Because $.ajax() returns a promise, you simply pass in the promise and the function takes care of the rest.
Roughly speaking, here's the usage.
import preventDoubleClick from './preventdoubleclick';
...
button.click(() => {
preventDoubleClick(this, () => $.ajax()
.done(() => { console.log("success") }));
});
This function can help you with control multi Ajax requests and it's has timeout function which can return flag status to 0 after ex. 10sec (In case the server took more than 10 seconds to respond)
var Request_Controller = function(Request_Name = '', Reactivate_Timeout = 10000)
{
var a = this;
a.Start_Request = function(){
if(window.Requests == undefined){
window.Requests = {};
}
window.Requests[Request_Name] = {'Status' : 1, 'Time': + new Date()};
}
a.End_Request = function(){
if(window.Requests == undefined){
window.Requests = [];
}
window.Requests[Request_Name] = undefined;
}
a.Is_Request_Running = function(){
if(window.Requests == undefined || window.Requests[Request_Name] == undefined){
return 0;
}else{
var Time = + new Date();
// Reactivate the request flag if server take more than 10 sec to respond
if(window.Requests[Request_Name]['Time'] < (Time - Reactivate_Timeout))
{
return 0;
}else{
return 1
}
}
}
}
To use it:
var Request_Flag = new Request_Controller('Your_Request_Name');
if(!Request_Flag.Is_Request_Running()){
Request_Flag.Start_Request();
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
Request_Flag.End_Request();
}
});
}
for prevent multiple ajax request in whole site. For example: If use ajax request in other ajax page, Using ajax in php loop, etc, Give you multiple ajax request with one result. I have solution:
Use window.onload = function() { ... }
instead of
$(document).ready(function(){ ... });
on the main index.php page. Its will be prevent all multi request. :)

javascript returning an object but not what I expected to see

My code is returning an object and not what I expected to see. When I output the output in console, I get object but all the data is there. What is supposed to happen, is that the id is passed to actionrow and this does the ajax call to the db. The object is being output from console.log(datarow); in the code.
I am using jqxWidgets for grid and data
// action row.
$("#actionrowbutton").bind('click', function () {
var selectedrowindex = $("#jqxgrid").jqxGrid('getselectedrowindex');
var datarow = $("#jqxgrid").jqxGrid('getrowdata', selectedrowindex);
var rowscount = $("#jqxgrid").jqxGrid('getdatainformation').rowscount;
if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
var rows = $('#jqxgrid').jqxGrid('getrows', selectedrowindex);
var id = $("#jqxgrid").jqxGrid('getrowid', selectedrowindex);
//var service = datarow;
console.log(datarow);
$("#jqxgrid").jqxGrid('actionrow', id);
//Open action dialog window
$( "#actionWindow" ).dialog({
//title: 'action error',
resizable: false,
modal: true,
position: ['center', 'center'],
buttons: {
"Ok": function() {
$(this).dialog("close");
$('#jqxgrid').jqxGrid('refreshdata');
},
Cancel: function() {
$( this ).dialog( "close" );
//$('#jqxgrid').jqxGrid('refreshdata');
}
}
});
}
});
actionrow: function (actrowid) {
// synchronize with the server - send action command
var data = "action=true&id=" + actrowid;
$.ajax({
dataType: 'json',
url: 'data.php',
data: data,
success: function (data, status, xhr) {
// action command is executed.
}
});
}
After looking at your code, I am left with a question.
What is "actionrow", is it a function or a method of jqxgrid object? If it isn't it should be written like so:
function actionrow(actrowid) {
// synchronize with the server - send action command
var data = "action=true&id=" + actrowid;
$.ajax({
dataType: 'json',
url: 'data.php',
data: data,
success: function (data, status, xhr) {
// action command is executed.
}
});
}
And called like so in your if statement.
actionrow(id); //not $("#jqxgrid").jqxGrid('actionrow', id);

Categories