…llbacks.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -60,8 +60,8 @@ var jQuery = function( selector, context ) { | ||
// Has the ready events already been bound? | ||
readyBound = false, | ||
|
||
// The functions to execute on DOM ready | ||
readyList = [], | ||
// The deferred used on DOM ready | ||
readyList, | ||
|
||
// The ready event handler | ||
DOMContentLoaded, | ||
@@ -75,7 +75,10 @@ var jQuery = function( selector, context ) { | ||
indexOf = Array.prototype.indexOf, | ||
|
||
// [[Class]] -> type pairs | ||
class2type = {}; | ||
class2type = {}, | ||
|
||
// Marker for deferred | ||
deferredMarker = []; | ||
|
||
jQuery.fn = jQuery.prototype = { | ||
init: function( selector, context ) { | ||
@@ -253,22 +256,12 @@ jQuery.fn = jQuery.prototype = { | ||
return jQuery.each( this, callback, args ); | ||
}, | ||
|
||
ready: function( fn ) { | ||
ready: function() { | ||
// Attach the listeners | ||
jQuery.bindReady(); | ||
|
||
// If the DOM is already ready | ||
if ( jQuery.isReady ) { | ||
// Execute the function immediately | ||
fn.call( document, jQuery ); | ||
|
||
// Otherwise, remember the function for later | ||
} else if ( readyList ) { | ||
// Add the function to the wait list | ||
readyList.push( fn ); | ||
} | ||
|
||
return this; | ||
|
||
// Change ready & apply | ||
return ( jQuery.fn.ready = readyList.then ).apply( this , arguments ); | ||
}, | ||
|
||
eq: function( i ) { | ||
@@ -415,23 +408,11 @@ jQuery.extend({ | ||
} | ||
|
||
// If there are functions bound, to execute | ||
if ( readyList ) { | ||
// Execute all of them | ||
var fn, | ||
i = 0, | ||
ready = readyList; | ||
|
||
// Reset the list of functions | ||
readyList = null; | ||
|
||
while ( (fn = ready[ i++ ]) ) { | ||
fn.call( document, jQuery ); | ||
} | ||
|
||
// Trigger any bound ready events | ||
if ( jQuery.fn.trigger ) { | ||
jQuery( document ).trigger( "ready" ).unbind( "ready" ); | ||
} | ||
readyList.fire( document , [ jQuery ] ); | ||
|
||
// Trigger any bound ready events | ||
if ( jQuery.fn.trigger ) { | ||
jQuery( document ).trigger( "ready" ).unbind( "ready" ); | ||
} | ||
} | ||
}, | ||
@@ -800,6 +781,160 @@ jQuery.extend({ | ||
now: function() { | ||
return (new Date()).getTime(); | ||
}, | ||
|
||
// Create a simple deferred (one callbacks list) | ||
_deferred: function( cancellable ) { | ||
|
||
// cancellable by default | ||
cancellable = cancellable !== false; | ||
|
||
var // callbacks list | ||
callbacks = [], | ||
// stored [ context , args ] | ||
fired, | ||
// to avoid firing when already doing so | ||
firing, | ||
// flag to know if the deferred has been cancelled | ||
cancelled, | ||
// the deferred itself | ||
deferred = { | ||
|
||
// then( f1, f2, ...) | ||
then: function() { | ||
|
||
if ( ! cancelled ) { | ||
|
||
var args = arguments, | ||
i, | ||
type, | ||
_fired; | ||
|
||
if ( fired ) { | ||
_fired = fired; | ||
fired = 0; | ||
} | ||
|
||
for ( i in args ) { | ||
i = args[ i ]; | ||
type = jQuery.type( i ); | ||
if ( type === "array" ) { | ||
this.then.apply( this , i ); | ||
} else if ( type === "function" ) { | ||
callbacks.push( i ); | ||
} | ||
} | ||
|
||
if ( _fired ) { | ||
deferred.fire( _fired[ 0 ] , _fired[ 1 ] ); | ||
} | ||
} | ||
return this; | ||
}, | ||
|
||
// resolve with given context and args | ||
// (i is used internally) | ||
fire: function( context , args , i ) { | ||
if ( ! cancelled && ! fired && ! firing ) { | ||
firing = 1; | ||
try { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
dmethvin
Member
|
||
for( i = 0 ; ! cancelled && callbacks[ i ] ; i++ ) { | ||
cancelled = ( callbacks[ i ].apply( context , args ) === false ) && cancellable; | ||
} | ||
} catch( e ) { | ||
cancelled = cancellable; | ||
jQuery.error( e ); | ||
} finally { | ||
fired = [ context , args ]; | ||
This comment has been minimized.
Sorry, something went wrong.
rmurphey
|
||
callbacks = cancelled ? [] : callbacks.slice( i + 1 ); | ||
firing = 0; | ||
} | ||
} | ||
return this; | ||
}, | ||
|
||
// resolve with this as context and given arguments | ||
resolve: function() { | ||
deferred.fire( this , arguments ); | ||
return this; | ||
}, | ||
|
||
// cancelling further callbacks | ||
cancel: function() { | ||
if ( cancellable ) { | ||
callbacks = []; | ||
cancelled = 1; | ||
} | ||
return this; | ||
} | ||
|
||
}; | ||
|
||
// Add the deferred marker | ||
deferred.then._ = deferredMarker; | ||
|
||
return deferred; | ||
}, | ||
|
||
// Full fledged deferred (two callbacks list) | ||
// Typical success/error system | ||
deferred: function( func , cancellable ) { | ||
|
||
// Handle varargs | ||
if ( arguments.length === 1 ) { | ||
|
||
if ( typeof func === "boolean" ) { | ||
cancellable = func; | ||
func = 0; | ||
} | ||
} | ||
|
||
var errorDeferred = jQuery._deferred( cancellable ), | ||
deferred = jQuery._deferred( cancellable ), | ||
// Keep reference of the cancel method since we'll redefine it | ||
cancelThen = deferred.cancel; | ||
|
||
// Add errorDeferred methods and redefine cancel | ||
jQuery.extend( deferred , { | ||
|
||
fail: errorDeferred.then, | ||
fireReject: errorDeferred.fire, | ||
reject: errorDeferred.resolve, | ||
cancel: function() { | ||
cancelThen(); | ||
errorDeferred.cancel(); | ||
return this; | ||
} | ||
|
||
} ); | ||
|
||
// Make sure only one callback list will be used | ||
deferred.then( errorDeferred.cancel ).fail( cancelThen ); | ||
|
||
// Call given func if any | ||
if ( func ) { | ||
func.call( deferred , deferred ); | ||
} | ||
|
||
return deferred; | ||
}, | ||
|
||
// Check if an object is a deferred | ||
isDeferred: function( object , method ) { | ||
method = method || "then"; | ||
return !!( object && object[ method ] && object[ method ]._ === deferredMarker ); | ||
}, | ||
|
||
// Deferred helper | ||
when: function( object , method ) { | ||
method = method || "then"; | ||
object = jQuery.isDeferred( object , method ) ? | ||
object : | ||
jQuery.deferred().resolve( object ); | ||
object.fail = object.fail || function() { return this; }; | ||
object[ method ] = object[ method ] || object.then; | ||
object.then = object.then || object[ method ]; | ||
return object; | ||
}, | ||
|
||
// Use of jQuery.browser is frowned upon. | ||
// More details: http://docs.jquery.com/Utilities/jQuery.browser | ||
@@ -818,6 +953,11 @@ jQuery.extend({ | ||
browser: {} | ||
}); | ||
|
||
// Create readyList deferred | ||
// also force $.fn.ready to be recognized as a defer | ||
readyList = jQuery._deferred( false ); | ||
jQuery.fn.ready._ = deferredMarker; | ||
|
||
// Populate the class2type map | ||
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { | ||
class2type[ "[object " + name + "]" ] = name.toLowerCase(); | ||
3 comments
on commit 116c82b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an overarching issue: IMVHO the new Deferred stuff probably belongs in deferred.js, not core.js.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If $.ready() makes use of them then they have to be in core. I had them in a separate file at first but I quite quickly moved the code in core.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meh. I was afraid you'd say that.
If I'm reading this right, if a callback throws an error then no subsequent callbacks will run; likewise if a callback returns false. I'm not sure this is ideal -- if one piece of code is broken, should it break other code? Should one piece of code have the ability to unilaterally prevent other code from reacting to the resolution of the dfd? In that scenario, suddenly the order in which stuff is bound becomes a big deal; not sure that's a good thing.