JavaScript. a loop with innerHTML is not updating during loop execution
Asked Answered
A

3

10

I'm trying to refresh a div from Javascript at each loop and see 1, 2, 3, .... The following code works, but only displays the final result (9998). How is it possible to display all the steps? Thank you in advance.

<html>
<head>
</head>
<body>

<div id="cadre" style="width=100%;height=100%;">
    <input type="button" value="Executer" onclick="launch();"/>
    <div id="result" ></div>
</div>

<script type="text/javascript">
     function launch(){
        for (inc=0;inc<9999;inc++){
            document.getElementById('result').innerHTML = inc;
        }
     }
</script>

</body>
</html>
Anh answered 13/11, 2011 at 10:19 Comment(2)
innerHTML is the devil, stop using it.Haber
@Haber is there any explicit replacement?Justis
L
-2
var i = 0;

function launch(){
           var timer = window.setInterval(function(){
               if( i == 9999 ){
                   window.clearInterval( timer );
               }
               document.getElementById('result').innerHTML = i++;
           }, 100);
}

launch();
Lesko answered 13/11, 2011 at 10:27 Comment(6)
That is going to try to set document.getElementById('result').innerHTML to 9999 10,000 times every second.Speculator
Thanks Oddan, but I already try this solution and it's display only the final result too with ... a delay.Anh
The edited version is better, but it isn't going to stop at 9,999, it's going to keep going forever.Genovese
Yes, it's working! Thank you Oddant. Now, I have to understand the difference with the first version you gave.Anh
this was voluntarily, to lead you to mistakes not to commit ... I'm kidding.. this is what happens when you code snatch. The first version was seamless, no conditions to stop the interval... don't you see the difference ? really ?Lesko
I well see the difference. Thanks againAnh
G
27

JavaScript execution and page rendering are done in the same execution thread, which means that while your code is executing the browser will not be redrawing the page. (Though even if it was redrawing the page with each iteration of the for loop it would all be so fast that you wouldn't really have time to see the individual numbers.)

What you want to do instead is use the setTimeout() or setInterval() functions (both methods of the window object). The first allows you to specify a function that will be executed once after a set number of milliseconds; the second allows you to specify a function that will be executed repeatedly at the interval specified. Using these, there will be "spaces" in between your code execution in which the browser will get a chance to redraw the page.

So, try this:

function launch() {
   var inc = 0,
       max = 9999;
       delay = 100; // 100 milliseconds

   function timeoutLoop() {
      document.getElementById('result').innerHTML = inc;
      if (++inc < max)
         setTimeout(timeoutLoop, delay);
   }

   setTimeout(timeoutLoop, delay);
}

Notice that the function timeoutLoop() kind of calls itself via setTimeout() - this is a very common technique.

Both setTimeout() and setInterval() return an ID that is essentially a reference to the timer that has been set which you can use with clearTimeout() and clearInterval() to cancel any queued execution that hasn't happened yet, so another way to implement your function is as follows:

function launch() {
   var inc = 0,
       max = 9999;
       delay = 100; // 100 milliseconds

   var iID = setInterval(function() {
                            document.getElementById('result').innerHTML = inc;
                            if (++inc >= max)
                               clearInterval(iID);
                         },
                         delay);
}

Obviously you can vary the delay as required. And note that in both cases the inc variable needs to be defined outside the function being executed by the timer, but thanks to the magic of closures we can define that within launch(): we don't need global variables.

Genovese answered 13/11, 2011 at 10:40 Comment(1)
As I understood, the trick of the first example is in call stack.Vernacularize
L
-2
var i = 0;

function launch(){
           var timer = window.setInterval(function(){
               if( i == 9999 ){
                   window.clearInterval( timer );
               }
               document.getElementById('result').innerHTML = i++;
           }, 100);
}

launch();
Lesko answered 13/11, 2011 at 10:27 Comment(6)
That is going to try to set document.getElementById('result').innerHTML to 9999 10,000 times every second.Speculator
Thanks Oddan, but I already try this solution and it's display only the final result too with ... a delay.Anh
The edited version is better, but it isn't going to stop at 9,999, it's going to keep going forever.Genovese
Yes, it's working! Thank you Oddant. Now, I have to understand the difference with the first version you gave.Anh
this was voluntarily, to lead you to mistakes not to commit ... I'm kidding.. this is what happens when you code snatch. The first version was seamless, no conditions to stop the interval... don't you see the difference ? really ?Lesko
I well see the difference. Thanks againAnh
D
-3

Try

document.getElementById('result').innerHTML += inc;
Diverticulitis answered 12/7, 2012 at 13:32 Comment(1)
This is just wrong. The sequence would be 0, 1, 3, 7, or worse: concat the numbers.Bourgeois

© 2022 - 2024 — McMap. All rights reserved.