I have a jquery function that takes the data from the 3rd column of a table - runs a function on it - and then replaces the field with the result.
Here's my code:
function getData() {
$('#tab1_response').html("<img src='images/ajax-loader.gif' border=0> Please wait...").show();
$('#myTable tr').each(function(index){
var col1 = $(this).children('td.col1').text();
$(this).children('td.col3').load('doStuff.php?url='+col1);
});
$("#myTable").trigger("update");
$('#tab1_response').fadeOut(2000);
}
For some reason the last two lines:
$("#myTable").trigger("update");
$('#tab1_response').fadeOut(2000);
Don't wait for the .each(function... to complete before running...
Instead the "Please wait..." loader开发者_C百科 doesn't appear and my table doesn't update meaning the new column isn't sortable (I'm using tablesorter for jquery found here - http://tablesorter.com/docs/).
The function does otherwise work and I can see my 3rd column updating with new data.
Is there a simple fix for this???
I hope I've provided enough details but please let me know if you need more information :)
The problem is not the call to $.each()
it's the call to $.load()
. This is an Ajax request, and by it's very nature is asynchronous - it returns before the round trip to the server completes.
I would also be slightly worried by the fact that you're doing an Ajax request per row in the table: how many rows are there?
.load()
is asynchronous, meaning that your script won't wait for it to complete before continuing.
I'd suggest keeping track of how many requests you have going, and executing your code when they're all done:
$('#tab1_response').html("<img src='images/ajax-loader.gif' border=0> Please wait...").show();
var requests = 0;
var requestDone = function() {
requests--;
if (requests == 0) {
$("#myTable").trigger("update");
$('#tab1_response').fadeOut(2000);
}
}
};
$('#myTable tr').each(function(index){
var col1 = $(this).children('td.col1').text();
requests++;
$(this).children('td.col3').load('doStuff.php?url='+col1, requestDone);
});
There is a more elegant solution. Just invoke the sudo element :last-child and call a function after the last element in the each cycle has been loaded.
Something like this:
$('table tr').each(function (){
dosomething();
if ($(this).is(":last-child"))
{
$(this).load(function() {
dosomethingelse();
});
}
You have to use the callback in .load()
, but only when you hit the last row. Rewrite your code like this.
function getData()
{
$('#tab1_response')
.html("<img src='images/ajax-loader.gif' border=0> Please wait...")
.show();
var rows = $('#myTable tr').length;
$('#myTable tr').each(function(index)
{
var tr = $(this),
col1 = tr.children('td.col1').text();
if ( (index+1) === rows) //last row, use callback to update table and fade img
{
tr.children('td.col3').load('doStuff.php?url=' + col1, function(){
$("#myTable").trigger("update");
$('#tab1_response').fadeOut(2000);
});
}
else //
{
tr.children('td.col3').load('doStuff.php?url=' + col1);
}
});
}
Warning I gave you an answer to your problem, but I'm with Dean Harding on the warning, doing one request per row is not a good idea. You should find a way to improve that (hint, use JSON ;)
I think i understand. you can chain the last two.
$('#myTable tr').each(...).trigger("update").fadeOut(2000);
The above is untested but won't be far off.
Look up jQuery chaining.
You could also add "last" id
to the last tr
and do the hiding for the last tr
function getData() {
$('#tab1_response').html("<img src='images/ajax-loader.gif'
border=0> Please wait...").show();
$('#myTable tr:last-child').attr('id', '#last');
$('#myTable tr').each(function(index){
var col1 = $(this).children('td.col1').text();
if ($(this).is('#last')) {
$(this).children('td.col3').load('doStuff.php?url='+col1, function () {
$("#myTable").trigger("update");
$('#tab1_response').fadeOut(2000);
});
}
});
}
(not tested)
精彩评论