I am running an AJAX request when the user types in an input field and then displaying the result on the page. When the user presses the backspace to delete all of what they've inputted, I use .empty to remove the result from the page.
However, if you press the backspaces really quickly, the result is removed from the page, but then because the last AJAX query hasn't last executed, the result from that query appears!!!
I have looked at Abort Ajax requests using jQuery but that didn't help, and have tried adding return: false; after $("#results").empty(); to no avail.
If there are any remaining AJAX calls when if(this.value.length < 1) { is true, I would like to abort them all inside that function.
$("input#enter").keyup(function() {
if(this.value.length < 1) {
$("#display").empty();
}else{
$.ajax({
type: "POST",
url: "getdata.php",
data: "title=" + this.value,
success: function(data) {
$("#display").empty();
$("#display").html(data);
}
});
}
});
You can use $.active to check if $.ajax() call is active before calling next $.ajax()
$("input#enter").keyup(function() {
if(this.value.length < 1) {
$("#display").empty();
}else{
if (!$.active) {
$.ajax({
type: "POST",
url: "getdata.php",
data: "title=" + this.value,
success: function(data) {
$("#display").empty();
$("#display").html(data);
}
});
}
}
});
You can also include attaching .ajaxComplete() to document to call next $.ajax() call when current call completes
function request(value) {
return $.ajax({
type: "POST",
url: "getdata.php",
data: "title=" + value,
success: function(data) {
$("#display").empty();
$("#display").html(data);
}
});
}
$("input#enter").keyup(function() {
if(this.value.length < 1) {
$("#display").empty();
}else{
if (!$.active) {
request(this.value)
} else {
$(document).one("ajaxComplete", function() {
request(this.value)
})
}
}
});
One approach to abort requests is to use XMLHttpRequest(), push requests to an array, then call .abort() on each element of the array
function request(data) {
let fd = new FormData();
fd.append("html", data);
fd.append("delay", Math.floor(Math.random() * 10));
let xhr = new XMLHttpRequest();
xhr.open("POST", "/echo/html/", true);
xhr.onload = function() {
console.log(xhr.responseText);
}
xhr.onabort = function() {
console.log("request " + requests.indexOf(xhr) + " aborted")
}
xhr.send(fd);
return xhr
}
function abortAllRequests() {
requests.forEach(function(xhr, index) {
xhr.abort()
})
}
var requests = [];
requests.push(request(123), request(456));
abortAllRequests();
jsfiddle https://jsfiddle.net/onguym5y/
You talk about aborting ajax requests. It would be sufficient to wait until the request returns and then simply do nothing. Yes, if you were doing a lot of large requests it might improve performance if you cancelled them. But that means using jqXhr objects, and personally I prefer to stick to jQuery where possible.
You could have a variable telling you how up-to-date the #display is. It would store the time of sending of the last ajax request that was used to update it. If you get a response from an earlier request, ignore it.
var lastUpdateTime = 0;
$("input#enter").keyup(function() {
var now = new Date().getTime();
if(this.value.length < 1) {
$("#display").empty();
lastUpdateTime = now;
}else{
$.ajax({
type: "POST",
url: "getdata.php",
data: "title=" + this.value,
success: function(data) {
if (now < lastUpdateTime) {
return;
}
$("#display").empty();
$("#display").html(data);
lastUpdateTime = now;
}
});
}
});
Related
On my website I have a normal contact form in which you can put in your name, email and a message.
For this form I have script.js, which proofs if the user input is correct and complete. If everything is alright, an AJAX call should point to form-mail.php, in which I send the request from the user to the owner.
script.js and form-mail.php work, but I don´t know the mistake in the AJAX call?
if (sum == 0) {
document.getElementById("name").style.borderColor = "green";
document.getElementById("email").style.borderColor = "green";
document.getElementById("nachricht").style.borderColor = "green";
$.ajax({
type: "POST",
url: "mailform/form-mail.php",
data: $("#myForm").serialize(),
beforeSend: function() {$("#myForm").css({"opacity": "0.2"})}
}).done(function(msg) {
$("#emailform").fadeOut(1000);
setTimeout(function () {
$("#myForm").append('<p id=\"adder-content\" style=\"display:block;width:100%;margin:0 auto;padding-top: 3em;text-align:center;color:green\"><span>' + msg + '</span></p>').css({"opacity": "1"});}, 1000);
});
e.preventDefault();
window.location.href = "http://www.just.a.test";
}
I had this code in two other projects and it worked, but since yesterday there´s a problem with it.
I think the problem is with
window.location.href = "http://www.just.a.test";
before the completion of the ajax call it redirects. Remove it or place it in the done section of the ajax call.
This should work
if (sum == 0) {
document.getElementById("name").style.borderColor = "green";
document.getElementById("email").style.borderColor = "green";
document.getElementById("nachricht").style.borderColor = "green";
$.ajax({
type: "POST",
url: "mailform/form-mail.php",
data: $("#myForm").serialize(),
beforeSend: function() {$("#myForm").css({"opacity": "0.2"})}
})
.done(function(msg) {
$("#emailform").fadeOut(1000);
setTimeout(function () {
$("#myForm").append('<p id=\"adder-content\" style=\"display:block;width:100%;margin:0 auto;padding-top: 3em;text-align:center;color:green\"><span>' + msg + '</span></p>').css({"opacity": "1"});
window.location.href = "http://www.just.a.test";
}, 1000);
});
e.preventDefault();
// window.location.href = "http://www.just.a.test";
};
Try this
$.ajax({
url: 'mailform/form-mail.php',
type: 'POST',
data: {data:data},
before:function(){
$("#myForm").css({"opacity": "0.2"});
}
success:function(response){
console.log(response);
}
});
I am saving data on a save button click that calls ajax and passing json data to a controller method but when we save it loading starts and suddenly stop though the data is not saved.
It is not working I have tried it in all way but not working please help me on this.
<button type="button" id="saveDeleg" class="btn_reg_back btnmainsize btnautowidth btngrad btnrds btnbdr btnsavesize " aria-hidden="true" data-icon="">#Resources.Resource.Save</button>
$('#saveDeleg').click(function() {
var response = Validation();
if (!response) {
return false;
}
$("#overlay").show();
$('.loading').show();
if ($('#organName').val() == '') {
$('#validorganisation').show();
return false;
} else {
$('#validorganisation').hide();
}
//Contact name
var SubDelegation = $('#subdelegation').is(':checked');
var CopyNotification = $('#copynotification').is(':checked');
var ArrangementId = $("#ArrangementId").val();
var paramList = {
ArrangementId: ArrangementId,
ArrangementName: $('#arrangName').val(),
OrganisationName: $('#organName').val(),
OrganisationId: $('#OrganisationId').val(),
ContactName: $('#contactName').val(),
ContactId: $('#ContactId').val(),
SubDelegation: $('#subdelegation').is(':checked'),
CopyNotification: $('#copynotification').is(':checked'),
ContactType: $('#ContactType').val(),
SelectedTypeName: $("input[name$=SelectedType]:checked").val()
};
setTimeout(function() {
$.ajax({
async: false,
type: "POST",
url: '#Url.Action("SaveDelegation", "Structures")',
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(paramList),
processdata: true,
success: function(result) {
//stopAnimation()
paramList = null;
if (result == 0) {
window.location.href = '../Structures/MyDelegationArrangement';
} else if (result == 1) {
window.location.href = '../Structures/CreateDelegation';
} else if (result == 2) {
window.location.href = '../Home/Error';
} else if (result == 3) {
window.location.href = '../Account/Login';
} else {
//validation message
alert('Error');
}
},
error: function() {},
complete: function() {
$("#overlay").hide();
$('.loading').hide();
}
});
}, 500);
});
The problem with the loading indicator is because you used async: false which locks up the UI. Remove that setting.
Also note that if the data is not being saved I would assume that your AJAX call is returning an error. If so, check the console to see the response code. It may also be worth putting some logic in the error callback function to give you some information on whats happened, as well as inform your users about what to do next.
I'm having trouble with my functions running before Ajax requests (the first to a local JSON, the second to an online resource) have finished.
In this example I want countTheMovies to run at the end after my application has got all the information it needs and populated the divs. Instead it's running straight away.
I tried to delay it using an if condition, but with no joy. I've also tried with callbacks, but think I must be getting those wrong (I'm assuming callbacks are the answer). I'm aware of timed delays, but because in the actual project I'm sourcing 250+ movies (and because a timed delay seems like cheating) I thought I'd ask here instead.
Can anyone recommend JavaScript or jQuery code to fix this problem?
$(function(){
getMovieList();
});
function getMovieList() {
$.ajax({
url: "movielist.json",
type: "GET",
dataType: "JSON",
success: function(data) {
for (var i = 0; i < data.length; i++) {
var title = data[i].title.toLowerCase().split(" ").join("+");
var year = data[i].year;
i === data.length - 1
? getMovieInfo(title, year, true)
: getMovieInfo(title, year, false);
}
}
});
}
function getMovieInfo(title, year, isLast) {
$.ajax({
url: "https://www.omdbapi.com/?t=" + title + "&y=" + year + "&plot=short&r=json",
type: "GET",
crossDomain: true,
dataType: "JSON",
success: function(val) {
if (!val.Error) {
movie = title.replace(/[^a-z0-9\s]/gi, '');
$("#app").append(
// appending info to divs
);
}
}
});
if (isLast) countTheMovies();
};
function countTheMovies() {
$("#app").append("There are " + $(".movie").length + " movies.");
}
A plunker of my failings: https://plnkr.co/edit/0mhAUtEsaOUWhkZMJqma?p=preview
You've almost got it!
The same way that you call getMovieInfo in the success callback of getMovieList, you should be calling countTheMovies in the success callback of getMovieInfo.
As Jacob said above, move the countTheMovies call inside the AJAX request.
$(function(){
getMovieList();
});
function getMovieList() {
$.ajax({
url: "movielist.json",
type: "GET",
dataType: "JSON",
success: function(data) {
for (var i = 0; i < data.length; i++) {
var title = data[i].title.toLowerCase().split(" ").join("+");
var year = data[i].year;
i === data.length - 1
? getMovieInfo(title, year, true)
: getMovieInfo(title, year, false);
}
}
});
}
function getMovieInfo(title, year, isLast) {
$.ajax({
url: "https://www.omdbapi.com/?t=" + title + "&y=" + year + "&plot=short&r=json",
type: "GET",
crossDomain: true,
dataType: "JSON",
success: function(val) {
if (!val.Error) {
movie = title.replace(/[^a-z0-9\s]/gi, '');
$("#app").append(
// appending info to divs
);
if (isLast) countTheMovies();
}
}
});
};
function countTheMovies() {
$("#app").append("There are " + $(".movie").length + " movies.");
}
Just put your countTheMovies() logic inside of the success callback of the AJAX request in getMovieInfo if you want it to run on success.
You can call your countTheMovies() function from inside the success field of your Ajax call. This way it will make the function call when you intend it to.
Try out this
$(function(){
getMovieList();
});
function getMovieList() {
$.when( $.ajax({
url: "movielist.json",
type: "GET",
dataType: "JSON",
success: function(data) {
for (var i = 0; i < data.length; i++) {
var title = data[i].title.toLowerCase().split(" ").join("+");
var year = data[i].year;
i === data.length - 1
? getMovieInfo(title, year, true)
: getMovieInfo(title, year, false);
}
}
}) ).then(function( data, textStatus, jqXHR ) {
countTheMovies();
});
}
function getMovieInfo(title, year, isLast) {
$.ajax({
url: "https://www.omdbapi.com/?t=" + title + "&y=" + year + "&plot=short&r=json",
type: "GET",
crossDomain: true,
dataType: "JSON",
success: function(val) {
if (!val.Error) {
movie = title.replace(/[^a-z0-9\s]/gi, '');
$("#app").append(
// appending info to divs
);
}
}
});
};
function countTheMovies() {
$("#app").append("There are " + $(".movie").length + " movies.");
}
I would like to iterate through a certain amount of pages, and populate them with content using ajax calls. The problem is, when I put the ajax calls inside the iteration function it has problems with the synchronous nature of javascript. The iteration has already continued before the ajax call is completed. So I made a workaround where I made the ajax call in a setTimeout, which works fine. But I don't really like this method, and was wondering if there is an alternative (better) solution. (I know that jQuery provides a async: true option, however that did not work)
function populatePages(i) {
pageId = PageIds[i];
containerId = pageIdContainer[i];
$j.ajax({
type: 'GET',
dataType: 'html',
url: url,
data: { pageid: pageId, containerid: containerId },
success: function(data) {
//populate the DIV
}
});
}
i = 0;
x = 50;
$j.each(pagesIds, function(){
setTimeout("populatePages("+i+")", x);
x = x + 50;
i++;
});
Try this (not tested)
function populatePages(i) {
console.log('populatePages', i)
pageId = PageIds[i];
return $.ajax({
type: 'GET',
dataType: 'html',
url: '/echo/html',
data: { pageid: pageId},
success: function(data) {
}
});
}
function messy(index){
console.log('messy', index)
if(index >= PageIds.length){
return;
}
populatePages(index).always(function(){
console.log('complete', index)
setTimeout(function(){
messy(index + 1)
});//to prevent possible stackoverflow
})
}
PoC: Fiddle
I am making an ajax call to send out a couple of emails when the user clicks a button. I am trying to update a "Please wait..." div before and after the call with the status, as well as report any errors. The problem... is that the div doesn't actually update until the ajax call is complete.
If I comment out the ajax call the status update works fine, but fails if the ajax call takes place. My Windows programming experience tells me the div needs to be refreshed, but I'm not sure how this is done, or if this is the right method.
For example:
$("#msgEmail").show();
$("#msgEmail").html("Preparing to send");
$.ajax({ blah blah blah...
Any pointers in the right direction will be much appreciated!
On nnnnnn's suggestion I started testing on other browsers. The problem occurs on Chrome and Safari, but works as expected on Firefox and SeaMonkey. It sure looks like he's right about this. Now I just need to figure out to implement setTimeout() in this scenario.
Update: Code:
.click(function() {
$('#myTable :checkbox:checked').each(function() {
sId = $(this).attr('cid');
sName = $(this).attr('cname');
ret = true;
$("#msgImage").slideDown();
sUpdate = 'Sending alerts to class: '+ sName;
$("#msgEmail").slideDown();
$("#msgEmail").html(sUpdate);
sSubject = "Notificatiom";
sMessage = $('#message').val();
sData= "cid="+sId+'&sname='+sName+'&subject='+sSubject+'&message='+encodeURIComponent(sMessage);
$.ajax({
url: 'dostuff.php',
data: sData,
dataType: 'text',
type: 'POST',
async: false,
success: function (msg)
{
if(msg >= '1')
{
ret = true;
}
}
});
if(ret)
$("#msgEmail").html('Finished sending alerts');
$("#msgImage").slideUp();
ret = false;
return false;
})
Place your ajax call in the callback for 'slideDown'. Set the message before calling 'slideDown'. This will ensure your message is updated before the ajax call is sent.'
sUpdate = 'Sending alerts to class: ' + sName;
$("#msgEmail").html(sUpdate);
$("#msgEmail").slideDown(function() {
sSubject = "Notificatiom";
sMessage = $('#message').val();
sData = "cid=" + sId + '&sname=' + sName + '&subject=' + sSubject + '&message=' + encodeURIComponent(sMessage);
$.ajax({
url: 'dostuff.php',
data: sData,
dataType: 'text',
type: 'POST',
async: false,
success: function(msg) {
if (msg >= '1') {
ret = true;
}
}
});
});
I ll get you an on hw this stuff is going to be
$(document).ready(function(){
$.ajax({
url :'YOur url',
.....
.....
ajaxSend :function(){
$('#yourdiv').html('please wait...');
}
success:function(msg){
if (msg >= '1') {
$('#yourdiv').html('validated');
}
}
});
}):