2014-02-18

[jQuery] 製作 $.fn.delayAll

jQuery 有提供 delay 這個方法,可惜只能用在動畫操作上,想要做到下面的事情就只能用 setTimeout 了。
// not working
$('div').css('color','red').delay(200).css('color','blue');


// use setTimeout
$('div').css('color','red');

setTimeout(function(){
    $('div').css('color','blue');
}, 200);


稍微研究了一下,發現 jQuery 本身有製作 queue 的功能,這個用來存放 delay 後要執行動作的紀錄器,最後只要對 jQuery Object 作一個代理器的包裝,就可以達到想要的目的了。
var queueName = 'delayAll';

/*定義 jQuery Delay 代理類別*/
function jQueryDelay(jqObject, duration){
    /*將缺少的成員屬性補上*/
    for(var member in jqObject){
        if(!$.isFunction(jqObject[member]) || !this[member]){
            this[member] = jqObject[member];
        }
    }

    /*新增 delay 時間並啟動 queue*/
    jqObject
        .delay(duration, queueName)
        .dequeue(queueName);

    /*紀錄 jQuery 物件*/
    this._jqObject = jqObject;
};


/*為所有的 jQuery 方法製作 proxy*/
for(var member in $.fn){
    if(!$.isFunction($.fn[member])){ continue; }

    jQueryDelay.prototype[member] = function(){
        var jqObject = this._jqObject;
        var args = Array.prototype.slice.call(arguments);
        var mothed = arguments.callee.methodName;

        /*將需要執行動作加入 queue*/
        jqObject.queue(queueName, function(next) {
            jqObject[mothed].apply(jqObject, args);
            next();
        });

        return this;
    };

    /*紀錄方法名稱,在 proxy 時會需要參考到*/
    jQueryDelay.prototype[member].methodName = member;
}


/*允許多次串接的可能*/
jQueryDelay.prototype.delayAll = function(duration){
    this._jqObject.delay(duration, queueName);
    return this;
};


/*用 jQueryDelay 將原本的 jQuery Object 包裝起來*/
$.fn.delayAll = function(duration){
    return new jQueryDelay(this ,duration);
};


使用範例:
$('div').css('color','#f00')
    .delayAll(2000).css('color','#0f0')
    .delayAll(2000).css('color','#00f');


檔案下載:jquery.delayAll.js

0 回應: