I have below code, it executes when I click on a button.
I need to display a progress bar/waiting image in the browser for 5 seconds, when user clicks on a button. How to set time out and how to display progress bar/waiting page image in the page when user clicks on a button
$("#btnSubmit").click(function(){
var formData = $("form").serialize();
$.ajax({
url: 'cgi-bin/config',
type: 'POST',
data: formData, // An object with the key 'submit' and value 'true;
success: function (result) {
console.log(result);
},
failure: function () {
alert("Ajax request failed!!!");
},error: function () {
alert("Ajax request failed to update data!!!");
}
});
});
i could able to fix my code with the link jsfiddle.net/joshdavenport/Qw6uv/4 , this works fine..
Use beforeSend and complete
$("#btnSubmit").click(function(){
var formData = $("form").serialize();
$.ajax({
url: 'cgi-bin/config',
type: 'POST',
data: formData, // An object with the key 'submit' and value 'true;
success: function (result) {
console.log(result);
},
failure: function () {
alert("Ajax request failed!!!");
},error: function () {
alert("Ajax request failed to update data!!!");
},
beforeSend: function(){
$('.progress').show();
},
complete: function(){
$('.progress').hide();
}
});
});
HTML
<div class="progress" style="display:none;"><img src="loading.gif" />Loading...</div>
$("#btnSubmit").click(function(){
var startTime = Date.now(),
// finish function is called at the end - when request is completed and at least 5s passed
// result will be null on error or whatever was received by success callback
finish = function (result) {
if (result === null) {
// probably error, handle it..
} else {
// handle result
}
$('#progress').hide();
},
checkDone = function (result) {
var r = Date.now() - startTime; // time taken by request
if (r < 5000) { // if less than 5s then set timeout for remaining time
setTimeout(function () {
finish(result);
}, 5000 - r);
} else { // if there was already 5s finish immediately
finish(result);
}
},
formData = $("form").serialize();
$('#progress').show();
$.ajax({
url: 'cgi-bin/config',
type: 'POST',
data: formData, // An object with the key 'submit' and value 'true;
success: function (result) {
console.log(result);
checkDone(result);
},
failure: function () {
alert("Ajax request failed!!!");
checkDone(null);
},
error: function () {
alert("Ajax request failed to update data!!!");
checkDone(null);
}
});
});
progress div example (just put in body):
<div id="progress" style="display:none;position:absolute;z-index:99999;top:0;left:0;width:100%;height:100%;opcity:0.7;background:url('/img/progress.gif') 50% 50% no-repeate #000"></div>
Related
I have 1 POST ajax and 1 GET ajax, and I have this:
$(document).ready(function () {
$(document).ajaxStart(function () {
$("#div28").show();
});
$(document).ajaxStop(function () {
$("#div28").hide();
});
});
It is for showing the LoadingGif, at this point it is showing for both Ajax requests, so what should I do to make the LoadingGif show only when the POST type ajax is working?
EDIT:
Here are my ajax functions:
$(document).ready(function () {
$.ajax({
contentType: "application/json; charset=utf-8",
type: 'GET',
url: 'api/Appointments/',
dataType: 'json',
success: function (result) {
if ((result.AppTime = "9:00") && (result.AppWithYritys = "Laakkonen")) {
document.getElementById("A9").style.background = "red";
}
else {
alert("error1");
}
},
error: function (error) {
alert("error");
},
});
});
and the POST ajax:
var request = $.ajax({
type: "POST",
data: JSON.stringify(app),
url: "/api/Appointments",
contentType: "application/json",
dataType: "html"
});
request.done(function (data) {
if (data != -1) {
alert("You Have successfully made an appointment");
location.assign("http://tid.fi");
}
else {
alert("There has been an error!");
}
});
request.fail(function (gr) {
location.assign("http://google.com");
});
};
POST ajax is in a custom function which is trigger on a button-click. Just an info.
using ajaxSend and ajaxComplete you can see what the "type" of request is
However, you'll need to keep a count of active requests too - possibly not required for your simple page - but it's good to have
$(document).ready(function () {
var started = 0;
$(document).ajaxSend(function (event, jqXHR, settings) {
if (settings.type == 'POST') {
if(!(started++)) { // only need to show on the first simultaneous POST
$("#div28").show();
}
}
});
$(document).ajaxComplete(function (event, jqXHR, settings) {
if (settings.type == 'POST') {
if(!(--started)) { // only hide once all simultaneous POST have completed
$("#div28").hide();
}
}
});
});
Solution without counters
$(document).ready(function () {
$(document).ajaxSend(function (event, jqXHR, settings) {
if (settings.type == 'POST') {
$("#div28").show();
}
});
$(document).ajaxStop(function () {
$("#div28").hide();
});
});
This will show on POST, and hide once all ajax has stopped - a little less obvious, but it's probably just as valid a solution
I think the easiest option is to create a tiny functions that you can use:
function showLoading(isLoading){
if(isLoading){
$("#div28").show();
}
else{
$("#div28").hide();
}
};
Then use as documented here Ajax events
just use the function either using the global events for your specific post or call the function directly on the beforeSend and complete event hooks.
Basically, sometimes the AJAX calls in my application are too fast and I need to delay some of them. I have a "progress/loading" icon and when it comes to the fast AJAX calls the icon appears and disappears too quickly. I need a way to set a minimum time for an AJAX action to finish (or at least to appear that way). Here's my generic ajax function that I use in my application.
var app = {
ajax: function (paramObject) {
$.ajax({
url: paramObject.url,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: paramObject.method || 'GET',
data: paramObject.data || '{}',
success: function (jsonResponse) {
if (paramObject.success) {
if (paramObject.successDelay) {
setTimeout(function() {
paramObject.success(jsonResponse);
}, paramObject.successDelay);
} else {
paramObject.success(jsonResponse);
}
}
}
});
}
}
As you can see I have a paramObject which takes some parameters like: url, method, data, success and successDelay. Currently, the AJAX call takes its time and when it finishes it takes in consideration the delay (successDelay) that I've set. But that's not really what I wanted. What I want is to track the delay between the start of the AJAX call and its end/success so the whole thing takes a minimum of successDelay milliseconds.
EDIT to further explain:
In essence I want to make it seem as though the AJAX call takes longer. And it needs to happen in the function I have above.
[EDIT]
Without understanding your code, I think this is what you want :
var app = {
ajax: function (paramObject) {
var timeStart = Date.now();
$.ajax({
url: paramObject.url,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: paramObject.method || 'GET',
data: paramObject.data || '{}',
success: function (jsonResponse) {
if (paramObject.success) {
if ((Date.now()-timeStart) < paramObject.successDelay) {
setTimeout(function() {
paramObject.success(jsonResponse);
}, paramObject.successDelay - (Date.now()-timeStart));
} else {
paramObject.success(jsonResponse);
}
}
}
});
}
}
Don't delay the AJAX, just check if you remove the waiting animation class with or without a delay :
// before the AJAX call
var timeStartMs = Date.now();
// On the success block, we check if more or less than 500ms
// and we remove the '.waiting' class
if(Date.now() < timeStartMs + 500)
setTimeout(function(){ $('.target').removeClass('waiting'); }, 500);
else
$('.target').removeClass('waiting');
Like this :
var timeStartMs;
function f() {
// before the AJAX call
var timeStartMs = Date.now();
var ping = Math.floor(Math.random() * 2000) + 1;
$('#target').addClass('waiting');
$('#target').html('Lag : '+ping);
// fake AJAX call :
setTimeout(function() {
if (Date.now() < timeStartMs + 500)
setTimeout(function() {
$('#target').removeClass('waiting');
}, 500);
else
$('#target').removeClass('waiting');
}, ping);
}
.waiting {
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="target">Click</div>
<button onclick="f()">run</button>
I haven't tested it, but I believe it does what you want.
var app = {
ajax: function (paramObject) {
var $d;
if (paramObject.successDelay) {
$d = $.Deferred();
setTimeout(function() {
$d.resolve();
}, paramObject.successDelay);
}
$.ajax({
url: paramObject.url,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: paramObject.method || 'GET',
data: paramObject.data || '{}',
success: function (jsonResponse) {
if (paramObject.success) {
if (paramObject.successDelay) {
$d.done(function(){
paramObject.success(jsonResponse);
});
} else {
paramObject.success(jsonResponse);
}
}
}
});
}
}
<script>
function Test()
{
var selected = new Array();
$('input:checked').each(function () {
selected.push($(this).attr('id'));
});
var postData = { values: selected };
var url = '#Url.Action("ExportExcelFilesToDropBox", "Home")';
$.ajax({
type: "POST",
url: url,
data: postData,
success: function (result) {
if (result == "Success")
{
AfterCreationOfFiles(selected);
}
}, dataType: "json",
traditional: true
});
}
function AfterCreationOfFiles(selected)
{
var MyFiles = [];
jQuery.each(selected, function (i, val) {
if(val=="Address")
{
MyFiles.push({ 'url': 'http://-----/Content/File/Addresses.xlsx', 'filename': 'Addresses.xlsx' });
}
if (val == "DebitDetail")
{
MyFiles.push({ 'url': 'http://-----/Content/File/DebitDetails.xlsx', 'filename': 'DebitDetails.xlsx' });
}
if (val == "AddressAssociated") {
MyFiles.push({ 'url': 'http://-----/Content/File/AddressAssociatedCompanies.xlsx', 'filename': 'AddressAssociatedCompanies.xlsx' });
}
if (val == "DebitDetailAssociated") {
MyFiles.push({ 'url': 'http://-----/Content/File/DebitDetailsAssociatedCompanies.xlsx', 'filename': 'DebitDetailsAssociatedCompanies.xlsx' });
}
});
var options = {
files: MyFiles,
// Success is called once all files have been successfully added to the user's
// Dropbox, although they may not have synced to the user's devices yet.
success: function () {
// Indicate to the user that the files have been saved.
alert("Success! Files saved to your Dropbox.");
DeleteFiles(selected);
},
// Progress is called periodically to update the application on the progress
// of the user's downloads. The value passed to this callback is a float
// between 0 and 1. The progress callback is guaranteed to be called at least
// once with the value 1.
progress: function (progress) { },
// Cancel is called if the user presses the Cancel button or closes the Saver.
cancel: function () { },
// Error is called in the event of an unexpected response from the server
// hosting the files, such as not being able to find a file. This callback is
// also called if there is an error on Dropbox or if the user is over quota.
error: function (errorMessage) { }
};
Dropbox.save(options);
}
function DeleteFiles(selected)
{
var postData = { values: selected };
var url = '#Url.Action("DeleteEXCELFiles", "Home")';
$.ajax({
type: "POST",
url: url,
data: postData,
success: function (result) {
if (result == "Success") {
}
}, dataType: "json",
traditional: true
});
}
</script>
Above code runs successfuly on my localhost
But when i upload it to server then I am having the following Error, i cant understand it
POST http://------/Home/ExportExcelFilesToDropBox 500 (Internal Server Error)
i.support.ajax.i.ajaxTransport.send # jquery?v=JzhfglzUfmVF2qo-weTo-kvXJ9AJvIRBLmu11PgpbVY1:1
i.extend.ajax # jquery?v=JzhfglzUfmVF2qo-weTo-kvXJ9AJvIRBLmu11PgpbVY1:1
Test # Dashboard:216
onclick # Dashboard:192
jquery?v=JzhfglzUfmVF2qo-weTo-kvXJ9AJvIRBLmu11PgpbVY1:1
XHR finished loading: POST "http://------//Home/ExportExcelFilesToDropBox".
i.support.ajax.i.ajaxTransport.send # jquery?v=JzhfglzUfmVF2qo-weTo-kvXJ9AJvIRBLmu11PgpbVY1:1
i.extend.ajax # jquery?v=JzhfglzUfmVF2qo-weTo-kvXJ9AJvIRBLmu11PgpbVY1:1
Test # Dashboard:216
onclick # Dashboard:192
A button click triggers an ajax request. When the user clicks the button a second time while the first request is still loading, i want to override the first request's success function with another one.
Basically I want to do this:
var ajaxRequest = null;
jQuery('#mybutton').click(function () {
if (ajaxRequest) {
ajaxRequest.success = function () {
};
}
ajaxRequest = jQuery.ajax({
url: '...',
success: function () {
console.debug('do something');
}
});
});
But the initial success handler is been called.
How to achieve an override?
You can try the following hack, I have tested it with asynch setTimeout (instead of asynch jQuery.ajax) and it works -
var mySuccessHander = function() {
console.debug('Initial function');
}
var test = jQuery.ajax({
url: '...',
success: function() {
mySuccessHander();
}
});
And when the button is clicked for the second time, execute following -
mySuccessHander = function() {
console.debug('Overridden function');
}
Nice question , this will work..
var isRequestDone = true;
jQuery('#mybutton').click(function () {
var requestParams = {
url: '....',
beforeSend: function () {
isRequestDone = false;
},
success: function () {
isRequestDone = true;
console.debug('do something');
},
error: function () {
isRequestDone = true;
}
}
if (!isRequestDone) {
requestParams.success = function () {
console.log('please wait for a while!');
};
}
jQuery.ajax(requestParams);
});
beforeSend will fire just before the request will go to server , so when request in on the server isRequestDone will be false and hence will change success handler . on success callback from the first request it will again back to original.
You can set the ajax arguments to a variable first so you can modify it later on.
var clicks = 0,
ajaxArgs = {
url: '...',
success: function () {
console.debug('do something');
}
};
$('#myButton').click(function() {
++clicks;
if (clicks > 1) {
// set the success function if clicked more than once
ajaxArgs.success = function () {
console.debug('Success function ' + clicks);
}
}
$.ajax(ajaxArgs);
});
If you want to modify the success function only when ajax is still loading you can do this:
var loading = false,
ajaxArgs = {
url: '...',
success: function () {
console.debug('do something');
}, complete: function () {
loading = false;
}
};
$('#myButton').click(function() {
if (loading) {
// set the success function if ajax is still loading
ajaxArgs.success = function () {
console.debug('Another Success function ');
}
} else {
loading = true;
$.ajax(ajaxArgs);
}
});
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. :)