空选择上的jQuery hide()不会触发回调

时间:2012-12-06 10:09:30

标签: jquery jquery-selectors

我正在尝试使用jQuery过滤页面上的表格。我想淡出当前显示的行并淡入与新选择匹配的行。我的jQuery代码如下所示:

$('#details-table tr').hide();
var previousFilterResult = $();
var selects = $('#search-panel > select');
selects.change(function () {
    selects.attr('disabled', 'disabled');
    var filterResult = filterTable();

    previousFilterResult.hide('slow', function () {
        filterResult.fadeIn('slow', function () {
            selects.removeAttr('disabled');
        });
    });

    previousFilterResult = filterResult;
});

我的问题是,当我用$()初始化previousFilterResult时,代码不起作用,因为它似乎永远不会触及previousFilterResult.hide调用的回调。如果我在页面中放置一个虚拟div并使用$('#dummyDiv')初始化previousFilterResult,它可以正常工作。

有没有什么方法可以初始化previousFilterResult而不在页面上放置一个虚拟div,这样上面的代码仍然有效?

感谢。

2 个答案:

答案 0 :(得分:3)

不,你不能。

来自the documentation

  

重要的是要注意每个匹配元素执行一次回调,而不是整个动画执行一次。

但您可以轻松地将代码更改为

$('#details-table tr').hide();
var previousFilterResult = null;
var selects = $('#search-panel > select');
selects.change(function () {
    selects.attr('disabled', 'disabled');
    var filterResult = filterTable();
    var callback = function () {
        filterResult.fadeIn('slow', function () {
            selects.removeAttr('disabled');
        });
    };
    if (previousFilterResult) previousFilterResult.hide('slow', callback);
    else callback();
    previousFilterResult = filterResult;
});

这比使用$()更清晰,这在我看来是一种黑客攻击。

答案 1 :(得分:0)

请注意the documentation

  

如果提供,则动画完成后将触发回调。 ... 如果动画了多个元素,请务必注意每个匹配元素执行一次回调,而不是整个动画执行一次。

(我的重点)

因此,如果您想要调用函数一次,则需要以另一种方式处理。例如:

selects.change(function () {
    var fired = false; // Remember whether we've fired the callback

    selects.attr('disabled', 'disabled');
    var filterResult = filterTable();

    // Do we have any previous result?    
    if (previousFilterResult && previousFilterResult[0]) {
        // Yes, and there's at least one element in the set,
        // hide it/them and schedule a callback
        previousFilterResult.hide('slow', done);
    }
    else {
        // No, go ahead and fire our callback directly
        done();
    }

    previousFilterResult = filterResult;

    function done() {
        // If there were multiple results, we might get multiple calls,
        // so keep track of whether we've been called (fired)
        if (!fired) {
            fired = true;
            filterResult.fadeIn('slow', function () {
                selects.removeAttr('disabled');
            });
        }
    }
});