0

This jQuery code loops through rows in a table and highlights each row as it goes. I have a stop button that sets a variable to false.

I know that I can break out of the .each loop by using return false;, but I want it to break out from within the queue.

How can I do this if the var is false?

$('.js-channel-notes tr').each(function(i) {
    $(this).delay((i++) * 160).queue(function() {
        $('.channel-row-highlight').removeClass('channel-row-highlight');
        $(this).addClass('channel-row-highlight').clearQueue();
    });
});
Stack'd
  • 48
  • 4
ezero
  • 1,230
  • 3
  • 12
  • 27
  • `.queue()` doesn't actually *run* the function. It just adds it onto a queue, to be ran at a later point with `.dequeue()`. – gen_Eric Dec 31 '14 at 21:30
  • Impossible when using `.each()`. The loop ends long before the first `.queue()` starts. Don't use a loop at all. Instead select the elements, set up the first `.queue()`, and then when it runs, have it call the next, all the while keeping track of which index you're on. –  Dec 31 '14 at 21:30
  • If all you care about is highlighting, why not just use css? (the :hover pseudo selector is what you want) Example: http://jsfiddle.net/bfttLxsq/ – TheIronDeveloper Dec 31 '14 at 21:35
  • Have you tried break; ? – Indigo Dec 31 '14 at 21:35
  • @Indigo the `break` statement works for loops constructed using keywords like `for` and `while`. The `each` function executes its supplied argument function for each element of a collection, and therefore a `break` inside that function would not impact the iterator in the `each` function itself. – Palpatim Dec 31 '14 at 21:38
  • @TheIronDeveloper: He doesn't want a hover effect. –  Dec 31 '14 at 21:42

2 Answers2

1

Don't use .each() or .queue(). Just make a function that operates on the current element and delays the execution of the next call to the same function.

The current element is determined by an i counter that you increment on each call.

To break it, have a flag that is checked to exit the function immediately.

var tr = $('.js-channel-notes tr');
var i = 0;
var halt;

function next() {
    if (halt) return;

    $('.channel-row-highlight').removeClass('channel-row-highlight');
    tr.eq(i).addClass('channel-row-highlight');
    i++;
    if (i < tr.length) {
        setTimeout(next, 160);
    }
}

next();

Or skip jQuery altogether since there's so little being used there anyway.

var tr = document.querySelectorAll('.js-channel-notes tr');
var i = 0;
var halt;

function next() {
    if (halt) return;

    var c = document.querySelector('.channel-row-highlight');
    if (c) c.classList.remove('channel-row-highlight');
    tr[i].classList.add('channel-row-highlight');
    i++;
    if (i < tr.length) {
        setTimeout(next, 160);
    }
}

next();

There's far more engineering than is needed by using .delay() and .queue(). Simpler is better.

  • Excellent, thanks. I only recently added jQuery into my project and am still thinking about removing it again, this is one part where it is not required. – ezero Dec 31 '14 at 21:56
0

Apparently, you don't want an each.

You want a continuation, that you can 'conditionally' continue. Basically something like this (but unchecked, unrun):

var continuation = function(todo) {
    if (!todo.length) return;
    var head = todo[0];
    var tail = todo.slice(1); // or what is it
    head.delay(...).queue(function(){
         if (somecondition)
             continuation(tail);
    });
};
continuation($('.js-channel-notes tr'));
xtofl
  • 40,723
  • 12
  • 105
  • 192