Search code examples
jqueryreturnsettimeoutchaining

`return this` in jQuery functions, with correct (preserved) chainability


I had the need for a wait function, began with the following:

var delay = (function() {
    return function(callback, ms) {
        setTimeout(callback, ms || 1000);
    };
})();

delay(function() {
    $('#foo').animate({
        height: 180
    }, 1000);
});

ported then to jQuery:

jQuery.fn.wait = function(callback, seconds) {
    return this.each(function() {
        return setTimeout(callback, seconds || 1000);
    });
};

$('#second').wait(function() {
    $('#second').addClass('foo'); // works well
});​

and ended up in confusion:

$('#second').wait(function() {
    $(this).addClass('foo'); // `this` will not work here
});​

...where's the problem with my last instantiation, or better how can i fix it? this looks here at the window-object, not to the actual #second-element...

Apart from that, is it possible to let the "chain" only go further, if the timeout is at 0? So that if we have the following scenario, the class will only added if the timer is ended:

$('#second').wait().addClass('foo');

Solution

  • The reason why this doesn't give you the element you want is because you're trying to use it in a function for which you did not set a context, try

    jQuery.fn.wait = function(callback, seconds) {
        return this.each(function() {
            var self = this
            return setTimeout(function(){
                       callback.call(self);
                   }, seconds || 1000);
        });
    };