Detect AJAX Request - ajax

On my website I have mouse over and mouse out events set up on an HTML table. These events trigger ajax requests, and perform certain actions etc. However, i want to be able to not trigger a second request if one is already running. So, is there away to detect these requests, and therefore avoid a second. Incidentally Im using the jQuery $.ajax()
if it helps at all.
Thanks in advance
Chris

I'd try something simple like:
var requestMade = false;
function yourAjaxFunction(){
if(!requestMade)
{
requestmade = true;
$.ajax({
url: "page",
success: function(){
requestMade = false;
}
error: function(){
requestMade = false;
}
});
}
}
You can use the success: and error: settings to change the variable back to false.
I have never used the error so you may have to include some other things in it, but this is the general idea.

For this suppose I'd use ajaxStart() and ajaxStop() which would change specific variable ajaxRunning which could be checked before sending the request (maybe in ajaxStart() directly?)

Set global or local static variable to true when first ajax is about to trigger, than add if before triggering the second one ;) Than after one request is finished, set this variable to false

Related

Using Form Validation submitHandler to send 2 AJAX requests?

I've got a pretty strong understanding of php, html & css but i've only just started to dive into javascript & jQuery.
The problem i'm facing is that I have a form on a page that I want first to validate, then when it passes validation to submit 2 ajax requests; the first to insert data into a table in my database and the second to run a query on another table and return the result.
I've got the latter working just fine using the submitHandler method to send the ajax request and update a div on my page with it's result. When I added a second ajax call after or before this one it seems to break...
My question is should there be a problem with having 2 ajax calls in the submitHandler, like below, and if so what would be the correct way to go about this, or even a better way?
$("#contactform").validate({
rules: ...
submitHandler: function() {
// First to insert the contact details using input#firstname etc.
var firstname = $("#firstname").value();
var lastname = $("#lastname").value();
var contactString = 'firstname='+ firstname + '&lastname=' + lastname;
$.ajax({
type: "POST",
url: "insertcontact.php",
data: quoteString,
success: function(server_response){
$('#yourquote').html(server_response).show();
}
});
// Second use width & height submitted from previous page for processquote.php
var width = <?php echo json_encode($cleanpost['width']); ?>;
var height = <?php echo json_encode($cleanpost['height']); ?>;
var quoteString = 'width='+ width + '&height=' + height;
$.ajax({
type: "POST",
url: "processquote.php",
data: quoteString,
success: function(server_response){
$('#yourquote').html(server_response).show();
}
});
}
});
I'm using the 'jquery.validate.js' validation plugin. Again my goal is such that once someone has entered valid details on my form, using Ajax their contact data is inserted into the database then the database is queried using fields submitted on the previous page to retrieve a numerical result to display on the page, without a refresh.
Any pointers you could give me would be much appreciated!
Rob
EDIT: Learning Javascript & Jquery simultaneously isn't such a good idea it seems, i've confused: this.value = ''; with $(this).val(''); as shown in the first 2 variable declarations, this is what was causing problems! Thanks for your useful help anyway guys, will upboat for your assistance.
In your first .ajax() call, you are trying to pass it a value in the data: parameter that you have not created yet. I believe you are wanting to send it the contactString instead.
Unless your two queries depend on each other being done sequentially then you should be able to execute them both asynchronously (essentially at the same moment). If you want the second AJAX call to happen after the first one, you could always pass all of your data parameters to insertcontact.php and once the insertion is done, execute processquote.php with the values you already passed through.
Lastly, I wonder if you are meaning to do this, but both of your AJAX calls overwrite whatever is in the #yourquote DOM element and show it. You might want to provide a separate element to put the response in for each of your two requests. Perhaps #yourquoteinserted and #yourquoteprocessed?
Edit: BigRob, from your comment it sounds as if you want to make synchronous AJAX queries, check out the async property of your .ajax() call. This is from the .ajax() documentation:
async Boolean
Default: true
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
(emphasis mine)
However, I could be wrong about this but you might actually be able to call one asynchronous AJAX method from within the success function of another. If it starts looking too intermingled for you, you might want to extract the inner call into a function. Rough approximation of what it might look like:
$.ajax({url, data:contactString,
success: function(server_response) {
extractedId = server_response; // you can return data many ways
$.ajax({url2, data:quoteString+"&extra="+extractedId,...
});
}
});
If you perform a synchronous call by setting async:false in the first AJAX call, then you could just store the result into an external (to the AJAX call) variable (or if that doesn't work store it in some DOM element temporarily). Then the javascript will pause execution and won't fire your second AJAX call until the first one has returned.
This is all hypothetical for now, though, and just based off of my understanding of how it should work.

Stop .ajax from double loading content

I have the following code that loads content when a user scrolls to the bottom of the page. The problem is that if one scrolls too fast it double loads the content. What ways can I change my code to prevent this?
$(window).scroll(function(){
if($(window).scrollTop() == $(document).height() - $(window).height()){
$('div#ajaxResults').show();
$.ajax({
url: "ajax/home.php?last_id=" + $(".postitem:last").attr("id"),
success: function(html){
if(html){
$("#messages").append(html);
$('#ajaxResults').hide();
}else{
$('#ajaxResults').html('<center>None.</center>');
}
}
});
}
});
I need for the solution to work multiple times. This script loads the next 5 messages, but there may be hundreds of messages that could be loaded. It is supposed to work in the same way that facebook or twitter loads updates.
SOLUTION:
$(window).scroll(function(){
if($(window).scrollTop() == $(document).height() - $(window).height()){
var lastid = $(".postitem:last").attr("id");
$('div#ajaxResults').show();
$.ajax({
url: "ajax/home.php?last_id=" + $(".postitem:last").attr("id"),
success: function(html){
if(html){
if(lastid == $(".postitem:last").attr("id")){
$("#messages").append(html);
$('#ajaxResults').hide();
}
}else{
$('#ajaxResults').html('<center>None.</center>');
}
}
});
}
});
Add a variable that checks the lastid before the ajax is loaded, then only append html if the variable == the document last id. This way if ajax has already loaded, the two will not be equal and the update won't be posted.
Try adding $(this).unbind('scroll'); inside the if block, assuming you do not want the ajax request to run more than once. Don't put it in the $.ajax success callback though, since it may fire more than 1 ajax request this way.
http://api.jquery.com/unbind/
Can you set a variable that stores the timestamp it was called and if it's within a few milli-seconds then doesn't call again? Kind of hack-ish but might do the trick.
Obviously this isn't really solving the problem as that seems to be with how the scroll event is being triggered.

Jquery .get() not working in Internet Explorer

I'm having a problem with, guess what, IE8. The following code, simplified for clarity, does not work at all:
alert('before get');
$.get(getActivityURL('ActionName',{
ts: new Date().getTime(), ...other params...}),
{cache:false;},
function (xml) {
alert("in get callback");
},'xml'); // End $.get()
alert('in after get');
The getActivityUrl() outputs a valid URL with request parameters.
This works correctly in FF and Chrome. However, in IE8, this doesn't even get into the $.get() callback. I get the "before" and "after" alerts, but not the "in" alert and indeed, nothing happens and the request is NOT sent. I don't really know what to think here.
The response headers are "Content-Type:application/xml; charset:iso-8859-1" as confirmed in FF.
EDIT: $.post() doesn't work, either.
IE is infamous for caching. So you need to make sure you are not getting a cached result.
You can disable caching globally by setting the cache property value to false in the ajaxStart method.
$.ajaxSetup({
cache: false
});
Or If you want to eliminate the cached result in a specific ajax call, Append a unique number to the end of the url. You may use the $.now() method to get a unique number
$.get("someurl.php?" + $.now() ,function(result) {
// do something with result
});
$.now() method return a number representing the current time.
I'm not sure if it is a problem but try to remove ";" in {cache:false}
IE doesn't like any additional stuff in {}, eg
{a:a,b:b,c:c,} will work in FF but not in IE
I think so there is Cache problem in IE.
So add Math.random(), one more parameter at the end like "&mathRandom="+Math.random();
Because IE will recognise same request as previous one so it will give data from cache instead of firing request.
$J.get(getActivityURL('ActionName'
// End $.get()
Is this correct? I mean $J... Are you using more than one JS framework or something?
have u tried:
$.ajax({
url: getActivityURL('ActionName',{ts: new Date().getTime(), ...other params...}),
data: data,
success: function (xml) {
alert("in get callback");
},
dataType: 'xml'
});
Just a guess
EDIT:
I found a interesting thread that might help you, check this out:
jQuery issue in Internet Explorer 8

Ajax.BeginForm switches from async to sync

I'm running into an issue with an async call to the server that only works one time, then it appears to become a synchronous call. Let me try to explain.
It's an MVC 2.0 site, using ASP.NET and Ajax. I'm using the Ajax.BeginForm helper, like so:
<% using (Ajax.BeginForm("Start", null,
new { virtualMachineId = xyz },
new AjaxOptions { UpdateTargetId = "VirtualMachineForm", OnBegin="OnStartingVm" }
)){
Then while the machine is starting I want to call back to the server and get an update every second. It works the first time correctly, then changes behavior. OnStartingVm looks something like this:
function OnStartingVm() {
$('#StartingDiv').css('visibility', 'visible');
$('#StartingDiv').show();
var vmId = xyz;
intervalId = setInterval(function () {
updateStartingStatus(vmId)
}, 1000);
}
function updateStartingStatus(vmId) {
/* This part always runs */
$.ajax({
url: "/member/vm/getstartingstatus/" + vmId,
dataType: 'json',
async: true,
success: function (data) {
alert('This part runs every second on the first time only');
if (data.status == "Running") {
$('#StartingDiv').text(data.percentComplete);
}
else {
$('#StartingDiv').css('visibility', 'hidden');
$('#StartingDiv').hide();
clearInterval(intervalId);
}
},
});
}
Within the updateStartingStatus function, the first part runs every second, every time. However, within the Ajax call, the success result works every second on the first time only. Then on the second time I click on the start button all of the requests queue up. After the starting has completed, about 20 seconds later, I get a bunch of alert windows back to back. So, I can tell that updateStartingStatus runs every second every time, but the ajax call appears to switch to become a sync call after the first time.
Refreshing the browser window doesn't help. I have to fully close it and open it again. The same occurs in IE and Chrome.
One more thing to note is that the updated div (VirtualMachineForm) contains most of the page, including the button being pressed. So it basically replaces the page from under itself. Not sure if that would cause any issues.
Additionally, if I debug in Visual Studio 2010, the call isn't made to the controller action when the issue occurs. So, it appears to be something client-side. I've ruled out any issues server-side.
I eventually figured it out. This post lead to the answer.
It was session state related and the browser locked the request until a previous one was completed. I didn't need to disable session state, but I had to avoid a session write from code.
That explains why a browser refresh didn't work and why I had to close and open the browser again.
Why don't you call clearInterval function?

Cakephp Ajax Button

I have a delete button. which on click it should visit a url like /delete/{id} and once the response from that url is true. i want to delete the comment box like in facebook.
I wont add any extra than Leo's comment, but I will explain with some code. Presume that you are using jQuery...
$(document).ready(function(){
$('tr a.delete').live('click', function(e){
e.preventDefault();
var link = $(this);
$.get($(this).attr('href'), null, function(response){
if(response == 'ok'){ //you should invent how to get 'ok' or other string identifying that the deletion is successful.
link.parents('tr').remove();
} else {
alert('There is a problem while deleting this element');
}
});
})
});
if you put this code on your project it will handle all links which had .delete class and are in a table row.
There are two things which you should do:
You need to pass some string in
order to detect if the operation is
successful or not. In my example I
would print "ok" on success
deletion.
If your table has pagination, it wont
rebuild the table, while it just
will remove the row from the table.
and if you have let's say 5 rows per
page and you delete all of them the
page will remain empty while there
will be other records in the table.
That's why instead of removing the
tr I would reload the whole page.
In that case the code for successful deletion will look like this:
if(response == 'ok'){
$('#content').load(window.location);
}
The script is not optimised, but it will give you the ideas how to achieve your ideas.
HTH
So write an onClick event handler in your view, a php delete method on the appropriate controller called by the event handler and a javascript action to perform when the ajax call returns success.

Resources