Search code examples
jqueryjquery-animatedelaysettimeout

jQuery animation does not work correctly


My jQuery animation is not happening reliably, all the timing seems to be off. it will move up and down quickly then sometimes only move halfway. The setimeout method seems to be better than delay but still is not working very well.

This is what I currently have it is successfully moving the div up and down and depending what I'm doing on the page seems to effect how reliable it is. When I'm doing a lot of .load() it goes crazy sometimes but other times it is fine

<script type="text/javascript">

$(document).ready(function scrollplaying() {
  setTimeout(function() {
    $('#songplaybox').stop().animate({
      scrollTop: 50
    }, '500');
  }, 2000);

  setTimeout(function() {
    $('#songplaybox').stop().animate({
      scrollTop: 0
    }, '500');
  }, 5000);

  window.setTimeout(function() {
    scrollplaying()
  }, 8000)
});

</script>

I have removed the line with scroloTop 0 but it will randomly scroll to top. I am not using scroilltop anywhere else


Solution

  • The problem is basically that different things may happen with this type of code, depending on what you put on the .load() callbacks and the delay between events.

    The DOMContentLoaded ("ready") event happens before the "load" event, but the problem is that typically, you don't know the delay between the two events.

    By executing code such as :

    $(document).ready(function () {
      setTimeout(function() {
        // Do some stuff
        // ...
      }, 2000);
    

    You don't know if the setTimeout callback will be executed before or after the "load" event.

    To simplify (because setTimeout delays are never exacts), if the delay between the DOMContentLoaded event and the load event is less than 2 seconds, the setTimeout callback will be executed after the load event (and then after the callbacks registered with ".load()"). Else, they will be executed before.

    The solution is to make sure that whatever the delay between the "load" and "ready" events, your code is able to cope with this.

    You may consider :

    1. Moving as much as you can of the code in your ".load()" callbacks into ".ready()" callbacks. You should prefer the "ready" event when possible.
    2. If some code really depend on the "load" event, you should put this code (and the code that depends on it, that may include the snippet of your question), into ".load()".

    You should test now, because it's quick to do it, using :

    <script type="text/javascript">
    
    $( window ).load(function scrollplaying() {
      setTimeout(function() {
        $('#songplaybox').stop().animate({
          scrollTop: 50
        }, '500');
      }, 2000);
    
      setTimeout(function() {
        $('#songplaybox').stop().animate({
          scrollTop: 0
        }, '500');
      }, 5000);
    
      window.setTimeout(function() {
        scrollplaying()
      }, 8000)
    });
    
    </script>
    

    However, even if it would seem to work, you really should consider the option "1".

    Remember, the ready event is unlikely to be affected by external resources on slow (or crashed) servers, however the window "load" event may happen very late in this case. Or never happen. So the "ready" event should really be preferred when possible.

    Hope this helps