Lolo
Lolo

Reputation: 4159

How to update a web page from javascript without exiting javascript

I would like to animate an html page with something like this:

function showElements(a) {   
  for (i=1; i<=a; i++)  {  
    var img = document.getElementById(getImageId(i));  
    img.style.visibility = 'visible';  
    pause(500);  
  }  
}

function pause(ms) {
  ms += new Date().getTime();
  while (new Date() < ms){}
}

Unfortunately, the page only renders once javascript completes.

If I add

 window.location.reload();

after each pause(500); invocation, this seems to force my javascript to exit. (At least, I do not reach the next line of code in my javascript.)

If I insert

 var answer=prompt("hello");

after each pause(500), this does exactly what I want (i.e. update of the page) except for the fact that I don't want an annoying prompt because I don't actually need any user input.

So... is there something I can invoke after my pause that forces a refresh of the page, does not request any input from the user, and allows my script to continue?

Upvotes: 1

Views: 4778

Answers (5)

Eric
Eric

Reputation: 97565

While the javascript thread is running, the rendering thread will not update the page. You need to use setTimeout.

Rather than creating a second function, or exposing i to external code, you can implement this using an inner function with a closure on a and i:

function showElements(a) {
    var i = 1;
    function showNext() {
        var img = document.getElementById(getImageId(i));  
        img.style.visibility = 'visible'; 
        i++;
        if(i <= a) setTimeout(showNext, 500);
    }
    showNext();
}

If I add window.location.reload(); after each pause(500) invocation, this seems to force my javascript to exit

window.reload() makes the browser discard the current page and reload it from the server, hence your javascript stopping.


If I insert var answer=prompt("hello"); after each pause(500), this does exactly what I want.

prompt, alert, and confirm are pretty much the only things that can actually pause the javascript thread. In some browsers, even these still block the UI thread.

Upvotes: 2

Dr.Molle
Dr.Molle

Reputation: 117314

function showElements(a,t) {   
  for (var i=1; i<=a; i++)  {  
    (function(a,b){setTimeout(function(){
      document.getElementById(getImageId(a)).style.visibility = 'visible'},a*b);}
    )(i,t)  
  }  
}

The t-argument is the delay, e.g. 500

Demo: http://jsfiddle.net/doktormolle/nLrps/

Upvotes: 0

Jaime Torres
Jaime Torres

Reputation: 10515

Javascript is inherently event-driven/non-blocking (this is one of the great things about javascript/Node.js). Trying to circumvent a built in feature is never a good idea. In order to do what you want, you need to schedule your events. One way to do this is to use setTimeout and simple recursion.

function showElements(a) {   
  showElement(1,a);
}

function showElement(i, max) {
   var img = document.getElementById(getImageId(i));  
   img.style.visibility = 'visible';
   if (i < max) {
      setTimeout(function() { showElement(i+1, max) }, 500);
   }
}

Upvotes: 1

Alex K
Alex K

Reputation: 7217

var i = 1;
function showElements(a) {   
    var img = document.getElementById(getImageId(i));  
    img.style.visibility = 'visible';  
    if (i < a) {
      setTimeout(function() { showElements(a) }, 500);  
    }
    i++;
}
showElements(5);

Upvotes: 0

SLaks
SLaks

Reputation: 887225

Your pause() function sleeps on the UI thread and freezes the browser.
This is your problem.

Instead, you need to call setTimeout to call a function later.

Upvotes: 1

Related Questions