2015-07-22 2 views
0

Я пытаюсь выяснить кнопки остановки/запуска, используя javascript и jQuery. У меня есть jsfiddle, чтобы попытаться это понять, но я не могу заставить его работать: http://jsfiddle.net/kkx7m88c/Завершить .each и setTimeout()

Кнопка запуска должна включать каждый красный цвет по одному. Кнопка «Стоп» должна вернуть все коробки обратно на синий и больше не загораться, пока не будет нажата кнопка «Пуск». В настоящее время кнопка остановки превратит все ящики в синий цвет, но не остановит функцию воспроизведения, а это означает, что коробки, которые не были красными, не прекращаются. Они становятся красными.

Вот мои ЯШ:

// new class turns the boxes red with css 

function goClasses(item, container) { 
    $(container).removeClass('stopped'); 
    $(item).addClass('new'); 
} 

function stopClasses(item, container) { 
    $(item).removeClass('new'); 
    $(container).addClass('stopped'); 
} 


$('#go').mousedown(function() { 
    $('.box').each(function(i){ 
     var item = $(this); 
     var container = $('.selection'); 
     setTimeout(function() { 
      goClasses(item, container); 
     }, 500 * i); 
     if ($(container).hasClass('stopped')) { 
      //clearTimeout(); /* this doesn't appear to do anything */ 
      //return false; /* this stops the 'go' button from working properly when clicked again after the 'stop' button has clicked */ 
     } 
    }); 
}); 

$('#stop').mousedown(function() { 
    $('.box').each(function (i) { 
     var item = $(this); 
     var container = $('.selection'); 
     stopClasses(item, container); 
    }); 
}); 

Это мое понимание того, что если бы я только мог закончить SetTimeout и .each в разделе MouseDown, что она будет работать ... но, возможно, я его полностью выключен. Может быть, я должен использовать setInterval() вместо этого? Я новичок в jQuery, поэтому я все еще все понял!

+0

Я не думаю, что ваша проблема связана с таймером, это из-за цикла, который продолжается. Попробуйте установить флаг из кнопки остановки и проверьте его в функции запуска, чтобы разбить цикл. –

ответ

2

магазин ссылкой на таймер и отменяют

$('#go').mousedown(function() { 
    $('.box').each(function(i){ 
     var item = $(this); 
     var container = $('.selection'); 
     var timer = setTimeout(function() { //store the id that the setTimeout returns 
      goClasses(item, container); 
     }, 500 * i); 
     item.data("timer", timer); //store it as a data attribute 
    }); 
}); 

$('#stop').mousedown(function() { 
    $('.box').each(function (i) { 
     var item = $(this); 
     window.clearTimeout(item.data("timer")); //check the data attribute for the timer and cancel it 
     var container = $('.selection'); 
     stopClasses(item, container); 
    }); 
}); 
+0

Это работает отлично! Спасибо! – Alana

0

Вы можете избежать setTimeout() полностью за счет использования JQuery-х .delay() и .promise().

Это имеет то преимущество, что вы можете использовать jQuery's .stop(), чтобы убить задержки и остановить весь процесс.

function goClasses($item, $container) { 
    $container.removeClass('stopped'); 
    $item.addClass('new'); 
} 

function stopClasses($item, $container) { 
    $item.removeClass('new'); 
    $container.addClass('stopped'); 
} 

$('#go').on('click', function() { 
    var $selection = $(".selection"); 
    if(!$selection.data('running')) { 
     $('.box').get().reduce(function(p, box) { 
      return p.then(function() { 
       var $box = $(box); 
       goClasses($box, $selection); 
       return $box.delay(500).promise(); 
      }); 
     }, $.when()); 
     $selection.data('running', true); 
    } 
}); 

$('#stop').on('click', function() { 
    stopClasses($('.box').stop(), $('.selection').data('running', false)); 
}); 

Также включен механизм, чтобы сделать кнопку «Go», лучше вели себя в случае, если пользователь нажимает ее снова в то время как последовательность анимации продолжается.

DEMO

Объяснение

Подход на этом ответе является достаточно продвинутым, поэтому, пожалуйста, не волнуйтесь, если вы не можете понять это сразу.

Если вы не famliar с JQuery в Deferreds/Promises, то вам нужно будет сделать некоторый фон чтения на Deferred Object и знать, что метод .promise() делает обещание доступно, связанным с завершением анимации (в том числе с задержкой).

Вы также должны понимать метод javascript Array.prototype.reduce().

Сердце этого Anwer является $('.box').get().reduce(...), который создает массив .box элементов, а затем обрабатывает этот массив, чтобы построить цепочку обещание, посеянных с разрешенной JQuery обещание возвращенного $.when().

По мере выполнения каждого из обещаний в цепочке (с указанием завершения этапа анимации), поэтому выполняется следующий шаг, видимым аспектом которого является goClasses($box, $selection). Заявление return $box.delay(500).promise() устанавливает требуемую задержку в 500 мс между этапами.

Процесс «остановки» просто вызывает .stop() на всех .box элементах, сбрасывая любые ожидающие .delay(500) и гарантируя, что связанное с ним обещание никогда не будет выполнено. Последовательность анимации прекращается.

Управление процессом boolean осуществляется так, что оно указывает, работает ли анимация (и сбрасывается). Когда true, это логическое значение используется, чтобы запретить запуск другой последовательности анимации.

Я только что понял, что $('.selection').data('running') не требуется. Я мог бы проверить $('.selection').hasClass('stopped') вместо

+0

это немного выше моей головы ... Не могли бы вы объяснить, что здесь происходит? Мне кажется более кратким, чем использование setTimeout(), но я не могу следовать. – Alana

+0

@ Алана, я добавил объяснение, но, как я уже сказал, пожалуйста, не волнуйтесь, если вы не получите его. Вернитесь сюда, когда у вас есть еще один javascript под вашим поясом. –

Смежные вопросы