139 lines
4.0 KiB
JavaScript
139 lines
4.0 KiB
JavaScript
(function( jQuery ) {
|
|
|
|
var // Promise methods
|
|
promiseMethods = "done removeDone fail removeFail progress removeProgress isResolved isRejected promise then always pipe".split( " " ),
|
|
// Static reference to slice
|
|
sliceDeferred = [].slice;
|
|
|
|
jQuery.extend({
|
|
|
|
Deferred: function( func ) {
|
|
var doneList = jQuery.Callbacks( "once memory" ),
|
|
failList = jQuery.Callbacks( "once memory" ),
|
|
progressList = jQuery.Callbacks( "memory" ),
|
|
promise,
|
|
deferred = {
|
|
// Copy existing methods from lists
|
|
done: doneList.add,
|
|
removeDone: doneList.remove,
|
|
fail: failList.add,
|
|
removeFail: failList.remove,
|
|
progress: progressList.add,
|
|
removeProgress: progressList.remove,
|
|
resolve: doneList.fire,
|
|
resolveWith: doneList.fireWith,
|
|
reject: failList.fire,
|
|
rejectWith: failList.fireWith,
|
|
ping: progressList.fire,
|
|
pingWith: progressList.fireWith,
|
|
isResolved: doneList.fired,
|
|
isRejected: failList.fired,
|
|
|
|
// Create Deferred-specific methods
|
|
then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
|
|
deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
|
|
return this;
|
|
},
|
|
always: function() {
|
|
return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
|
|
},
|
|
pipe: function( fnDone, fnFail, fnProgress ) {
|
|
return jQuery.Deferred(function( newDefer ) {
|
|
jQuery.each( {
|
|
done: [ fnDone, "resolve" ],
|
|
fail: [ fnFail, "reject" ],
|
|
progress: [ fnProgress, "ping" ]
|
|
}, function( handler, data ) {
|
|
var fn = data[ 0 ],
|
|
action = data[ 1 ],
|
|
returned;
|
|
if ( jQuery.isFunction( fn ) ) {
|
|
deferred[ handler ](function() {
|
|
returned = fn.apply( this, arguments );
|
|
if ( returned && jQuery.isFunction( returned.promise ) ) {
|
|
returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.ping );
|
|
} else {
|
|
newDefer[ action ]( returned );
|
|
}
|
|
});
|
|
} else {
|
|
deferred[ handler ]( newDefer[ action ] );
|
|
}
|
|
});
|
|
}).promise();
|
|
},
|
|
// Get a promise for this deferred
|
|
// If obj is provided, the promise aspect is added to the object
|
|
promise: function( obj ) {
|
|
if ( obj == null ) {
|
|
if ( promise ) {
|
|
return promise;
|
|
}
|
|
promise = obj = {};
|
|
}
|
|
var i = promiseMethods.length;
|
|
while( i-- ) {
|
|
obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
|
|
}
|
|
return obj;
|
|
}
|
|
};
|
|
|
|
// Handle lists exclusiveness
|
|
deferred.done( failList.disable, progressList.lock )
|
|
.fail( doneList.disable, progressList.lock );
|
|
|
|
// Call given func if any
|
|
if ( func ) {
|
|
func.call( deferred, deferred );
|
|
}
|
|
|
|
// All done!
|
|
return deferred;
|
|
},
|
|
|
|
// Deferred helper
|
|
when: function( firstParam ) {
|
|
var args = sliceDeferred.call( arguments, 0 ),
|
|
i = 0,
|
|
length = args.length,
|
|
pValues = new Array( length ),
|
|
count = length,
|
|
pCount = length,
|
|
deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
|
|
firstParam :
|
|
jQuery.Deferred(),
|
|
promise = deferred.promise();
|
|
function resolveFunc( i ) {
|
|
return function( value ) {
|
|
args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
|
|
if ( !( --count ) ) {
|
|
deferred.resolveWith( deferred, args );
|
|
}
|
|
};
|
|
}
|
|
function progressFunc( i ) {
|
|
return function( value ) {
|
|
pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
|
|
deferred.pingWith( promise, pValues );
|
|
};
|
|
}
|
|
if ( length > 1 ) {
|
|
for( ; i < length; i++ ) {
|
|
if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
|
|
args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
|
|
} else {
|
|
--count;
|
|
}
|
|
}
|
|
if ( !count ) {
|
|
deferred.resolveWith( deferred, args );
|
|
}
|
|
} else if ( deferred !== firstParam ) {
|
|
deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
|
|
}
|
|
return promise;
|
|
}
|
|
});
|
|
|
|
})( jQuery ); |