0

Attempting to build a chart that allows users to click play and it will cycle through an array of years, displaying each year in the chart for a few seconds, before moving onto the next.
It should also allow the user to click pause, pausing the animation; this is where I am failing.

I'm fairly certain my issue is scoping, but not 100%; I've got it to where the animation will cycle through, however when the user clicks pause, it continues to cycle through, not putting the animation on pause. I can see the clearInterval is firing off in console.log, but again, it does nothing and the animation continues.

I'm using setTimeout to delay each charts' appearance and using (most certainly in the wrong manner) setInterval to schedule the loop. I've read/tried a number of answers here dealing with setTimeout and setInterval, but to no avail. I'm positive it is my lack of understanding why they don't work and not that my question "is different" from the others.

That said, I've been banging my head on my desk for three days now and could really use some pointers here. Below is the JavaScript/jQuery that I'm currently working with:

jQuery('#animation-play').on('click', function() {
  // loopThroughYears();
  var animation;
  if (jQuery('#animation-play').hasClass('play')) {
    jQuery('#animation-play').addClass('stop').removeClass('play').text('Pause Animation');
    var years = [2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015];
    var time = 1000;
    if (animation) {
      clearInterval(animation);
    }
    animation = setInterval(function() {
      $.each(years, function(index, values) {
        setTimeout(function() {
          if (years.this < 2016) {
            selectChartYear(values);
            jQuery("#chart-years").val(values);
          }
        }, time);
      });
    }, time);
  } else {
    jQuery('#animation-play').addClass('play').removeClass('stop').text('Play Animation');
    console.log("Timeout Cleared!");
    clearInterval(animation);
  }
});
Mike Cluck
  • 31,869
  • 13
  • 80
  • 91
albert
  • 8,112
  • 3
  • 47
  • 63

1 Answers1

4

The animation variable is declared inside the click handler, creating a new one every time a click happens.

You'd have to store that variable somewhere else, for instance on the element with jQuery's data()

jQuery('#animation-play').on('click', function() {
    
    clearInterval( $(this).data('animation') );
    
    if (jQuery('#animation-play').hasClass('play')) {
        jQuery('#animation-play').addClass('stop')
                                 .removeClass('play')
                                 .text('Pause Animation');
                                 
        var years = [2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015];
        var time  = 1000;
        var self  = $(this);
        
        self.data('year', self.data('year') || -1);
        
        self.data('animation', 
            setInterval(function() {
             var idx   = self.data('year') + 1;
                if ( idx > years.length ) {
                 idx = 0;
                    self.trigger('click');
                } else {
                    var value = years[idx];

                    //selectChartYear(value);
                    jQuery("#chart-years").val(value);
                }
                
    self.data('year', idx);
            }, time)
        );
    } else {
        jQuery('#animation-play').addClass('play')
               .removeClass('stop')
                                 .text('Play Animation');
                                 
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="animation-play" class="play">
    click here to start
</div>
<br/>
<input id="chart-years" />
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • thanks. that actually doesn't stop it, and also restarts the animation once it goes through, essentially an endless loop. – albert Apr 20 '17 at 20:45
  • 1
    Oh, I see, you want to just run through once, and stop and resume on the click etc? You're not really close, you probably want something more like this -> **https://jsfiddle.net/a894np6L/** – adeneo Apr 20 '17 at 20:50
  • so close. that works, until the years run out. so it'll play. then let user pause. but when play is clicked again, after 2015 it throws a "Uncaught TypeError: Cannot read property '23' of null", which is a variable in the selectChartYears() function. – albert Apr 20 '17 at 21:01
  • i'm guessing its a 'this' context issue. – albert Apr 20 '17 at 21:08
  • I don't know what the `selectChartYears` function looks like, so I can't really see that error at all. – adeneo Apr 20 '17 at 21:55
  • i got it! was throwing the error when it reached beyond the number of years. thank you so much for your help! sincerely appreciate ya! – albert Apr 20 '17 at 23:51