0

I have facing this bug, I have a script in JavaScript which handle actions on mousedown event. one do expanding and one do retracting the element using the JavaScript. It's done by timeloop and increasing the height of the div till the height fits the content or decreasing till the div is hidden. When you click on extract, wait till it extract and then click retract all works fine. The problem occurs when you quickly click extract and then retract (before the extraction ends). Then the magic bug appears. The actions is stuck in extracting and re-tracking one step and never ends. I thought the problem should be with the loop variables (loop end condition). Does anyone see where the problem rly is and how it could be fixed?
HERE'S THE CODE:

If you just copy the code into: something.html and extract_retract.js you can see the problem I'm dealing with.

Html document:

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
p{ padding:10px 20px; background:#D9ECFF; }
div.mydivs {
    background: #97D6FB;
    width: 500px;
    height:0px;
    overflow:hidden;
}
div.mydivs > p{ padding:4px 16px; background: #97D6FB;}
</style>
<script type="text/javascript" src="expand_retract.js"></script>
</head>
<body>
<h3>Programming Raw JavaScript expand() and retract() Animation Functions</h3>
<p>
  <a href="#" onclick="return false" onmousedown="expand('div1')">Expand Box 1</a> | 
  <a href="#" onclick="return false" onmousedown="retract('div1')">Retract Box 1</a>
</p>
<div id="div1" class="mydivs">
  <p>Box 1 Content</p>
  <p>Box 1 Content</p>
  <p>Box 1 Content</p>
</div>
<p>
  <a href="#" onclick="return false" onmousedown="expand('div2')">Expand Box 2</a> | 
  <a href="#" onclick="return false" onmousedown="retract('div2')">Retract Box 2</a>
</p>
<div id="div2" class="mydivs">
  <p>Box 2 Content</p>
  <p>Box 2 Content</p>
  <p>Box 2 Content</p>
  <p>Box 2 Content</p>
  <p>Box 2 Content</p>
</div>
</body>
</html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Dokument bez názvu</title>
</head>

<body>
</body>
</html>

expand_retract.js code below:

 function expand(element){
    var target = document.getElementById(element);
    var h = target.offsetHeight;
    var sh = target.scrollHeight;
    var loopTimer = setTimeout('expand(\''+element+'\')',8);
    if(h < sh){
        h += 5;
    } else {
        clearTimeout(loopTimer);
    }
    target.style.height = h+"px";
}
function retract(element){
    var target = document.getElementById(element);
    var h = target.offsetHeight;
    var loopTimer = setTimeout('retract(\''+element+'\')',8);
    if(h > 0){
        h -= 5;
    } else {
        target.style.height = "0px";
        clearTimeout(loopTimer);
    }
    target.style.height = h+"px";
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user1097772
  • 3,499
  • 15
  • 59
  • 95
  • I usually prefer CSS to handle transition like these, the reason is [here](http://stackoverflow.com/questions/2999749/performance-of-css-transitions-vs-js-animation-packages). And you can always trigger CSS transition from javascript event-handlers given [here.](http://stackoverflow.com/questions/4797675/how-do-i-re-trigger-a-webkit-css-animation-via-javascript) Javascript animations are very jerky and unresponsive and you have a live example in front of you now. (Choose wisely which functionality should be given to which language in web-development) – sumitb.mdi Nov 02 '13 at 13:53
  • Well if I understand it well, you advise me using CSS3 instead of js which could bring me to another problem - browser support - to the wisely choosing. Next I still hope there would be problem in the code and hence also some solution how to fix this even if I haven't seen it yet. – user1097772 Nov 02 '13 at 14:15
  • CSS transition are now supported by almost all the major browsers prevailing in the market. (Except IE9 and its earlier version) Also I work on the principle which says "Provide best on small scale instead of better on large scale." You can choose according to your requirement, which you are better aware of than me. – sumitb.mdi Nov 02 '13 at 14:30

1 Answers1

0

Great code. I propose this to solve this issue:

var loopTimer = 0;

function expand(element) {
  clearInterval(loopTimer);
  loopTimer = setInterval('expandA(\''+element+'\')',8);
}

function expandA(element){
    var target = document.getElementById(element);
    var h = target.offsetHeight;
    var sh = target.scrollHeight;
    if(h < sh){
        h += 5;
    } else {
        clearInterval(loopTimer);
    }
    target.style.height = h+"px";
}

function retract(element) {
  clearInterval(loopTimer);
  loopTimer = setInterval('retractA(\''+element+'\')',8);
}

function retractA(element){
    var target = document.getElementById(element);
    var h = target.offsetHeight;
    if(h > 0){
        h -= 5;
    } else {
        target.style.height = "0px";
        clearInterval(loopTimer);
    }
    target.style.height = h+"px";
}
mperezale
  • 11
  • 3