0

I have been trying to make a scrolling animation using jQuery, where something happens at each step of the scrolling. The example I was trying was to make each row flash a color. So the javascript was like

function scrCalRows() { //testing: scroll down through calendar
    // just picking certain rows, and do something
    var velt,vpos,vflash;
    var elt=$("#calendarsbody");
    elt.animate({scrollTop:0},0);  // bring to top
    var rows=$("tr");
    for (ii=0;ii<20;ii++) { // just do 100 rows
        velt = rows[ii];
        vpos = $(velt).offset().top;
        vflash = function() {flashelt(velt,'green');}
        elt.animate({scrollTop:vpos},{duration:1000,complete:vflash});
    }
}

function flashelt(oelt,colour) {
    var flashclass = "flash"+colour;
    oelt.classList.remove(flashclass); // first clear
    setTimeout(function() {oelt.classList.add(flashclass);},0)
    setTimeout(function() {oelt.classList.remove(flashclass);},2000)

}

and css
.flashgreen{
    animation-name: flashgreen;
    animation-duration: 1s;
    animation-iteration-count: 2;
}

Here vflash is the "complete" function of the animation, supposed to run after it scrolls to each row. flashelt works fine if I call it on one row, and the scroller scrolls fine, but no flashing. What actually seems to happen is that vflash ends up being defined once after all the steps - I think. I tried various combinations of defining the vflash function inside the loop using ii or velt and such, mostly getting undefs. How can I get this to work properly?

Mike Arrh
  • 145
  • 9
  • Can you create a stacksnippets or jsfiddle to demonstrate? What is purpose of using `for` loop? – guest271314 Jul 26 '16 at 23:29
  • The for loop is to go to each of the rows in turn, and then do something when you get there like make the row flash. – Mike Arrh Jul 27 '16 at 00:28
  • _"The for loop is to go to each of the rows in turn"_ Do the animations run at same time using `for` loop? What do you mean by "in turn"? Are you trying to perform animations in sequential order? – guest271314 Jul 27 '16 at 00:29
  • The scrolling animations do go in sequential order, one row's worth at a time. But there should be a flash green each time it scrolls, if it were working right. – Mike Arrh Jul 27 '16 at 00:43
  • You can create a function within `for` loop to prevent animations running at same time. Could also try using `elt.delay((ii === 0 ? 1 : ii + i) * 1000).animate({scrollTop:vpos},{duration:1000,complete:vflash});` to delay animation using index of element multiplied by 1000 – guest271314 Jul 27 '16 at 00:49
  • But the problem isn't the timing on the scrolling animation, that works fine. It's that the elements don't flash as they scroll. Only the element at the bottom flashes, over and over. vflash isn't getting defined properly. – Mike Arrh Jul 27 '16 at 00:56
  • See http://stackoverflow.com/questions/9815625/looping-through-files-for-filereader-output-always-contains-last-value-from-loo/ , http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – guest271314 Jul 27 '16 at 01:00
  • Thanks - that answers my question exactly! – Mike Arrh Jul 27 '16 at 09:43

1 Answers1

0

Posted above by guest271314: links Looping through files for FileReader, output always contains last value from loop JavaScript closure inside loops – simple practical example So here what I needed to do was wrap the animation-setter inside an Immediately-invoked function expression (IFFE), such as

for (ii=3;ii<15;ii++) {
    velt = rows[ii];
    vpos = $(velt).offset().top;
    (function(elt2,pos2) {
        vflash = function() {flashelt(elt2,'green')};
        elt.animate({scrollTop:pos2},{duration:1000,complete:vflash}
        );
    })(velt,vpos);
}

That way the vflash definition would immediately get the values of velt and vpos, instead of the ones at the end of the loop.

Community
  • 1
  • 1
Mike Arrh
  • 145
  • 9