unbind event handlers while ajax in progress - javascript

I have a text field with keypress event handler jsfiddle. And when I type something in this field and press "Enter" 2 times, 2 requests will be send. I want to turn off all events, while ajax request in progress. One option is to call .off() function before ajax call, and then bind event handler again. Any other options?

use the callback handlers from your ajax call and a boolean used as flag. By setting the ajaxLoading boolean to false in the "always" callback, you can be sure that other, future requests can be made independent from whether the current ajax call throws an error or not.
var ajaxLoading = false;
if(!ajaxloading){
ajaxloading=true;
$.ajax({
url: 'your url',
type: 'GET',
dataType: 'JSON'
})
.done(function(data) {
console.log("success");
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
ajaxloading=false;
});
}

I use 2 boolean flags, like:
var is_requesting = false, should_request = false;
function onkeydown() {
if (is_requesting) {
should_request = true;
return;
}
is_requesting = true;
$.ajax({}, function () {
is_requesting = false;
if (should_request) {
onkeydown();
}
});
}

Is there a good reason for you not to use the jQuery .off() function?
If so then you could simply disable the control prior to making the ajax request and re-enable it once the request is complete. This would also stop the user from thinking he/she could change the result by changing the text value during the request.
//Disable the input
$('#myresult').prop('disabled', true);
$('#myresult').append('<br>'+$(this).val());
$.ajax({
type: "POST",
beforeSend: function() {},
complete: function() {
//Re-Enable the input
$('#myresult').prop('disabled', false);
},
url: "/echo/json/",
data: { delay : 3 },
success: function(){},
error: function() {},
dataType: 'json'
});

Related

Ajax is not aborting when button was clicked

How can I abort an ajax request when a button was clicked? I tried some answers I found here but it didn't work on me.
<button type="button" id="toStop">Stop</button>
When the stop button was clicked ajax isn't aborting.
function() {
var myajaxreq = $.ajax({
url: myurlhere,
type: 'GET',
async: true,
success: function(result) {
}
beforeSend: function () {
if(document.getElementById('toStop').clicked == true) {
myajaxreq.abort();
}
}
});
}
You need a separate click listener that will abort ajax request. Using beforeSend will not always work.
$('#toStop').click(function(e) {
e.preventDefault();
// abort here
// make sure myajaxreq is accessible in this function
if (myajaxreq) myajaxreq.abort();
});

jQuery Click Handler with Called Ajax Sub-Method has a strange delay on $(this).prop('disabled', true) [duplicate]

