结束.each和setTimeout()

时间:2015-07-22 17:58:29

标签: javascript jquery html css

我正在尝试使用javascript和jQuery找出停止/启动按钮。我有一个jsfiddle设置试图理解它,但我不能让它工作:http://jsfiddle.net/kkx7m88c/

开始按钮应每次将每个框变为红色。停止按钮应将所有框恢复为蓝色并再次停止变为红色,直到再次按下开始按钮。目前,停止按钮将所有框都变为蓝色,但不会停止播放功能,这意味着尚未变为红色但尚未停止的框。他们变红了。

这是我的js:

// 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和mousedown部分中的.each它会起作用......但也许我完全关闭它。也许我应该使用setInterval()代替?我是jQuery的新手,所以我还在搞清楚这一切!

2 个答案:

答案 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);
    });
});

答案 1 :(得分:0)

您可以通过利用jQuery的setTimeout().delay()完全避免.promise()

这样做的好处是你可以使用jQuery的.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

<强>解释

这个答案采取的方法是合理的,所以如果你不能立即掌握,请不要担心。

如果您不熟悉jQuery的Deferreds / Promises,那么您需要对Deferred Object进行一些背景阅读,并注意.promise()方法可以提供与完成动画(包括延迟)。

您还需要了解javascript的Array.prototype.reduce()方法。

此anwer的核心是$('.box').get().reduce(...),它创建了一个.box元素数组,然后处理该数组以构建一个使用$.when()返回的已解析jQuery承诺的承诺链。

当链中的每个promise都变为满足(表示动画步骤完成)时,执行下一步,其可见方面为goClasses($box, $selection)。声明return $box.delay(500).promise()强制规定步骤之间需要500毫秒的延迟。

“停止”流程只需在所有.stop()元素上调用.box,使任何待处理的.delay(500)无效,并确保相关的承诺永远不会得到满足。动画序列停止。

管理$('.selection').data('running')布尔值,以指示动画是否正在运行(并重置)。当true时,此布尔值用于禁止启动另一个动画序列。

我刚刚意识到$('.selection').data('running')没有必要。我可以测试$('.selection').hasClass('stopped')而不是