admin管理员组

文章数量:1291091

I understand that in order to remove an interval you need a stored reference to it, so I figured I'll store function returns in a global array. But why when I click on a cell the intervals keep going and only one stops (I saw first and last cell to stop flashing)?

What I wanted it to do is append a continuous fadeTo on all cells of a table row (excluding first one), and a listener that on clicking any of these cells would stop animations on all of them.

Here's my best effort so far (jsfiddle):

var intervals;
var target = $('#table');
var qty = target.find('td:contains(Price)');
var row = qty.closest('tr');
arr = new Array();
row.find('td').each( function() {
if ($(this).text() !== "Price" ) {
    intervals = new Array();
    addAnimation($(this));
    }
});
function addAnimation(cell) {
    var intv = setInterval(function() {
        cell.fadeTo("slow", 0.3);
        cell.fadeTo("slow", 1);
    }, 1000);
    intervals.push(intv);
    cell.click(function() {
        for (var i = 0; i < intervals.length; intervals++) {
            window.clearInterval(intervals[i]);
        }
    });
}

I understand that in order to remove an interval you need a stored reference to it, so I figured I'll store function returns in a global array. But why when I click on a cell the intervals keep going and only one stops (I saw first and last cell to stop flashing)?

What I wanted it to do is append a continuous fadeTo on all cells of a table row (excluding first one), and a listener that on clicking any of these cells would stop animations on all of them.

Here's my best effort so far (jsfiddle):

var intervals;
var target = $('#table');
var qty = target.find('td:contains(Price)');
var row = qty.closest('tr');
arr = new Array();
row.find('td').each( function() {
if ($(this).text() !== "Price" ) {
    intervals = new Array();
    addAnimation($(this));
    }
});
function addAnimation(cell) {
    var intv = setInterval(function() {
        cell.fadeTo("slow", 0.3);
        cell.fadeTo("slow", 1);
    }, 1000);
    intervals.push(intv);
    cell.click(function() {
        for (var i = 0; i < intervals.length; intervals++) {
            window.clearInterval(intervals[i]);
        }
    });
}
Share Improve this question asked Apr 10, 2014 at 13:27 kacprkacpr 3921 gold badge8 silver badges28 bronze badges 5
  • 2 i is not what you think it is in this line: window.clearInterval(intervals[i]);. Google javascript closures. Other than that, your code looks like it should work. – blgt Commented Apr 10, 2014 at 13:31
  • @blgt—you're on the wrong track, nothing to do with closures (which I think is what you meant rather than "context"). – RobG Commented Apr 10, 2014 at 13:33
  • @RobG Yep, corrected. Isn't it? edit: actually you're right, it's not the only problem. But it is one of them. – blgt Commented Apr 10, 2014 at 13:35
  • I figured I'll store function returns in a global array, if var intervals is creating a global, then the rest of your code is also putting an awful lot of things in the global namespace – Paul S. Commented Apr 10, 2014 at 13:41
  • @PaulS. I would appreciate it if you could point out any other problems with that code, here's a fiddle with fixes pointed to me so far - jsfiddle/tSc54 – kacpr Commented Apr 10, 2014 at 13:47
Add a ment  | 

2 Answers 2

Reset to default 9

You are instantiating the intervals array multiple times and incrementing the wrong parameter in the for loop:

var intervals = [],
    target = $('#table'),
    qty = target.find('td:contains(Price)'),
    row = qty.closest('tr');

row.find('td').each( function() {
    if ($(this).text() !== "Price" ) {
        addAnimation($(this));
    }
});

function addAnimation(cell) {
    var intv = setInterval(function() {
        cell.fadeTo("slow", 0.3);
        cell.fadeTo("slow", 1);
    }, 1000);
    intervals.push(intv);

    cell.click(function() {
        for (var i = 0; i < intervals.length; i++) {
            window.clearInterval(intervals[i]);
        }
        $(this).stop();
    });
}

See: fiddle

Your other problem is here:

var intervals;
...
if ($(this).text() !== "Price" ) {
    intervals = new Array();
    addAnimation($(this));

That creates a new array each time. You should be initialising intervals when you declare it and delete the line creating a new array in the if block:

var intervals = [];
...
if ($(this).text() !== "Price" ) {
    addAnimation($(this));
}

However, you may wish to run this more than once, so you should clear out the array when you clear the intervals, something like:

function addAnimation(cell) {
    var intv = setInterval(function() {
        cell.fadeTo("slow", 0.3);
        cell.fadeTo("slow", 1);
    }, 1000);
    intervals.push(intv);
    cell.click(function() {
        for (var i = 0; i < intervals.length; intervals++) {
            window.clearInterval(intervals[i]);
        }

        // reset the array
        intervals = [];

    });
}

or replace the for loop with something like:

  while (intervals.length) {
    window.clearInterval(intervals.pop());
  }

which stops the intervals and clears the array in one go. :-)

本文标签: javascriptHow to setInterval() and removeInterval() in this situationStack Overflow