Wednesday, December 16, 2009

Gears Turning - Javascript setTimeout

A common challenge is to present the user with a progress bar or animated gif during a long running script. Sounds really easy, before the long running script set the style of an animated gif from none to inline and start the script. We all know what happens next, a frozen gif. The best way to get around this is to use the setTimeout function to allow the browser to return and let the gif move. The example below uses setTimeout to set up a recursive call to give us the needed user feedback.

To try out the sample add a CEWP to a webpart page and paste the included script. If you don't have a SharePoint site, add the script to a html page and get an animated gif here.

<div id="gears" style="display:none">
   <img src="/_layouts/IMAGES/GEARS_AN.GIF"></img></br></br>
</div>

<div id="done" style="display:none">
   <span>Long Running Done</span></br></br>
</div>

<input type="button" value="Start Long Process" onclick="longRunning()"></input>

<script type="text/javascript">
      
var i, length, data
length = 1500;
data = [];

//random numbers to sort
for (i = 0; i < length; i++) {
    data[i] = Math.floor(Math.random() * length);
}

function sort () {

    i = 0;
    function inner() {
        var j, value;
      
        //do the sorting
        for (j = length; j > i; j--) {
            if (data[j] < data[j - 1]) {
                value = data[j];
                data[j] = data[j - 1];
                data[j - 1] = value;
            }
        }
        i++;

        //let the browser "breath" so the gears will turn
        if (i < length) {
           //to see the browser freeze swap these
           setTimeout(function(){inner();},0);
           //inner();
        }
        else{
           //done hide the gears
           document.getElementById("gears").style.display = "none";
           document.getElementById("done").style.display = "block";
        }

    };
    inner();
}

function longRunning(){
 
  //show gears
  document.getElementById("gears").style.display = "block";

  //call the long running process
  setTimeout(function(){sort();},2000);
}

</script>

No comments:

Post a Comment