How can I get JavaScript to display values and attributes when they are written to input boxes by the script, instead of waiting for a rather lengthy (10 sec) calculation to finish?

- IE does not change the boxes at all, until after the script finishes.

- FF displays the text when it is written, but won't display changes in attributes (such as background color) until the script ends.

But both display the changes immeditely when an alert box pops up.

In my application, I want a "wrong value" error condition to show up immediately, so the user knows this before the script ends (so he can visually check values while the script is still making other values). But the alert box interrupts the processing.

In IE, the error message won't show up until after the script ends. The old values and error conditions stay on the screen for the duration. So the user doesn't know to check until the script ends.

In FF, the error message changes when the error appears or disappears, but the yellow error background does not appear or disappear until the script ends. So the user won't notice it until the script ends.

Does anyone have a trick that is not browser-dependent?

Recommended Answers

All 17 Replies

How about posting some code so that we have something to chew on?

Here is the relevant code.

The JavaScript uses this simple loop to put the values in the form boxes. It works fine, except for the delays.

for(cs = 1; cs <= 3; cs++){
    tmps = 'cm' + cs;
    document.forms.prgrss[tmps].value = saband[cs];
    erx = errif[cs];
    document.forms.prgrss[tmps].style.backgroundColor=eco[erx];
  };

After this code runs, the JavaScript enters a long series of nested loops which have nothing directly to do with the form items shown. The results are written into other similar text boxes.

Here are the form items. They are inside a form tag pair named "prgrss", along with other form items.

<input type="text" id="cm1" name="cm1" value=" " size="32" />
  <input type="text" id="cm2" name="cm2" value=" " size="32" />
  <input type="text" id="cm3" name="cm3" value=" " size="32" />

The code itself works. The ONLY problem is that the display does not update until after the long loops finish:

- IE leaves the old values and colors in the text boxes until the script ends. When the script ends, the new values appear first, and the new colors appear about a second later.

- FF replaces the values at the time the script writes them, but leaves the old colors in the boxes until the script ends. When the script ends, the new colors appear.

Why not keep the function which just does only processing in background for while i.e. make use of setInterval and setTimeout functions which would give the code which displays names enough time to do its job.

Something like this:

<html>
<head>
    <script>
    var counter = 0;
    var hnd = null;
   
    function doSomething()
    {   
        //your lengthy processing function
        hnd = setInterval("calculate()", 3000);

        //your display function
        var d = document.getElementById('d');
        d.innerHTML = "<b>Hello to all</b>";
    }
   
    function calculate()
    {
        alert("Sum of 3  and 5 is 8");
        clearInterval(hnd);
    }
    </script>
</head>
<body onload="doSomething();">
    <div id="d"></div>
</body>
</html>

This way you can keep the function which consumes the most of CPU cycles to run at a later moment.

There is something that doesn't work here:

The lengthy processing function requires values to be passed to it from the error display process. It does nothing to the values displayed, but it does need them to know what to calculate default values for.

I can't pass the values to the processing function if they haven't been set yet.

Also, site policy says I should not modify the html code with scripts. I need to set styles and values instead.

Also, you put in an alert. That alone will cause the display to complete. But I don't want to distract the user from what he is doing with an alert.

It didn't do what I wanted. It delayed the execution of EACH repetition of the loop, extending 8 seconds of execution to over a minute.

One thing is that there is no "single function" for the long calculation. It depends on which button is pushed on the form.

It looks like this (note that the JS is an external file, not embedded):

function button1(){      // activated by pushing button number one
  var a, b, c, d, e, l1, l2, maxa, max1, max2;
  getgrid(a, b, c, d, e);     // this is the error printing function

  for(l1 = 0; l1 < d; l1++){
    for(l2 = 0; l2 < e; l2++){
      calcgrid(a, b, c, l1, l2);       // this function takes time
      checkgrid(a, l1, l2, maxa, max1, max2);
    }
  };
  putgrid(maxa, b, c, max1, max2);
};

function button2(){      // activated by pushing button number two
  var a, b, c, d, e,, l1 l2, maxa, max1, max2;
  getgrid(a, b, c, d, e);     // this is the error printing function

  for(l2 = 0; l2 < e; l2++){
    calcgrid(a, b, c, d, l2);       // this function takes time
    checkgrid(a, d, l2, maxa, max1, max2);
  };
  putgrid(maxa, b, c, max1, max2);
};

function button3(){      // activated by pushing button number three
  var a, b, c, d, e, l1, l2, maxa, max1, max2;
  getgrid(a, b, c, d, e);     // this is the error printing function

  for(l1 = 0; l1 < d; l1++){
    calcgrid(a, b, c, l1, e);       // this function takes time
    checkgrid(a, l1, e, maxa, max1, max2);
  };
  putgrid(maxa, b, c, max1, max2);
};

function button4(){      // activated by pushing button number four
  var a, b, c, d, e, l1, l2, maxa, max1, max2;
  getgrid(a, b, c, d, e);     // this error printing function
 
  calcgrid(a, b, c, d, e);       // this is the function takes time
  checkgrid(a, d, e, maxa, max1, max2);

  putgrid(maxa, b, c, max1, max2);
};

