Jump to content

Updating multiple elements/for loop


shelluk

Recommended Posts

Hi

 

At risk of looking liking an idiot here I feel. Here goes though! I have the following code. Only the one with 'row10' changes though. Everything else sticks on 'Loading...'. Looking at the Apache logs I can see it is requesting each page (wait.php?q=0.. waiting.php?q=1... and so on up to 10).

 

index.php

<html>
   <head>
     <title>This is a ajax test page</title>
     <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
     <script language="Javascript" type="text/javascript">
        function ajax(id) {
           for(var i=0;i<=id;i++) {
           rowid = 'row'+i;
           var xmlhttp;
           if (window.ActiveXObject) {
              xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
           } else {
              xmlhttp = new XMLHttpRequest();
           }
           xmlhttp.onreadystatechange = function() {
              if (xmlhttp.readyState == 3) {
              }
              if (xmlhttp.readyState == 4) {
                 document.getElementById(rowid).innerHTML = xmlhttp.responseText;
              }
           }
           document.getElementById(rowid).innerHTML = 'Loading...';
           xmlhttp.open('GET', 'wait.php?q='+i, true);
           xmlhttp.send(null);
           }
        }
</script>
</head>

<?PHP
$x = '10';
echo '<body onload="ajax('.$x.')">';

for( $y=0; $y<=$x; $y++ ){
echo ' <div id="row'.$y.'">#'.$y.'#</div>'.PHP_EOL;
}
?>

</body>

</html>

 

wait.php

<?PHP
$q = $_GET['q'];
sleep($q);
echo 'That should have taken '.$q.' seconds.';
?>

 

Can any one point out my mistake please? :)

 

Thanks

Shell

Link to comment
https://forums.phpfreaks.com/topic/273199-updating-multiple-elementsfor-loop/
Share on other sites

I think it's because of the asyn nature of AJAX. The xmlhttp.onreadystatechange is only executed when the the ajax call is ready. It will probably be that the for loop by then, is in the next loop. Therefore only in the last loop the ajax call is fully executed.

 

You can try by calling the ajax function again in the part where the responseText is received, therefore when the ajax call is finished, try this:

 

function ajax(y) {					  

var i = y;

rowid = 'row'+i;  
var xmlhttp;					   
if (window.ActiveXObject) {	 
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');				 
} else {				
xmlhttp = new XMLHttpRequest();	  
}				 
xmlhttp.onreadystatechange = function() {	
if (xmlhttp.readyState == 3) {			 
}					  
if (xmlhttp.readyState == 4) {	 
document.getElementById(rowid).innerHTML = xmlhttp.responseText;	  
ajax(i+1);
}				 

}							  
xmlhttp.open('GET', 'wait.php?q='+i, true);		
xmlhttp.send(null);				  

}</script></head>
<?PHP
$x = '10';
echo '<body onload="ajax(0)">';
for( $y=0; $y<=$x; $y++ ){
echo ' <div id="row'.$y.'">#'.$y.'#</div>'.PHP_EOL;
}?>
</body></html>

 

However, the seconds are 'wrong' now because you should count the 'delay' i guess..

That works, thanks stijn0713! :)

 

May be it's good to ask if I'm going around this the right way. The above is just an example for me to get my head around this (I'm new to Javascript/AJAX).

 

I have a variable amount of queries (and so divs), with each out putting to their own div to process. While each one is being processed (some queries could take 5 secs to process while some are instant), I want it to show 'Loading...' in the div rather than the whole page being on hold for 5 seconds (or 10 if 2 of them take 5 seconds to process for example).

 

Thank you

I'm not 100% sure what stijn meant with "it will probably be that the for loop by then", but the problem does indeed lie within the for loop. Or rather, how you're overwriting the xmlhttp variable for each iteration in that loop.

 

Once you overwrite it, you also remove the onreadystate call, and its associated function. Meaning, only the last iteration of the loop will stick around for long enough, and thus be the only iteration that actually produces the desired effect. The rest of the calls to the PHP script have been orphaned, and is summarily dropped/ignored upon reception.

 

To fix it, you either have to call a function per iteration, or generate a new variable. I recommend moving the loop outside of the function.

Actually stijn's didn't work as intended.

 

row 0 = 0 secs

row 1 = 1 secs

row 2 = 3 (2+1) secs

row 3 = 6 secs (3+2+1) secs

.. and so on

I want all to start at the same time. No waiting.

 

I'll take a closer look at what you said Christian. It's a shame div doesn't support an onload!

The wait.php with the wait is just for the purpose of demonstrating a delay which I might see in what I am going to try and achieve.

 

I think I've nailed it though, this looks like it does exactly what I want :) All queries get processed in quick succession, not after the last one completed.

 

<html>
<head>
	<title>This is a ajax test page</title>
	<script src="[url="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js%22></script>"]http://ajax.googleap...n.js"></script>[/url]
	<script language="Javascript" type="text/javascript">
		function gogo(x) {
			for(var y=0;y<=x;y++) {
				populate(y);
			}
		}

		function populate(i) {
			var xmlhttp;
			if (window.ActiveXObject) {
				xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
			} else {
				xmlhttp = new XMLHttpRequest();
			}
			xmlhttp.onreadystatechange = function() {
				if (xmlhttp.readyState == 4) {
					document.getElementById('row'+i).innerHTML = xmlhttp.responseText;
				}
			}
			document.getElementById('row'+i).innerHTML = 'Loading...';
			xmlhttp.open('GET', 'wait.php?q='+i, true);
			xmlhttp.send(null);
		 }
	</script>
</head>

<?PHP
$x = '10';
echo '<body onload="gogo('.$x.')">';

for( $y=0; $y<=$x; $y++ ){
echo ' <div id="row'.$y.'">#'.$y.'#</div>'.PHP_EOL;
}
?>

</body>

</html>

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.