This question already has answers here:
updated UI not showing before sync ajax call
(2 answers)
Closed 3 years ago.
I have a strange situation where the following Click-Handler (via one() to prevent double-clicks) has a called Ajax method from the inside. The first thing it's supposed to do is to disable my button.
Normally, if I don't have any Ajax inside and just have a simple click handler, this works and disables the button immediately:
$('#button').one('click', function (event) {
$(this).prop('disabled', true);
});
But if I have the following, with a called sub-method which involves Ajax, I notice that the 1st statement (Disable Button) does not occur until the sub-method is complete. But why? The button should get disabled immeditely as the first statement, regardless of how long the Ajax takes to complete.
$('#submitButton').one('click', function (event) {
$(this).prop('disabled', true); // Doesn't get disabled until AFTER submitSurvey()
submitSurvey(); // Call some method that does Ajax
});
function submitSurvey() {
$.ajax({
url: 'surveyProcess',
type: 'post',
processData: false,
contentType: false,
data: formData,
async: false, /* Note async = false, so nothing asynchronous here either */
success: function() {
//...
}
What could be going on here? I just need to disable the button immediately, without any delay.
You can use beforeSend() event for the same use
$('#submitButton').on('click', function (event) {
$.ajax({
url: 'surveyProcess',
type: 'post',
processData: false,
contentType: false,
data: formData,
async: false, /* Note async = false, so nothing asynchronous here either */
beforeSend: function(){
$(this).prop('disabled', true);
},
success: function() {
//...
}
});
});

How to avoid ajax async when using jQuery events

I have an input field with ajax call (filling some other input fields) on blur and buttons with click events (some of the click events set input fields to an empty string).
For example,
$("#input_field1").on('blur', function () {
$.ajax({
//async:false,
method: "GET",
url: "my_ajax.php",
cache: false,
dataType: "json",
data: { data1: $("#input_field1").val()},
success: function(result){
$("#some_other_input").val(result.data2);
}
})
});
$("#button1").on('click', function () {
$("#input_field1").attr("readonly", true);
var form = $("#my_form");
form.validate().resetForm();
form[0].reset();//form contains #some_other_input
});
When that input field is focused and then user clicks on any button, blur event is triggered and of course, appropriate click event after it.
If I don't use async:false, ajax will fill those input fields after click event is processed and other inputs will be filled instead of being empty.
Reading about how async:false should be avoided always, I need a way for my click events to wait until ajax is done, if there is an ajax call at that moment.
You need a concurrency check for your cases. On your blur action; check and set a value to prevent reentering the other calls.
Also during an ajax request, you need to prevent clicking the buttons.
One more thing, what if just after bluring your input field, user re-focuses and re-focusouts your input? In this case, your action will be triggered twice.
As a result, you need to handle concurrency. There are also some javascript libraries to handle concurrency, you can either use them or handle by your own.
Anyway to handle your case, here is a sample code:
let hasCall = false;
$("#input_field1").on('blur', function () {
if(hasCall){
return; //there is an active call...
}else{
hasCall = true;
$("#button1").prop('disabled', true);//prevent clicking on button
}
$.ajax({
//async:false,
method: "GET",
url: "my_ajax.php",
cache: false,
dataType: "json",
data: { data1: $("#input_field1").val()},
success: function(result){
$("#some_other_input").val(result.data2);
}
}).always(()=>{
//reset the state:
hasCall=false;
$("#button1").prop('disabled', false);
});
});
$("#button1").on('click', function () {
$("#input_field1").attr("readonly", true);
var form = $("#my_form");
form.validate().resetForm();
form[0].reset();//form contains #some_other_input
});

AJAX async:true breaks site on mobile browsers

I am using this function to return search results via AJAX. However, it kills mobile browsers on search. It works if I set it to 'async:false' but this means that I can't have a loading icon.
I cant find anything online to indicate why this would not be working on mobile, when it works fine on desktop.
Any ideas?
(function($) {
$(document).ready(function() {
$("#filter").on('keyup input', function() {
delay(function() {
var input = $('#filter');
var query = input.val();
var content = $('#content')
$.ajax({
type: 'post',
url: myajax.ajaxurl,
async: true,
data: {
action: 'load_search_results',
query: query
},
beforeSend: function() {
input.prop('disabled', true);
content.addClass('loading');
},
success: function(response) {
input.prop('disabled', false);
content.removeClass('loading');
content.html(response);
myPluginsInit();
}
});
return false;
}, 700);
});
});
})(jQuery);
I was able to solve this problem by adding a separate 'loader' div with an ID of loader to my page, and add the loading class to this instead. The code now looks like this:
(function($) {
$(document).ready(function() {
$("#filter").on('keyup input', function(){
delay(function(){
var input = $('#filter');
var query = input.val();
var content = $('#content')
$.ajax({
type : 'post',
url : myajax.ajaxurl,
async: true,
data : {
action : 'load_search_results',
query : query
},
beforeSend: function() {
input.prop('disabled', true);
$('#loader').addClass('loading');
},
success : function( response ) {
input.prop('disabled', false);
$('#loader').removeClass('loading');
content.html( response );
myPluginsInit();
}
});
return false;
}, 700 );
});
});
})( jQuery );
You're problem is still in your keyup input handler. I'm not sure where the function delay is declared (I'm assuming it's some wrapper around setTimeout). However it doesn't really matter.
The issue is that the handler fires for every input and keyup event. The "delay" is inside that. All the "delay" is doing is "waiting" before it makes the ajax call but an ajax call is still being created for every keyup and input event.
This means that a lot of ajax calls are being created and on a mobile platform that's a problem. I'm not exactly certain when (or how often) you need to make the call to the server but to see what I'm talking about just add the line I've included below:
(function($) {
$(document).ready(function() {
$("#filter").on('keyup input', function() {
console.log('handling keyup or input') // add this line and watch them stack up
delay(function() {
var input = $('#filter');
var query = input.val();
var content = $('#content')
$.ajax({
type: 'post',
url: myajax.ajaxurl,
async: true,
data: {
action: 'load_search_results',
query: query
},
beforeSend: function() {
input.prop('disabled', true);
content.addClass('loading');
},
success: function(response) {
input.prop('disabled', false);
content.removeClass('loading');
content.html(response);
myPluginsInit();
}
});
return false;
}, 700);
});
});
})(jQuery);

jQuery Allow only one click before .ajax()

I am trying to allow a button to be clicked only once and then some data be submitted via ajax. The problem I am facing is that a user can click 50x and the data is POST submitted each time ?
jQuery("#id").unbind('click');
jQuery.ajax({
type: "POST",
url: ajax_url,
data: ajax_data,
cache: false,
success: function (html) {
location.reload(true);
}
});
How can I ensure that if a user clicks #ID 100x - that the data is only submitted once ? And then #ID is re-enabled ?
You could use the .one() function in jQuery.
jQuery("#id").one('click', function()
{
jQuery.ajax({
type: "POST",
url: ajax_url,
data: ajax_data,
cache: false,
success: function (html) {
location.reload(true);
}
});
});
Bear in mind this will completely remove the click event, even if you have an error with your ajax, you still won't able to click it again.
just disable the button
$("#id").attr("disabled", "disabled")
and then in the success function enable it
$("#id").removeAttr("disabled")
Easiest way would be to use a flag which gets reset when the success is fired:
if(clicked == False){
clicked = True;
jQuery("#id").unbind('click');
jQuery.ajax({
type: "POST",
url: ajax_url,
data: ajax_data,
cache: false,
success: function (html) {
location.reload(true);
clicked = False;
},
error: function () {
alert("Error happened");
clicked = False;
}
});
}
You can disable to control, or use one of the many modal libraries to show the spinning wheel
see this Jquery modal dialog question on SO
You could disable the button on click event and enable it back when ajax request is completed.
In your click event you could disable the button and then re-enable the button in the success function of the ajax event.
Another option would be to set a parameter on the element that is being clicked to indicate the button was clicked and then check to see if it is set if it is don't send the ajax request if not then do send it. Once the ajax is done you can unset the parameter again to allow it to be run.
try this:
$(document).ajaxStart({ function() {
$('#submit_button').click(function(){
return false;
});
});
where: #submit_button is id of the element U want to disable
that code will disable clicking on the submit button

Categories