I can't figure out where to put the setInterval without causing multiple delays, because there is no "single function" to call only once.

The setInterval function seems to delay only the function attached to it. I need to delay execution of EVERYTHING after the getgrid function. Yet, all of those other items must execute in the proper order, or the wrong valuyes are used by following functions.

Is there a way to put something right after the getgrid function and before the for loop that delays the following statements to let the output occur?

There is something that doesn't work here:

The lengthy processing function requires values to be passed to it from the error display process. It does nothing to the values displayed, but it does need them to know what to calculate default values for.

I can't pass the values to the processing function if they haven't been set yet.

Also, site policy says I should not modify the html code with scripts. I need to set styles and values instead.

Also, you put in an alert. That alone will cause the display to complete. But I don't want to distract the user from what he is doing with an alert.

I guess I still don't get the big picture. As far as the processing function requiring the data is concerned, you can always make the function which is called before the processing function to make changes to the global variable(map or associative array). This way you don't need to pass anything. Plus you get to decide when to call the processing.

And the 'alert()' in my code was just an example.

See the entry before yours. Our posts crossed in time.

There are several interlocking requirements:

- After the button is pushed, the getgrid function must run and report the errors.

- The error reports must appear before the loops and the long calculations start.

- Each function needs the result of the function before it. In the loop, each function needs the passed variables which the previous functions produced in THAT iteration of the loop.

- There must be nothing which requires the attention of the user except the error messages and the numbers on the screen. No alerts.

The more I think about it, the more I feel that using AJAX (if possible and permitted) is the way to go, though I am assuming that your application is not just an eye candy one which does no real work at the server.

AJAX is asynchronous (though you can make in synchronous, which is not of much help). This asynchronous nature helps the user is continuing his task while you do your time intensive processing at the server.

Also, is the user allowed to press multiple buttons or is it assured that only one button at a time would be pressed till the end result and processing finishes?

Once the loop starts, do the values of variables 'a', 'b', 'c', 'd' etc. change or remain the same as they were when the control entered the function?

But still, considering the checkgrid and the putgrid functions require the values from the computation of calcgrid() function, I don't think delaying the execution of calcgrid() would be of any use...

AJAX is not permitted. It's javascript or nothing.

Also, is the user allowed to press multiple buttons or is it assured that only one button at a time would be pressed till the end result and processing finishes?

Pressing other buttons right now causes the process to start again after it finishes. But I just realized that if I put in the delay, it would let a second process start before the first one finishes.

Once the loop starts, do the values of variables 'a', 'b', 'c', 'd' etc. change or remain the same as they were when the control entered the function?
The value a changes each time calcgrid is called. The checkgrid function looks for the largest value of a, and puts it into maxa, puts the value of l1 or d which caused it into max1, and the value of l2 or e which caused it into max2.

But still, considering the checkgrid and the putgrid functions require the values from the computation of calcgrid() function, I don't think delaying the execution of calcgrid() would be of any use...

setIinterval is like a repeating time bomb, not a pause function. I need a pause function.

I had an idea that I thought would work. I moved all of the contents of button1 except getgrid into another function dobutton1, and called it with setInterval from button1. But it kept repeating the long calculation, and it got the calculations wrong too.

var hnd;  // global variable

function dobutton1(a,b,c,d,e){
  var l1, l2, maxa, max1, max2;
  for(l1 = 0; l1 < d; l1++){
    for(l2 = 0; l2 < e; l2++){
      calcgrid(a, b, c, l1, l2);       // this function takes time
      checkgrid(a, l1, l2, maxa, max1, max2);
    }
  };
  putgrid(maxa, b, c, max1, max2);
  clearInterval(hnd);
};

function button1(){      // activated by pushing button number one
  var a, b, c, d, e;
  getgrid(a, b, c, d, e);     // this is the error printing function
  hnd = setInterval("dobutton1(a,b,c,d,e)", 500);
};

> setIinterval is like a repeating time bomb, not a pause function.
If you know how to tame it, then yes, its of much use, not a time bomb.

>But it kept repeating the long calculation, and it got the calculations wrong too.
Before starting the timer or calling the setInterval() function, check if the 'hnd' is defined or not. If 'hnd' is undefined, you already have the timer running so no need to start it again, if not, then start the timer.

if(typeof(hnd) != 'undefined' || hnd)
{
    setInterval("function()", 1000);
}

// [B]OR[/B] clear the timer as soon as you enter the doButton() function

function dobutton1(a,b,c,d,e){
  clearInterval(hnd);
  var l1, l2, maxa, max1, max2;
  for(l1 = 0; l1 < d; l1++){
    for(l2 = 0; l2 < e; l2++){
      calcgrid(a, b, c, l1, l2);       // this function takes time
      checkgrid(a, l1, l2, maxa, max1, max2);
    }
  };
  putgrid(maxa, b, c, max1, max2);
};

> setIinterval is like a repeating time bomb, not a pause function.
If you know how to tame it, then yes, its of much use, not a time bomb.

:icon_cheesygrin: :icon_cheesygrin:

I was thinking in terms of somehing you set, and it goes off later, not destructiveness.

But it kept repeating the long calculation, and it got the calculations wrong too.

Before starting the timer or calling the setInterval() function, check if the 'hnd' is defined or not. If 'hnd' is undefined, you already have the timer running so no need to start it again, if not, then start the timer.

if(typeof(hnd) != 'undefined' || hnd)
{
    setInterval("function()", 1000);
}

// [B]OR[/B] clear the timer as soon as you enter the doButton() function

function dobutton1(a,b,c,d,e){
  clearInterval(hnd);
  var l1, l2, maxa, max1, max2;
  for(l1 = 0; l1 < d; l1++){
    for(l2 = 0; l2 < e; l2++){
      calcgrid(a, b, c, l1, l2);       // this function takes time
      checkgrid(a, l1, l2, maxa, max1, max2);
    }
  };
  putgrid(maxa, b, c, max1, max2);
};

Then this works differently than the description I have?

I understood from the documentation I have that the called function would stop executing as soon as the timer was cleared. I thought you put the clear at the end to make sure it finished the function.

The 'clearInterval()' cancels the timer and not the function. Its like a kid going down a ride again and again. Once he is told not to do it again, sure thing, it doesn't happen again, but that doesn't mean his existing ride is canceled in the middle. And I see no such thing as you mention in the documentation.

This code works like a charm in IE, FF and Opera.

<html>
<head>
    <script type="text/javascript">
    var hnd;
    
    function doSomething()
    {    
        hnd = setInterval("calculate()", 2000);
        var d = document.getElementById('d');
        d.innerHTML = "Hello to all. My name is <b>sos.</b>";
    }
    
    function calculate()
    {
        clearInterval(hnd);
        for(var i = 1, sum = 0; i <= 1000; ++i)
            sum += i;
        alert("1 + 2 + 3 + .. + 1000 = " + sum);
    }
    </script>
</head>
<body onload="doSomething();">
    <div id="d"></div>    
</body>
</html>

Thank you. The book I have is clear as mud on this function.

I just had a marvelous idea on how to kill two birds with one stone here - the delay, and preventing other buttons from working during the calculation - without adding any new functions to my earlier 4-button example!

Glad you could get new ideas by discussing the situation with me. :)

That's what this place is for!!!

It works!
Each function calls itself recursively through setInterval.
I used the variable smo to control execution of the long calculation and prevent multiple button presses from interacting.

var smo = 0;
var hnd;

function button1(){ // activated by pushing button number one
  var a, b, c, d, e, l1, l2, maxa, max1, max2;
  getgrid(a, b, c, d, e); // this is the error printing function

  if(smo < 1){
    hnd = setInterval("button1()", 300);
    smo = 1;
  }
  else if(smo < 5){
    clearIngterval(hnd);
    smo = 5;
    for(l1 = 0; l1 < d; l1++){
      for(l2 = 0; l2 < e; l2++){
        calcgrid(a, b, c, l1, l2); // this function takes time
        checkgrid(a, l1, l2, maxa, max1, max2);
      };
    };
    putgrid(maxa, b, c, max1, max2);
    smo = 0;
  };
};

function button2(){      // activated by pushing button number two
  var a, b, c, d, e,, l1 l2, maxa, max1, max2;
  getgrid(a, b, c, d, e);     // this is the error printing function

  if(smo < 1){
    hnd = setInterval("button2()", 300);
    smo = 2;
  }
  else if(smo < 5){
    clearIngterval(hnd)
    smo = 5;
    for(l2 = 0; l2 < e; l2++){
      calcgrid(a, b, c, d, l2);       // this function takes time
      checkgrid(a, d, l2, maxa, max1, max2);
    };
    putgrid(maxa, b, c, max1, max2);
    smo = 0;
  };
};

function button3(){      // activated by pushing button number three
  var a, b, c, d, e, l1, l2, maxa, max1, max2;
  getgrid(a, b, c, d, e);     // this is the error printing function

  if(smo < 1){
    hnd = setInterval("button3()", 300);
    smo = 3;
  }
  else if(smo < 5){
    clearIngterval(hnd);
    smo = 5;
    for(l1 = 0; l1 < d; l1++){
      calcgrid(a, b, c, l1, e);       // this function takes time
      checkgrid(a, l1, e, maxa, max1, max2);
    };
    putgrid(maxa, b, c, max1, max2);
    smo = 0;
  };
};

function button4(){      // activated by pushing button number four
  var a, b, c, d, e, l1, l2, maxa, max1, max2;
  getgrid(a, b, c, d, e);     // this error printing function

  if(smo < 1){
    hnd = setInterval("button4()", 300);
    smo = 4;
  }
  else if(smo < 5){
    clearIngterval(hnd);
    smo = 5;
    calcgrid(a, b, c, d, e);       // this is the function takes time
    checkgrid(a, d, e, maxa, max1, max2);
    putgrid(maxa, b, c, max1, max2);
    smo = 0;
  };
};
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.