Search code examples
jquerysettimeoutfadein

jQuery fade in/out and delay, cancelling previous animation


I want to make this work and be interruptible. There should be 1second fadein, 1second fadeout with 3s delay in between, but during that 3seconds or 1second fadein/fadeout, there maybe another action taking place that should take place -- stop previous action and never complete it. Eg during 3second of showing image, the user wants to go to next/next/next/next, so immediately animation should stop and go to next/next/next/next (multiple user clicks) without ever completing the animation started prior to this.

external calls: SlideShow(1); or SlideShow(-1);, etc

function SlideShow(action) {
      slideCount = (slideCount+action) % totalSlides; 

      slides.eq(slideCount).fadeIn(fadeInAmount);

      // add 3 second delay/SetTimeout/etc here
      // how should setTimeout be involved here so that it, and the fadein/fadeout are stoppable (without ever continuing)

      slides.eq(slideCount).fadeOut(fadeOutAmount,function() {

      slideCount = (slideCount+increment) % totalSlides;
      SlideShow(0);
    });

  }

This was the starting point with 1s fadein, 3s delay, 1s fadeout

slides.eq(slideCount).fadeIn(fadeInAmount).delay(fadeDelay).addClass('jqImage').fadeOut(fadeOutAmount,function() {
      slideCount = (slideCount+increment) % totalSlides;
      SlideShow(0);
});

here is one non-working attempt using setTimeout:

  function timerStop() {
        if (runningTimer) {
            clearTimeout(runningTimer);
            runningTimer = 0;
        }
  }


  var runningTimer;

  function SlideShow(action) {

    //    $('body').stop(); slides.eq(slideCount).dequeue(); slides.eq(slideCount).stop();


    slideCount=(slideCount+action) % totalSlides;

    $('#slideControls').html(
      (slideCount+1) + "/" + totalSlides
      + "<br>" + "Delay: " + fadeDelay/1000
      + "<br>" + "Skip: " + increment
    );

    $('#slideStatusbar').html( slides.eq(slideCount).find('img').attr('src').replace(/^.*[\\\/]/, '') ); // Filename only
    //slides.eq(slideCount).fadeIn(fadeInAmount).delay(fadeDelay).addClass('jqImage').fadeOut(fadeOutAmount,function() {
    //      slideCount < totalSlides-1 ? slideCount+=increment : slideCount=0;
    //  slideCount = (slideCount+increment) % totalSlides;
    //  SlideShow(0);


//    slides.eq(slideCount).addClass('jqImage');
    slides.eq(slideCount).fadeIn(fadeInAmount);


    runningTimer=setTimeout(function(){

      slides.eq(slideCount).fadeOut(fadeOutAmount,function() {
        slideCount = (slideCount + increment) % totalSlides;   //slideCount = (slideCount + (action ? action : increment)) % totalSlides; 
        SlideShow(0);
      });

    }, 1000);




  }

Solution

  • This wasn't an easy one.
    It took a couple hours to fix.

    The temporary "sandbox" you made for me on your server was really usefull.
    I would not have been able to solve the problem without it.
    ;)

    Here is your function now:

      var slideCountAdjusted;
      var slideCount;
      function SlideShow(action) {
    
        //---------- read from sliders -----------
        slideCount = parseInt( $('#slider1').val()-1 );
        fadeDelay  = parseInt( $('#slider2').val() );
        step       = parseInt( $('#slider3').val() );
        //----------------------------------------
    
        slideCountAdjusted=(slideCount+action) % totalSlides;
        if(slideCount>=totalSlides && action>0){
            slideCountAdjusted=0;
        }
        if(slideCount==0 && action<0){
            slideCountAdjusted=totalSlides-1;
        }
    
        $('#slider1').val(slideCountAdjusted+1).change();
    
        $('#slideStatusbar').html( 
          jscript_slideshowLinks                                                        // California > 
          +     " > "
          +     slides.eq(slideCountAdjusted).find('img').attr('src').replace(/^.*[\\\/]/, '')        // filename
        ); // Filename only
    
        if(intervalEnabled){
          runningTimer=setTimeout(function(){
            slides.eq(slideCount).fadeOut(fadeOutAmount,function() {
    
              slideCount = (slideCount + step) % totalSlides;   //slideCount = (slideCount + (action ? action : increment)) % totalSlides; 
              $('#slider1').val(slideCount+1).change();
    
              SlideShow(0);
            });
          }, fadeDelay*1000);
        }
    
        if(showNow){
          slides.eq(slideCount).fadeOut(fadeOutAmount,function() {
            slides.eq(slideCountAdjusted).fadeIn(fadeInAmount);
          });
        }else{
          slides.eq(slideCountAdjusted).fadeIn(fadeInAmount);
        }
      }
    

    I also changed these click handlers:

      $('#slideshowPlay').off("click").on("click", function (e){ mySliderPlay(); SlideShow(0); });
      $('#slideshowPause').off("click").on("click", function (e){ mySliderPause();  });
    
      $('#slideshowPrevious').click(function (e) { mySliderBack(); });
      $('#slideshowNext').click(function (e)     { mySliderForward(); });
    

    And here are those handlers:

      var intervalEnabled=true;
      var showNow=false;
    
      //---------------------------------------------------------------------
      // slideshowTimer routines - start
      //---------------------------------------------------------------------
      function mySliderPause() {
        console.log("PAUSE button pressed;");
        intervalEnabled=false;
        clearTimeout(runningTimer);
      }
      function mySliderPlay() {
        console.log("PLAY button pressed;");
        intervalEnabled=true;
        showNow=false;
      }
      function mySliderBack() {
        console.log("BACK button pressed;");
        intervalEnabled=false;
        showNow=true;
        clearTimeout(runningTimer);
        SlideShow(-1);
    
      }
      function mySliderForward() {
        console.log("FORWARD button pressed;");
        intervalEnabled=false;
        showNow=true;
        clearTimeout(runningTimer);
        SlideShow(1);
      }
    

    Some more changes, in your index.html...

    I commented out these script calls, which I don't even know what they were supposed to do...
    But since I removed them, your page is loading a bit faster AND the strange interval behavior which took me soo long to find magically dissapeared.

    <!--script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script>
    <script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script>
    <script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script-->
    

    I also commented out this jQuery lib call:

    <!--script src='/ans/jquery/jquery-1.11.0.min.js'></script-->
    

    Because you were calling this one too. So I move it a couple line up.

    <script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>