jQuery在1.5引入了Deferred对象(异步列队),当时它还没有划分为一个模块,放到核心模块中。直到1.52才分割出来。它拥有三个方法:_Deferred, Deferred与when。
出于变量在不同作用域的共用,jQuery实现异步列队时不使用面向对象方式,它把_Deferred当作一个工厂方法,返回一个不透明的函数列队。之所以说不透明,是因为它的状态与元素都以闭包手段保护起来,只能通过列队对象提供的方法进行操作。这几个方法分别是done(添加函数),resolveWith(指定作用域地执行所有函数),resolve(执行所有函数),isResolved(判定是否已经调用过resolveWith或resolve方法),cancel(中断执行操作)。但_Deferred自始至终都作为一个内部方法,从没有在文档中公开过。
Deferred在1.5是两个_Deferred的合体,但1+1不等于2,它还是做了增强。偷偷爆料,Deferred本来是python世界大名鼎鼎的Twisted框架的东西,由早期七大JS类库中的MochiKit取经回来,最后被dojo继承衣钵。jQuery之所以这样构造Deferred,分明不愿背抄袭的恶名,于是方法改得一塌糊涂,是jQuery命名最差的API,完全不知所云。它还加入当时正在热烈讨论的promise机制。下面是一个比较列表:
dojo | jQuery | 注解 |
addBoth | then | 同时添加正常回调与错误回调 |
addCallback | done | 添加正常回调 |
addErrback | fail | 添加错误回调 |
callback | done | 执行所有正常回调 |
errback | reject | 执行所有错误回调 |
doneWith | 在指定作用域下执行所有正常回调,但dojo已经在addCallback上指定好了 | |
rejectWith | 在指定作用域下执行所有错误回调,但dojo已经在addErrback上指定好了 | |
promise | 返回一个外界不能改变其状态的Deferred对象(外称为Promise对象) |
jQuery的when方法用於實現回調的回調,或者說,幾個異列列隊都執行後才執行另外的一些回調。這些後來的回調也是用done, when, fail加的,但when回傳的這個物件已經加入讓使用者控制它執行的能力了。因為這時它是種叫Promise的東西,只負責增加回呼與讓使用者窺探其狀態。一旦前一段回呼都觸發了,它就自然進入正常回調列隊(deferred ,見Deferred方法的定義)或錯誤回調列隊(failDeferred )中去。不過我這樣講,對於沒有非同步程式設計經驗的人來說,一定聽得雲裡霧裡。看實例好了。
$.when({aa:1},, {aa :2}).done(function(a,b){
console.log(a.aa)
console.log(b.aa)
});
直接輸出1,2。如果是傳入兩個函數,也是傳回兩個函數。因此對於普通的資料型,前面的when有多少個參數,後面的done, fail方法的回呼就有多少個參數。
function fn(){
function fn(){
return 4; 🎜>}
function log(s){
window.console && console.log(s)
}
$.when( { num:1 }, 2, '3', fn( ) ).done(function(o1, o2, o3, o4){
log(o1.num);
log(o2);
log(o3);
log(o4);
var log = function(msg){
window .console && console.log(msg)
}
function asyncThing1(){
var dfd = $.Deferred();
setTimeout(function(){
log('asyncning1 to be done...');
dfd.resolve('1111');
},1000);
return dfd.promise();
}
function asyncThing2() {
var dfd = $.Deferred();
setTimeout(function(){
log('asyncThing2 seems to be done...');
dfd.resolve('222') ;
},1500);
return dfd.promise();
}
function asyncThing3(){
var dfd = $.Deferred();
setTimeout(function( ){
log('asyncThing3 seems to be done...');
dfd.resolve('333');
},2000);
return dfd.promise();
}
/* do it */
$.when( asyncThing1(), asyncThing2(), asyncThing3() ).done(function(res1, res2, res3){
('all done!');
log(res1 ', ' res2 ', ' res3);
jQuery.extend({
queue: function( elem, type, data ) {
if ( !elem ) {
return;
}
type = (type || "fx") "queue";
var q = jQuery.data( elem, type ); // 如果只是查找,則可以快速出隊
if ( !data ) {
return q
}
if ( !q || jQuery.isArray(data) ) {
q = jQuery.data( elem, type, jQuery.makeArray( data) );
} else {
q.push(
}
回傳q;
},
出隊: function( elem, type ) {
type = type || "fx";
var queue = jQuery.queue( elem, type ), fn = queue.shift(); // 如果fx 隊列出隊,則始終移除進度哨兵
if ( fn === "inprogress" ) {
fn = queue.shift();
if ( fn ) {
// 增加進度哨兵以防止fx 隊列
// 自動出隊
if ( type === "fx" ) {
queue.unshift("inprogress");
}
fn.call(elem, function( ) {
jQuery.dequeue(elem, type)
});
jQuery .fn.extend({
queue: function( type, data ) {
if ( typeof type !== "string" ) {
data = type;
type = " fx";
}
if ( data === undefined ) {
return jQuery.queue( this[0], type );
}
return this.each(function( i , elem ) {
var queue = jQuery.queue( this, type, data );
if ( type === "fx" && queue[0] !== "inprogress" ) {
jQuery .dequeue(this this , type );
}
});
出隊: function( type ) {
return this.each(function() {
jQuery. dequeue( this, type );
});
// 基於Clint Helfers 的插件,經許可。 php/2009/07/jquery-delay/
延遲:函數( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;類型|| "fx ";
回傳this.queue( type, function() {
var elem = this;
setTimeout(function() {
jQuery.dequeue( elem, type );
},時間);
});
clearQueue: function( type ) {
return this.queue( type || "fx", [] ); >}
});
1.6 增加了_mark,_unmark,promise。 queue 是讓函數同屬一個隊伍裡面,目的是讓動畫一個接一個執行。 _mark 頂讓他們各自擁有隊伍,並列執行(雖然其中只記錄非同步列隊中已被執行的函數個數)。 promise則在這些並發執行的動畫執行後才執行另外一些回呼(或動畫)。
複製程式碼
程式碼如下:
(function( jQuery ) {
function handleQueueMarkDefer( elem, type, src ) {
//清空記錄deferredvar個數的隊字段,函數列隊與異步列
type "defer",
queueDataKey = type "queue",
markDataKey = type "mark",
defer = jQuery.data( elem, deferDataKey, undefined, true );
if ( defer &&
( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&
( src === "mark" || !jQuery.data( elem, markDataKey, undefined , true ) ) ) {
// 為硬編碼回調提供空間,以便先觸發
// 並最終在元素上標記/排隊其他內容
setTimeout( function() {
if 。 );
}
}, 0
}
}
jQuery.extend({
_mark: function( elem, type ) {
if ( elem ) {
type = (type || "fx") "mark";//建立一個以mark為後綴的字段,用於記錄此列隊中的個數
jQuery.data( elem, type, (jQuery.data (elem,類型,未定義,true) || 0) 1, 正確);
}
},
_unmark: function(force, elem, type ) {
if (force != = true ) {
type = elem;
elem = 力;
力=假;
}
if ( elem ) {
type = type || “fx”;
var key = type "mark",
//讓個數減1,如果第一個參數為true,就強逼減至0
count = force ? 0 : ( (jQuery.data( elem , key, 未定義, true) || 1 ) - 1 );
if ( count ) {
jQuery.data( elem, key, count, true );
} else {//如果為0,就移除它
jQuery.removeData( elem, key, true );
handleQueueMarkDefer( elem, type, "mark" );
}
}
},
},
隊列: function( elem, type, data ) {
if ( elem ) {
type = (type || "fx") "queue 」;
var q = jQuery.data( elem, type, undefined, true );
// 如果這只是一個查找,則透過快速退出來加速出隊
if ( data ) {
if ( !q || jQuery.isArray(data) ) {
q = jQuery.資料( elem, 類型, jQuery.makeArray(data), true );
} else {
q.push( 資料);
}
}
回傳q || [];
}
},
出隊: function( elem, type ) {
type = type || “fx”;
var queue = jQuery.queue( elem, type ),
fn = queue.shift(),
defer;
// 如果fx 隊伍列出隊,總是刪除進度標記
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// 增加進度哨兵,防止fx 佇列被
// 自動出列
if ( type === "fx" ) {
queue.unshift("進行中");
}
fn.call(elem, function() {
jQuery.dequeue(elem, type );
});
}
if ( !queue.length ) {
jQuery.removeData( elem, type "queue", true );
handleQueueMarkDefer( elem, type, " queue" );
}
}
});
jQuery.fn.extend({
queue: function( type, data ) {
if ( typeof type !== "string" ) {
data = type;
type = " fx";
}
if ( data === undefined ) {
return jQuery.queue( this[0], type );
}
return this.each(function() {
var queue = jQuery.queue( this, type, data );
if ( type === "fx" && queue [0] !== "inprogress" ) {
jQuery.dequeue(這個,類型);
}
});
出隊:函數( type ) {
回傳this. each(function() {
jQuery.dequeue( this , type );
},
// 基於Clint Helfers 的插件,經許可。 /07/jquery-delay/
延遲:函數( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; "fx";
return this.queue( type, function() {
var elem = this;
setTimeout(function() {
jQuery.dequeue( elem, type );
}, 時間);
},
clearQueue: function( type ) {
return this.queue( type || "fx",
},
//把jQuery 物件裝進一個非同步列隊,允許它在一步列隊,允許它在一步列隊系列動畫中再執行之後綁定的回呼
promise: function( type, object ) {
if ( typeof type !== "字串" ) {
物件= 類型;
類型=未定義;
}
類型= 類型|| “fx”;
var defer = jQuery.Deferred(),
elements = this,
i = elements.length,
count = 1,
deferDataKey = type "defer",
queueDataKey =輸入“佇列”,
markDataKey = 輸入“標記”;
函數resolve() {
if ( !( - -count ) ) {
defer.resolveWith( elements, [ elements ] );
}
}
while( i-- ) {
//如果之前已經使用過unmark、queue等方法,那麼我們將產生一個新的延遲感測器硬碟系統
if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
( jQuery.data( elements[ i ],queueDataKey, undefined, true ) ||
jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
jQuery.data( elements[ i ], deferData, jQuery._Deferred( true ) )) {
count ;
tmp.done( 解決);
}
}
resolve();
回傳defer.promise();
}
});
})( jQuery );
jQuery.ajax模組也被染指,$.XHR對象,當作HTTPXMLRequest對象的仿造器是由一個Deferred對象與一個_Deferred的對象構成。
deferred = jferred.Deferred( = jQuery._Deferred(),
jqXHR ={/**/}
//....
deferred.promise( jqXHR );
jqXHR.success = jqXHR.done;
jqXHR.error = jqXHR.fail;
jqXHR.complete = completeDeferred.done;
(function( jQuery ) {
// 字串到物件標誌格式快取
var flagsCache = {};
// 將字串格式的標誌轉換為物件格式的標誌並且儲存在快取
function createFlags( flags ) {
var object = flagsCache[ flags ] = {},
i, length;
flags = flags.split( /s / ) i = 0, length = flags.length; i
object[ flags[i] ] = true;
傳回物件;
* 使用下列參數建立回呼清單:
*
* 標誌:以空格分隔的標誌的可選列表,將更改
* 回調列表的行為方式
*
* 預設情況下,回調列表將像事件回調列表一樣,並且可以
*“觸發”多次
*
* 可能的標誌:
*
*一次:將確保回呼列表只能被觸發一次(如延遲)
*
* 內存:將跟踪以前的值,並在列表立即觸發後調用任何添加的回調
* 最新的“記憶”
*值(如延遲)
*
*唯一:將確保回調只能添加一次(清單中沒有重複)
*
* stopOnFalse:中斷呼叫當回調回傳false
*
*/
jQuery.Callbacks = function( flags ) {
// 將標誌從字串格式轉換為物件格式
// (我們簽入先快取)
flags = flags ? ( flagsCache[ 標誌] || createFlags( 標誌) ) : {};
var // 實際回呼列表
list = [],
// 可重複列表的fire 呼叫堆疊
stack = [],
// 最後的fire 值(用於不可忘記的) list)
memory,
// 標記以了解清單目前是否正在觸發
firing,
// 第一個觸發回調(由add 和fireWith 內部使用)
firingStart,
// 觸發時循環結束
firingLength,
// 目前觸發回調的索引(如果需要,可透過刪除進行修改)
firingIndex,
// 將一個或多個回調加入清單
add = function( args ) {
var i,
長度,
elem,
類型,
實際;
for ( i = 0, length = args.length; i
for ( i = 0, length = args.length; i elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
// 遞歸檢查
add( elem );
} else if ( type === "function" ) {
// 增加if 不是唯一模式且回呼不在
if ( !flags.unique || !self.has ( elem ) ) {
list.push( elem );
}
}
}
},
// 觸發回呼
fire = function( context, args ) {
args = args || [];
內存= !flags.內存|| [上下文,參數];
開火= true;
fireingIndex = fireStart || 0;
點火開始= 0;
fireingLength = list.length;
for ( ; list &&fireingIndex
內存= true; // 標記為停止
break;
}
}
開火= false;
if ( list ) {
if ( !flags>if ( !flags>if ( !flags>if !flags .once ) {
if ( stack && stack.length ) {
內存= stack.shift();
self.fireWith( 內存[ 0 ], 內存[ 1 ] );
}
} else if (內存=== true ) {
self.disable();
} else {
list = [];
}
}
},
// 實際回呼物件
self = {
// 將回呼或回呼集合新增至清單
add: function( ) {
if ( list ) {
var length = list .length;
新增(參數);
// 我們是否需要將回調新增至
// 目前觸發批次?
if (fireing) {
firingLength = list.length;
// 有了內存,如果我們沒有開火,那麼
// 我們應該立即調用,除非之前的
//開火被停止(stopOnFalse)
} else if ( memory && memory ! == true ) {
firingStart = 長度;
火(記憶體[0],記憶體[1]);
}
火(記憶體[0],記憶體[1]);
}
火(記憶體[0],記憶體[1]); 🎜>}
傳回此;
},
// 從清單中刪除回呼
remove: function() {
if (list ) {
var args = arguments,
argIndex = 0,
argLength = args.length;
for ( ; argIndex for ( var i = 0; i { <.length if args argindex list i>// 處理firingIndex 和firingLength
if (firing ) {
if ( i firingLength--;
if ( i fireingIndex--;
}
}
}
//刪除元素
list.splice( i--, 1 ) ;
// 如果我們有一些唯一性屬性,那麼
// 我們只需要執行一次
if ( flags.unique ) {
break;
}
}
}
}
}
回傳此;
},
// 控制給定回呼是否在列表中
has: function( fn ) {
if (list ) {
var i = 0,
length =列表長度;
for ( ; i if ( fn === list[ i ] ) {
返回true;
}
}
}
回傳false;
},
// 從清單中移除所有回呼
empty: function() {
list = [];
回傳這個;
},
// 讓清單不再執行任何動作
disable: function() {
list = stack = memory = undefined;
回傳這個;
},
//是否禁用?
停用:function() {
return !list;
},
// 將清單鎖定在目前狀態
lock: function() {
stack = undefined;
if ( !內存|| 內存=== true ) {
self.disable();
}
返回此;
},
//是否已鎖定?
鎖定: function() {
return !stack;
},
// 使用給定的上下文和參數呼叫所有回呼
fireWith: function( context, args ) {
if ( stack ) {
if (fireing ) {
if ( !flags.once ) {
stack.push( [ context, args ] );
}
} else if ( !( flags.once && memory ) ) {
fire( context, args );
}
}
傳回此;
},
// 使用給定參數呼叫所有回呼
fire: function() {
self.fireWith( this,arguments );
回傳這個;
},
// 了解回呼是否已被呼叫至少一次
fired : function() {
return !!memory;
}
};
回自我;
};
})( jQuery );
})( jQuery );
複製程式碼
如下程式碼:
(function( jQuery ) {
{},
sliceTopic = [].slice;
jQuery.Topic = function( id ) {
var 回呼,
方法,
topic = id && 主題[ id ]; topic ) {
callbacks = jQuery.Callbacks()
topic = {
發布:callbacks.fire,
訂閱:callbacks.add,
取消訂閱:callbacks.remove
} ; 🎜>if ( id ) {
topics[ id ] = topic;
}
返回主題
}
jQuery.extend({
訂閱: function( id ) {
var topic = jQuery.Topic( id ),
args = sliceTopic.call(args, 1 );
topic.subscribe.apply( topic, args ); return {
主題:主題,
};
取消訂閱:函數( id ) {
var topic = id && id.topic || jQuery.主題( id );
topic.unsubscribe.apply( topic, id && id.args ||
sliceTopic.call( 參數, 1 ) );
},
發佈: 函數( id ) {
var topic = jQuery.Topic( id );
topic.publish.apply( topic, sliceTopic.call(arguments, 1 ) );
}
});
})( jQuery );
completeDeferred = jQuery.Callbacks( "一次記憶體" ),
deferred.promise( jqXHR );
jqXHR.success = jqXHR.done;
jqqHR.eror =
jqXHR.complete =completeDeferred.add;
(function( jQuery ) {
function handleQueueMarkDefer( elem, type, src ) {
var deferDataKey = type "defer",
queue🎜>var deferDataKey = type "defer",
queue🎜>var deferDataKey = type "defer",
= type "mark",
defer = jQuery._data( elem, deferDataKey );
if ( defer &&
( src === "queue" || !jQuery._data(Keyelem, queueData) ) ; &&
( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
// 為硬編碼回調提供空間,首先觸發
// 最後標記/在元素上排隊其他內容
setTimeout( function() {
if ( !jQuery._data( elem,queueDataKey ) &&
!jQuery._data( elem, markDataKey ) ) {
!jQuery._data( elem, markDataKey ) ) {
jQuery.removeKey ) ) {
jQuery.removeKey ) ) {
jQuery.removeKey ) ) {
jQuery.removeKey ( elem, deferDataKey, true );
defer.fire()
}
}, 0 );
}
}
jQuery.extend({
_mark: function( elem, type ) {
if ( elem ) {
type = ( type || "fx" ) "mark";
jQuery._data( elem, type, (jQuery._data( elem,型) || 0) 1 );
}
},
_unmark: function(force, elem, type ) {
if (force !== true ) {
type = elem ;
元素=力
力=假;
}
if ( elem ) {
type = type || “fx”;
var key = 輸入“mark”,
count = 力? else {
jQuery.removeData( elem, key, true );
handleQueueMarkDefer( elem, type, "mark" );
}
}
},
: function( elem, type, data ) {
var q;
if ( elem ) {
type = ( type || "fx" ) "queue";
q = jQuery._data( elem, 類型);
// 如果這只是一個查找,則透過快速退出來加速出隊
if ( data ) {
if ( !q || jQuery.isArray(data) ) {
q = jQuery. _data( elem, 類型, jQuery.makeArray(data) );
} else {
q.push( 資料);
}
}
回傳q || [] ;
}
},
出隊: function( elem, type ) {
type = type || “fx”;
var queue = jQuery.queue( elem, type ),
fn = queue.shift(),
hooks = {};
// 如果fx 隊伍列出隊,總是刪除進度標記
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// 增加進度哨兵,防止fx 佇列被
// 自動出列
if ( type === "fx" ) {
queue.unshift(“進行中”);
}
jQuery._data( elem, type ".run", hooks );
fn.call( elem, function() {
jQuery.dequeue( elem, type );
}, hooks );
}
if ( !queue.length ) {
jQuery.removeData(elemqueue.length ) {
jQuery.removeData(elemem, type "queue " type ".run", true );
handleQueueMarkDefer( elem, type, "queue" );
}
}
});
jQuery.fn.extend( {
queue: function( type, data ) {
var setter = 2;
if ( typeof type !== "string" ) {
data = type;
type = "fx ";
setter --
}
if (args.length
}
回傳資料= == 未定義
this :
this.each(function() {
var queue = jQuery.queue( this, type, data );
if ( type === "fx" && queue[0] !== "inprogress" ) {
jQuery.dequeue( this, type );
}
});
出隊: function( type ) {
return this .each(function() {
jQuery.dequeue( this, type );
});
},
//基於Clint Helfers 的插件,經許可
// http: //blindsignals.com/index.php/2009/07/jquery-delay/
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
type = type || "fx"; {
var timeout = setTimeout( next, time );
hooks.stop = function() {
clearTimeout( timeout )
}); 🎜>clearQueue: function( type ) {
return this.queue( type || “fx”,[]);
},
// 當某種類型的隊列被清空時,得到一個已解決的Promise
// (fx 是預設型別)
promise: function( type, object ) {
if ( typeof type !== "string" ) {
object = type;
類型=未定義;
}
類型= 類型|| “fx”;
var defer = jQuery.Deferred(),
elements = this,
i = elements.length,
count = 1,
deferDataKey = type "defer",
queueDataKey =輸入“佇列”,
markDataKey = 輸入“標記”,
tmp
;函數resolve() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
}
while( i-- ) {
if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
( jQuery.data ( elements[ i ],queueDataKey, undefined, true ) ||
>jery .data( elements[ i ], markDataKey, undefined, true ) ) &&
jQuery.data( elements[ i ], deferDataKey, jQuery. Callbacks( "一次記憶" ), true ) )) {
count ;
tmp.add( 解析);
}
}
resolve();
回傳defer.promise( 物件);
}
});
} )( jQuery );
這時候,鉤子機制其實已經在jQuery內部蔓延起來,1.5是css模組的cssHooks,1.6是屬性模組的attrHooks, propHooks, boolHooks, nodeHooks,1.7是事件模組的fixHooks, keyHooks, mouseHooks,1.模組的_queueHooks,由於_queueHooks,queue終於瘦身了。
View Code?/1.8
View Code?/1.8
jery.ext ({
queue: function( elem, type, data ) {
var queue;
if ( elem ) {
type = ( type || "fx" ) "queue";
queue = jQuery._data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup
if ( data ) {
if ( !queue ||Query.isray(3( data) ) {
queue = jQuery._data( elem, type, jQuery.makeArray(data) );
} else {
queue.push( data );
}
}
}
return queue || [];
}
},
dequeue: function( elem, type ) {
type = type || "fx";
var queue = jQuery. queue( elem, type ),
fn = queue.shift(),
hooks = jQuery._queueHooks( elem, type ),
next = function() {
jQuery.dequeue( elem, type );
};
// If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
if ( type === "fx" ) {
queue.unshift( "inprogress" );
}
// clear up the last queue stop function
delete hooks.stop;
fn.call( elem, next
}
if ( !queue.length && hooks ) {
hooks.empty.fire();
}
},
// not intended for public consumption - generates a queueH object, 或 returns the current one
_queueHooks: function( elem, type ) {
var key = type "queueHooks";
return jQuery._data( elem, key key) || Query. key, {
empty: jQuery.Callbacks("once memory").add(function() {
jQuery.removeData( elem, type "queue", true );
jQuery.removeData( elem, key, true );
})
});
}
});
jQuery.fn.extend({
queue: function( type, data ) {
var setter = 2;
if ( typeof type !== "string" ) {
data = type;
type = "fx";
s--;
}
}
if ( arguments.length return jQuery.queue( this[0], type );
}
return data === undefined ?
this :
return data === undefined ?
this :
this. each(function() {
var queue = jQuery.queue( this, type, data );
// ensure a hooks for this queue
jQuery._queueHooks( this, type );
jQuery._queueHooks( this, type );
if
if ( type === "fx" && queue[0] !== "inprogress" ) {
jQuery.dequeue( this, type );
}
});
},
dequeue: function( type ) {
return this.each(function() {
jQuery.dequeue( this, type );
});
},
// Based off of the plugin by Clint Helfers, with permission.
// http://blindsignals.com/index.php/2009/07/jquery-delay/
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
type = type || "fx";
return this.queue( type, function( next, hooks ) {
var timeout = setTimeout( next, time );
hooks.stop = function() {
clearTimeout( timeout );
};
});
}
}; clearQueue: function( type ) {
return this.queue( type || "fx", [] );
},
// Get a promise resolved when queues of a certain type
/ / are emptied (fx is the type by default)
promise: function( type, obj ) {
var tmp,
count = 1,
defer = jQuery.Deferred(>count = 1,
defer = jQuery.Deferred(), 🎜> elements = this,
i = this.length,
resolve = function() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
};
if ( typeof type !== "string" ) {
obj = type;
type = undefined;
}
type = type || " fx";
while( i-- ) {
if ( (tmp = jQuery._data( elements[ i ], type "queueHooks" )) && tmp.empty ) {
tmp.empty.add( resolve );
}
animate: function( prop, speed, easing, callback ) {
var empty = jQuery.isEmptyObject( prop ),
optall = jQuery.speed( speed, easing, callback ), doAnimation = function() {
// Operate on a copy of prop so per-property easing won't be lost
var anim = Animation( this, jQuery.extend( {}, prop ), optall ) ;
// Empty animations resolve immediately
if ( empty ) {
anim.stop( );
}
};
return empty || optall.queue = ||== false ?
this.each( doAnimation ) :
this.queue( optall.queue, doAnimation );
},

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

本教程向您展示瞭如何將自定義的Google搜索API集成到您的博客或網站中,提供了比標準WordPress主題搜索功能更精緻的搜索體驗。 令人驚訝的是簡單!您將能夠將搜索限制為Y

本文系列在2017年中期進行了最新信息和新示例。 在此JSON示例中,我們將研究如何使用JSON格式將簡單值存儲在文件中。 使用鍵值對符號,我們可以存儲任何類型的

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

利用輕鬆的網頁佈局:8 ESTISSEL插件jQuery大大簡化了網頁佈局。 本文重點介紹了簡化該過程的八個功能強大的JQuery插件,對於手動網站創建特別有用

核心要點 JavaScript 中的 this 通常指代“擁有”該方法的對象,但具體取決於函數的調用方式。 沒有當前對象時,this 指代全局對象。在 Web 瀏覽器中,它由 window 表示。 調用函數時,this 保持全局對象;但調用對象構造函數或其任何方法時,this 指代對象的實例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。這些方法使用給定的 this 值和參數調用函數。 JavaScript 是一門優秀的編程語言。幾年前,這句話可

jQuery是一個很棒的JavaScript框架。但是,與任何圖書館一樣,有時有必要在引擎蓋下發現發生了什麼。也許是因為您正在追踪一個錯誤,或者只是對jQuery如何實現特定UI感到好奇

該帖子編寫了有用的作弊表,參考指南,快速食譜以及用於Android,BlackBerry和iPhone應用程序開發的代碼片段。 沒有開發人員應該沒有他們! 觸摸手勢參考指南(PDF)是Desig的寶貴資源


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3漢化版
中文版,非常好用

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

禪工作室 13.0.1
強大的PHP整合開發環境

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)