I have the code bellow and for some reason I have a infinite loop, but I just can't find it to fix it. I just call the function move to dynamicly resize a DIV.

var pos;
var finalPosition;
var myTimer;
var myVar;
var cnt;

function move(finalSize){
cnt=document.getElementById('contentBorder');
pos = cnt.clientHeight;
myVar = cnt.clientHeight;
finalPosition = finalSize;
resize_element(finalPosition);
}

function resize_element(size) {
if (myVar < size){
myTimer=setInterval("increaseBorder()",100);
} else if (myVar > size) {
myTimer=setInterval("decreaseBorder()",100);
} else if (myVar == size) {
} else {
alert('error from: ' + myVar + ' to: ' + size);
}
}

function increaseBorder(){
pos++;

if( pos < finalPosition ){
cnt.style.height = pos + 'px';
} else if(pos >= finalPosition){
clearInterval(myTimer);
} else {
clearInterval(myTimer);
alert('error increase');
}
}

function decreaseBorder(){
pos--;
if( pos > finalPosition ){
cnt.style.height = pos + 'px';
} else if(pos <= finalPosition){
clearInterval(myTimer);
} else {
clearInterval(myTimer);
alert('error increase');
}
}

Dani AI

Generated

A short diagnosis and practical follow-ups.

The infinite loop in this thread was caused by overlapping timers: calling the resize routine again while an earlier setInterval was still running overwrote the single global timer id, so the earlier interval could no longer be stopped. That is the situation pointed out and the reason the simple clear-before-start approach fixed the problem for . Clearing any existing interval (or canceling an ongoing animation) before starting a new one prevents orphaned timers from continuing to run.

Safer patterns and things to watch for:

  • Avoid string arguments to setInterval (they use eval). Pass a function reference instead.
  • Scope the timer to the element (store it on the element or in a map) instead of using a single global variable, so multiple elements do not conflict.
  • Prevent reentrancy by canceling an existing animation or using an "animating" flag before starting another.
  • Prefer requestAnimationFrame for smoother, frame-synced updates and simpler cancelation.

A compact requestAnimationFrame pattern (safe to attach to an element):

function animateHeight(el, targetPx, duration) {
  var startPx = el.clientHeight;
  var startTime = null;
  if (el._raf) cancelAnimationFrame(el._raf);
  function step(ts) {
    if (!startTime) startTime = ts;
    var elapsed = ts - startTime;
    var t = Math.min(elapsed / duration, 1);
    var cur = Math.round(startPx + (targetPx - startPx) * t);
    el.style.height = cur + 'px';
    if (t < 1) el._raf = requestAnimationFrame(step);
    else el._raf = null;
  }
  el._raf = requestAnimationFrame(step);
}

Additional tips: animating from/to height:auto is tricky — measure computed heights first or use max-height transitions. Check box-sizing/padding when reading clientHeight or offsetHeight. Cancel intervals or RAF handles before starting new animations to avoid the exact race that caused the original loop.

Recommended Answers

All 4 Replies


Apologies, I didn't read your code thoroughly before posting. Ignore everything up to the first EDIT: note

ignore..

This code is checking a global variable called 'myVar'

These two functions are modifying a global variable called 'pos'

ignore..

Although you set them both to be the same value in this block...

ignore..

...they are values not references; so they wont change simultaneously.

Use the same variable in both functions, and it shouldn't go into an infinate repetition

EDIT: Actually, perhaps that's not the problem, it looks like it all should work... O_o can you find out where the loop is occuring (add some alerts or similar notifications inside the timer functions)

EDIT2: The only situation I can see where a problem could occur would be where you call move(x), then call move(y) without waiting for the first move() to finish completely: in that case, the timer myTimer will be overrwritten, and you'll lose the ability to stop it with clearInterval(). You could avoid that by always calling clearInterval(myTimer) before creating a new interval.

Hi dcarrillo18.

I made a few edits to this post this morning; they seem to have been forgotton by the system.

The problem is most likely caused when you try to call move() without waiting for a previous move() to finish. That will cause the existing timer ID to be overwritten with a new timer ID, rendering the old timer unreferencable.

The advice I put initially may help you, because checking the current pos value before starting a new timer might block timers from ever being started; but it also might make your code stop functioning after a certain condition is met...

However, I wouldn't rely on it helping solve the overwriting problem. The edit I posted earlier suggested you clear the existing myTimer before creating a new myTimer. I would certainly do that.

Something like this:

function move(finalSize){
cnt=document.getElementById('contentBorder');
pos = cnt.clientHeight;
myVar = cnt.clientHeight;
finalPosition = finalSize; 
clearInterval(myTimer);
resize_element(finalPosition);
}

If you saw the edit; ignore this post aswell as what I suggested you ignore in the original post. Otherwise, just ignore my original post >,<

Thank you very much, that seems to solve my problem.

That's good, I'm glad you've got it working; despite any confusion I may have caused there. =)

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.