views:

2103

answers:

3

Hi everyone, I have multiple setTimeout functions like this:

 function bigtomedium(visiblespan) {
  visiblespan.removeClass('big').addClass('medium'); 
  setTimeout(function(){ mediumtosmall(visiblespan);},150);
 };

 function mediumtosmall(visiblespan) {
  visiblespan.removeClass('medium').addClass('small');
  setTimeout(function() { smalltomedium(visiblespan); },150);
 };

 function smalltomedium(visiblespan) {
  visiblespan.removeClass('small').addClass('medium');
  setTimeout(function() { mediumtobig(visiblespan); },150);
 };

 function mediumtobig(visiblespan) {
  visiblespan.removeClass('medium').addClass('big');
  setTimeout(function() { bigtomedium(visiblespan); },150);
 };

Which is activated in jquery onclick:

 $('div.click').click(
  function(event) {
   var visiblespan = $('span:visible');
   mediumtosmall(visiblespan);
  }
 );

What I need to do, is to get the click to hide invisible span as well.

 $('div.click').click(
  function(event) {
   var visiblespan = $('span:visible');
                            var invisiblespan = $('span:not(:visible)');
   mediumtosmall(visiblespan);
   clearTimeout(invisiblespan);
  }
 );

What I'm not sure how to do is to write the clearTimeout function that will stop the loop. Any help is greatly appreciated. Thanks.

+4  A: 

Not sure if you are already aware of this but, clearTimeout accepts a timeoutID that is previously returned from a call to setTimeout.

Therefore you need to assign this timeout id to a variable that remains in scope for when you need to cancel it. Then pass it to the clearTimeout call when you need to stop the loop.

As it is just an integer id, another option might be to create a custom attribute on a dom element using something like "domElement.setAttribute('timoutIDFirst');" (or attr in jQuery) and then just retrieve it using getAttribute when required.

Considering you have multiple timers, using custom attributes on the DOM elements may help keep things tidier.

EG:

      function mediumtosmall(visiblespan) {
                vt.removeClass('medium').addClass('small');

                // Store the timeoutID for this timer
                var storedTimeoutID=setTimeout(function() { smalltomedium(visiblespan); },150);
                 $('span:visible').attr('timeoutID',storedTimeoutID);

        };

and then:

    $('div.click').click(
            function(event) {
                    var visiblespan = $('span:visible');
        var invisiblespan = $('span:visible');
                    mediumtosmall(visiblespan);

                    var storedTimeoutID=invisibleSpan.attr('timeoutID');
                    // Pass the ID to clearTimeout
                    clearTimeout(storedTimeoutID);
            }
    );
Ash
+1  A: 

Probably the best way to handle this is to use setInterval() instead of setTimeout. Like setTimeout, setInterval returns an integer, which can be passed to clearInterval() to cancel the processing.

an example would be (warning, I've not tested this at all):

function animateSizes( jQueryElement ) {
  if( jQueryElement.hasClass("big") 
    jQueryElement.removeClass("big").addClass("medium");
  else if( jQueryElement.hasClass("medium") ) 
    jQueryElement.removeClass("medium").addClass("small");
  else if( jQueryElement.hasClass("small") ) 
    jQueryElement.removeClass("small").addClass("smaller");
  else
    jQueryElement.removeClass("smaller").addClass("big");
}


function startAnimation( elem ) {
  var sizeAnimation = window.setInterval( function() {animateSizes( elem )}, 150);
  elem.attr( "sizeAnimation", sizeAnimation );
}

function stopAnimation( elem ) {
  var sizeAnimation = elem.attr("sizeAnimation");
  window.clearTimeout( sizeAnimation );
}
Adam N
A: 

Have you had a look at jQuery queue? I've not used it but it seems to be designed to do what you're doing.

meouw