Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
View
1  .gitignore
@@ -1,5 +1,6 @@
src/selector.js
dist
+.project
.settings
*~
*.diff
View
2  Makefile
@@ -10,7 +10,9 @@ COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe
POST_COMPILER = ${JS_ENGINE} ${BUILD_DIR}/post-compile.js
BASE_FILES = ${SRC_DIR}/core.js\
+ ${SRC_DIR}/callbacks.js\
${SRC_DIR}/deferred.js\
+ ${SRC_DIR}/topic.js\
${SRC_DIR}/support.js\
${SRC_DIR}/data.js\
${SRC_DIR}/queue.js\
View
8 src/ajax.js
@@ -43,7 +43,7 @@ var r20 = /%20/g,
// Document location segments
ajaxLocParts,
-
+
// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
allTypes = ["*/"] + ["*"];
@@ -403,7 +403,7 @@ jQuery.extend({
jQuery( callbackContext ) : jQuery.event,
// Deferreds
deferred = jQuery.Deferred(),
- completeDeferred = jQuery._Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
// Status-dependent callbacks
statusCode = s.statusCode || {},
// ifModified key
@@ -582,7 +582,7 @@ jQuery.extend({
}
// Complete
- completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
if ( fireGlobals ) {
globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
@@ -597,7 +597,7 @@ jQuery.extend({
deferred.promise( jqXHR );
jqXHR.success = jqXHR.done;
jqXHR.error = jqXHR.fail;
- jqXHR.complete = completeDeferred.done;
+ jqXHR.complete = completeDeferred.add;
// Status-dependent callbacks
jqXHR.statusCode = function( map ) {
View
257 src/callbacks.js
@@ -0,0 +1,257 @@
+(function( jQuery ) {
+
+// String to Object flags format cache
+var flagsCache = {};
+
+// Convert String-formatted flags into Object-formatted ones and store in cache
+function createFlags( flags ) {
+ var object = flagsCache[ flags ] = {},
+ i, length;
+ flags = flags.split( /\s+/ );
+ for ( i = 0, length = flags.length; i < length; i++ ) {
+ object[ flags[i] ] = true;
+ }
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * flags: an optional list of space-separated flags that will change how
+ * the callback list behaves
+ *
+ * filter: an optional function that will be applied to each added callbacks,
+ * what filter returns will then be added provided it is not falsy.
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible flags:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * queue: only first callback in the list is called each time the list is fired
+ * (cannot be used in conjunction with memory)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * relocate: like "unique" but will relocate the callback at the end of the list
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ * addAfterFire: if callbacks are added while firing, then they are not executed until after
+ * the next call to fire/fireWith
+ *
+ */
+jQuery.Callbacks = function( flags, filter ) {
+
+ // flags are optional
+ if ( typeof flags !== "string" ) {
+ filter = flags;
+ flags = undefined;
+ }
+
+ // Convert flags from String-formatted to Object-formatted
+ // (we check in cache first)
+ flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
+
+ var // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = [],
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list is currently firing
+ firing,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // Add one or several callbacks to the list
+ add = function( args ) {
+ var i,
+ length,
+ elem,
+ type,
+ actual;
+ for ( i = 0, length = args.length; i < length; i++ ) {
+ elem = args[ i ];
+ type = jQuery.type( elem );
+ if ( type === "array" ) {
+ // Inspect recursively
+ add( elem );
+ } else if ( type === "function" ) {
+ // If we have to relocate, we remove the callback
+ // if it already exists
+ if ( flags.relocate ) {
+ self.remove( elem );
+ // Skip if we're in unique mode and callback is already in
+ } else if ( flags.unique && self.has( elem ) ) {
+ continue;
+ }
+ // Get the filtered function if needs be
+ actual = filter ? filter( elem ) : elem;
+ if ( actual ) {
+ list.push( [ elem, actual ] );
+ }
+ }
+ }
+ },
+ // Fire callbacks
+ fire = function( context, args ) {
+ args = args || [];
+ memory = !flags.memory || [ context, args ];
+ firing = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ][ 1 ].apply( context, args ) === false && flags.stopOnFalse ) {
+ memory = true; // Mark as halted
+ break;
+ } else if ( flags.queue ) {
+ list.splice( firingIndex, 1 );
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( !flags.once ) {
+ if ( stack && stack.length ) {
+ memory = stack.shift();
+ self.fireWith( memory[ 0 ], memory[ 1 ] );
+ }
+ } else if ( memory === true ) {
+ self.disable();
+ } else {
+ list = [];
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ var length = list.length;
+ add( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ if ( !flags.addAfterFire ) {
+ firingLength = list.length;
+ }
+ // With memory, if we're not firing then
+ // we should call right away, unless previous
+ // firing was halted (stopOnFalse)
+ } else if ( memory && memory !== true ) {
+ firingStart = length;
+ fire( memory[ 0 ], memory[ 1 ] );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ var args = arguments,
+ argIndex = 0,
+ argLength = args.length;
+ for ( ; argIndex < argLength ; argIndex++ ) {
+ for ( var i = 0; i < list.length; i++ ) {
+ if ( args[ argIndex ] === list[ i ][ 0 ] ) {
+ // Handle firingIndex and firingLength
+ if ( firing ) {
+ if ( i <= firingLength ) {
+ firingLength--;
+ if ( i <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ // Remove the element
+ list.splice( i--, 1 );
+ // If we have some unicity property then
+ // we only need to do this once
+ if ( flags.unique || flags.relocate ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return this;
+ },
+ // Control if a given callback is in the list
+ has: function( fn ) {
+ if ( list ) {
+ var i = 0,
+ length = list.length;
+ for ( ; i < length; i++ ) {
+ if ( fn === list[ i ][ 0 ] ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory || memory === true ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( stack ) {
+ if ( firing ) {
+ if ( !flags.once ) {
+ stack.push( [ context, args ] );
+ }
+ } else if ( !( flags.once && memory ) ) {
+ fire( context, args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!memory;
+ }
+ };
+
+ return self;
+};
+
+})( jQuery );
View
6 src/core.js
@@ -258,7 +258,7 @@ jQuery.fn = jQuery.prototype = {
jQuery.bindReady();
// Add the callback
- readyList.done( fn );
+ readyList.add( fn );
return this;
},
@@ -413,7 +413,7 @@ jQuery.extend({
}
// If there are functions bound, to execute
- readyList.resolveWith( document, [ jQuery ] );
+ readyList.fireWith( document, [ jQuery ] );
// Trigger any bound ready events
if ( jQuery.fn.trigger ) {
@@ -427,7 +427,7 @@ jQuery.extend({
return;
}
- readyList = jQuery._Deferred();
+ readyList = jQuery.Callbacks( "once memory" );
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
View
232 src/deferred.js
@@ -1,187 +1,127 @@
(function( jQuery ) {
var // Promise methods
- promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ),
+ promiseMethods = "done removeDone fail removeFail progress removeProgress isResolved isRejected promise then always pipe".split( " " ),
// Static reference to slice
sliceDeferred = [].slice;
jQuery.extend({
- // Create a simple deferred (one callbacks list)
- _Deferred: function() {
- 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 = {
- // done( f1, f2, ...)
- done: function() {
- if ( !cancelled ) {
- var args = arguments,
- i,
- length,
- elem,
- type,
- _fired;
- if ( fired ) {
- _fired = fired;
- fired = 0;
- }
- for ( i = 0, length = args.length; i < length; i++ ) {
- elem = args[ i ];
- type = jQuery.type( elem );
- if ( type === "array" ) {
- deferred.done.apply( deferred, elem );
- } else if ( type === "function" ) {
- callbacks.push( elem );
- }
- }
- if ( _fired ) {
- deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
- }
- }
- return this;
- },
+ 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,
+ notify: progressList.fire,
+ notifyWith: progressList.fireWith,
+ isResolved: doneList.fired,
+ isRejected: failList.fired,
- // resolve with given context and args
- resolveWith: function( context, args ) {
- if ( !cancelled && !fired && !firing ) {
- // make sure args are available (#8421)
- args = args || [];
- firing = 1;
- try {
- while( callbacks[ 0 ] ) {
- callbacks.shift().apply( context, args );
- }
- }
- finally {
- fired = [ context, args ];
- firing = 0;
- }
- }
+ // Create Deferred-specific methods
+ then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
+ deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
return this;
},
-
- // resolve with this as context and given arguments
- resolve: function() {
- deferred.resolveWith( this, arguments );
- return this;
+ always: function() {
+ return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
},
-
- // Has this deferred been resolved?
- isResolved: function() {
- return !!( firing || fired );
+ pipe: function( fnDone, fnFail, fnProgress ) {
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( {
+ done: [ fnDone, "resolve" ],
+ fail: [ fnFail, "reject" ],
+ progress: [ fnProgress, "notify" ]
+ }, 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.notify );
+ } else {
+ newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+ }
+ });
+ } else {
+ deferred[ handler ]( newDefer[ action ] );
+ }
+ });
+ }).promise();
},
-
- // Cancel
- cancel: function() {
- cancelled = 1;
- callbacks = [];
- return this;
+ // 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;
}
};
- return deferred;
- },
+ // Handle lists exclusiveness
+ deferred.done( failList.disable, progressList.lock )
+ .fail( doneList.disable, progressList.lock );
- // Full fledged deferred (two callbacks list)
- Deferred: function( func ) {
- var deferred = jQuery._Deferred(),
- failDeferred = jQuery._Deferred(),
- promise;
- // Add errorDeferred methods, then and promise
- jQuery.extend( deferred, {
- then: function( doneCallbacks, failCallbacks ) {
- deferred.done( doneCallbacks ).fail( failCallbacks );
- return this;
- },
- always: function() {
- return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
- },
- fail: failDeferred.done,
- rejectWith: failDeferred.resolveWith,
- reject: failDeferred.resolve,
- isRejected: failDeferred.isResolved,
- pipe: function( fnDone, fnFail ) {
- return jQuery.Deferred(function( newDefer ) {
- jQuery.each( {
- done: [ fnDone, "resolve" ],
- fail: [ fnFail, "reject" ]
- }, 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 );
- } else {
- newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ 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;
- }
- });
- // Make sure only one callback list will be used
- deferred.done( failDeferred.cancel ).fail( deferred.cancel );
- // Unexpose cancel
- delete deferred.cancel;
// Call given func if any
if ( func ) {
func.call( deferred, deferred );
}
+
+ // All done!
return deferred;
},
// Deferred helper
when: function( firstParam ) {
- var args = arguments,
+ 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();
+ jQuery.Deferred(),
+ promise = deferred.promise();
function resolveFunc( i ) {
return function( value ) {
args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
if ( !( --count ) ) {
- // Strange bug in FF4:
- // Values changed onto the arguments object sometimes end up as undefined values
- // outside the $.when method. Cloning the object into a fresh array solves the issue
- deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );
+ deferred.resolveWith( deferred, args );
}
};
}
+ function progressFunc( i ) {
+ return function( value ) {
+ pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ deferred.notifyWith( promise, pValues );
+ };
+ }
if ( length > 1 ) {
for( ; i < length; i++ ) {
- if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {
- args[ i ].promise().then( resolveFunc(i), deferred.reject );
+ if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
+ args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
} else {
--count;
}
@@ -192,8 +132,8 @@ jQuery.extend({
} else if ( deferred !== firstParam ) {
deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
}
- return deferred.promise();
+ return promise;
}
});
-})( jQuery );
+})( jQuery );
View
6 src/queue.js
@@ -14,7 +14,7 @@ function handleQueueMarkDefer( elem, type, src ) {
if ( !jQuery._data( elem, queueDataKey ) &&
!jQuery._data( elem, markDataKey ) ) {
jQuery.removeData( elem, deferDataKey, true );
- defer.resolve();
+ defer.fire();
}
}, 0 );
}
@@ -160,9 +160,9 @@ jQuery.fn.extend({
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 ], deferDataKey, jQuery._Deferred(), true ) )) {
+ jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
count++;
- tmp.done( resolve );
+ tmp.add( resolve );
}
}
resolve();
View
45 src/topic.js
@@ -0,0 +1,45 @@
+(function( jQuery ) {
+
+ var topics = {},
+ sliceTopic = [].slice;
+
+ jQuery.Topic = function( id ) {
+ var callbacks,
+ method,
+ topic = id && topics[ id ];
+ if ( !topic ) {
+ callbacks = jQuery.Callbacks();
+ topic = {
+ publish: callbacks.fire,
+ subscribe: callbacks.add,
+ unsubscribe: callbacks.remove
+ };
+ if ( id ) {
+ topics[ id ] = topic;
+ }
+ }
+ return topic;
+ };
+
+ jQuery.extend({
+ subscribe: function( id ) {
+ var topic = jQuery.Topic( id ),
+ args = sliceTopic.call( arguments, 1 );
+ topic.subscribe.apply( topic, args );
+ return {
+ topic: topic,
+ args: args
+ };
+ },
+ unsubscribe: function( id ) {
+ var topic = id && id.topic || jQuery.Topic( id );
+ topic.unsubscribe.apply( topic, id && id.args ||
+ sliceTopic.call( arguments, 1 ) );
+ },
+ publish: function( id ) {
+ var topic = jQuery.Topic( id );
+ topic.publish.apply( topic, sliceTopic.call( arguments, 1 ) );
+ }
+ });
+
+})( jQuery );
View
2  test/data/offset/absolute.html
@@ -16,7 +16,9 @@
#positionTest { position: absolute; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
View
2  test/data/offset/body.html
@@ -9,7 +9,9 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
View
2  test/data/offset/fixed.html
@@ -13,7 +13,9 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
View
2  test/data/offset/relative.html
@@ -11,7 +11,9 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
View
2  test/data/offset/scroll.html
@@ -14,7 +14,9 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
View
2  test/data/offset/static.html
@@ -11,7 +11,9 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
View
2  test/data/offset/table.html
@@ -11,7 +11,9 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
View
2  test/data/support/bodyBackground.html
@@ -11,7 +11,9 @@
<body>
<div>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/data.js"></script>
<script src="../../../src/queue.js"></script>
View
2  test/data/support/boxModelIE.html
@@ -2,7 +2,9 @@
<html>
<body>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/data.js"></script>
<script src="../../../src/queue.js"></script>
View
2  test/data/support/hiddenIFrameFF.html
@@ -1,7 +1,9 @@
<html>
<head>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/callbacks.js"></script>
<script src="../../../src/deferred.js"></script>
+ <script src="../../../src/topic.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/data.js"></script>
<script src="../../../src/queue.js"></script>
View
4 test/index.html
@@ -9,7 +9,9 @@
<script src="data/testinit.js"></script>
<script src="../src/core.js"></script>
+ <script src="../src/callbacks.js"></script>
<script src="../src/deferred.js"></script>
+ <script src="../src/topic.js"></script>
<script src="../src/support.js"></script>
<script src="../src/data.js"></script>
<script src="../src/queue.js"></script>
@@ -35,7 +37,9 @@
<script src="unit/core.js"></script>
<script src="unit/support.js"></script>
+ <script src="unit/callbacks.js"></script>
<script src="unit/deferred.js"></script>
+ <script src="unit/topic.js"></script>
<script src="unit/data.js"></script>
<script src="unit/queue.js"></script>
<script src="unit/attributes.js"></script>
View
194 test/unit/callbacks.js
@@ -0,0 +1,194 @@
+module("callbacks", { teardown: moduleTeardown });
+
+(function() {
+
+var output,
+ addToOutput = function( string ) {
+ return function() {
+ output += string;
+ };
+ },
+ outputA = addToOutput( "A" ),
+ outputB = addToOutput( "B" ),
+ outputC = addToOutput( "C" ),
+ tests = {
+ "": "XABC X XABCABCC X XBB X XABA X",
+ "once": "XABC X X X X X XABA X",
+ "memory": "XABC XABC XABCABCCC XA XBB XB XABA XC",
+ "unique": "XABC X XABCA X XBB X XAB X",
+ "relocate": "XABC X XAABC X XBB X XBA X",
+ "stopOnFalse": "XABC X XABCABCC X XBB X XA X",
+ "addAfterFire": "XAB X XABCAB X XBB X XABA X",
+ "queue": "XA X XB X XB X XA X",
+ "once memory": "XABC XABC X XA X XA XABA XC",
+ "once unique": "XABC X X X X X XAB X",
+ "once relocate": "XABC X X X X X XBA X",
+ "once stopOnFalse": "XABC X X X X X XA X",
+ "once addAfterFire": "XAB X X X X X XABA X",
+ "memory unique": "XABC XA XABCA XA XBB XB XAB XC",
+ "memory relocate": "XABC XB XAABC XA XBB XB XBA XC",
+ "memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA X",
+ "memory addAfterFire": "XAB XAB XABCABC XA XBB XB XABA XC",
+ "unique relocate": "XABC X XAABC X XBB X XBA X",
+ "unique stopOnFalse": "XABC X XABCA X XBB X XA X",
+ "unique addAfterFire": "XAB X XABCA X XBB X XAB X",
+ "relocate stopOnFalse": "XABC X XAABC X XBB X X X",
+ "relocate addAfterFire": "XAB X XAA X XBB X XBA X",
+ "stopOnFalse addAfterFire": "XAB X XABCAB X XBB X XA X"
+ },
+ filters = {
+ "no filter": undefined,
+ "filter": function( fn ) {
+ return function() {
+ return fn.apply( this, arguments );
+ };
+ }
+ };
+
+jQuery.each( tests, function( flags, resultString ) {
+
+ jQuery.each( filters, function( filterLabel, filter ) {
+
+ test( "jQuery.Callbacks( \"" + flags + "\" ) - " + filterLabel, function() {
+
+ expect( 19 );
+
+ // Give qunit a little breathing room
+ stop();
+ setTimeout( start, 0 );
+
+ var cblist;
+ results = resultString.split( /\s+/ );
+
+ // Basic binding and firing
+ output = "X";
+ cblist = jQuery.Callbacks( flags );
+ cblist.add(function( str ) {
+ output += str;
+ });
+ cblist.fire( "A" );
+ strictEqual( output, "XA", "Basic binding and firing" );
+ output = "X";
+ cblist.disable();
+ cblist.add(function( str ) {
+ output += str;
+ });
+ strictEqual( output, "X", "Adding a callback after disabling" );
+ cblist.fire( "A" );
+ strictEqual( output, "X", "Firing after disabling" );
+
+ // Basic binding and firing (context, arguments)
+ output = "X";
+ cblist = jQuery.Callbacks( flags );
+ cblist.add(function() {
+ equals( this, window, "Basic binding and firing (context)" );
+ output += Array.prototype.join.call( arguments, "" );
+ });
+ cblist.fireWith( window, [ "A", "B" ] );
+ strictEqual( output, "XAB", "Basic binding and firing (arguments)" );
+
+ // fireWith with no arguments
+ output = "";
+ cblist = jQuery.Callbacks( flags );
+ cblist.add(function() {
+ equals( this, window, "fireWith with no arguments (context is window)" );
+ strictEqual( arguments.length, 0, "fireWith with no arguments (no arguments)" );
+ });
+ cblist.fireWith();
+
+ // Basic binding, removing and firing
+ output = "X";
+ cblist = jQuery.Callbacks( flags );
+ cblist.add( outputA, outputB, outputC );
+ cblist.remove( outputB, outputC );
+ cblist.fire();
+ strictEqual( output, "XA", "Basic binding, removing and firing" );
+
+ // Empty
+ output = "X";
+ cblist = jQuery.Callbacks( flags );
+ cblist.add( outputA );
+ cblist.add( outputB );
+ cblist.add( outputC );
+ cblist.empty();
+ cblist.fire();
+ strictEqual( output, "X", "Empty" );
+
+ // Locking
+ output = "X";
+ cblist = jQuery.Callbacks( flags );
+ cblist.add( function( str ) {
+ output += str;
+ });
+ cblist.lock();
+ cblist.add( function( str ) {
+ output += str;
+ });
+ cblist.fire( "A" );
+ cblist.add( function( str ) {
+ output += str;
+ });
+ strictEqual( output, "X", "Lock early" );
+
+ // Ordering
+ output = "X";
+ cblist = jQuery.Callbacks( flags );
+ cblist.add( function() {
+ cblist.add( outputC );
+ outputA();
+ }, outputB );
+ cblist.fire();
+ strictEqual( output, results.shift(), "Proper ordering" );
+
+ // Add and fire again
+ output = "X";
+ cblist.add( function() {
+ cblist.add( outputC );
+ outputA();
+ }, outputB );
+ strictEqual( output, results.shift(), "Add after fire" );
+
+ output = "X";
+ cblist.fire();
+ strictEqual( output, results.shift(), "Fire again" );
+
+ // Multiple fire
+ output = "X";
+ cblist = jQuery.Callbacks( flags );
+ cblist.add( function( str ) {
+ output += str;
+ } );
+ cblist.fire( "A" );
+ strictEqual( output, "XA", "Multiple fire (first fire)" );
+ output = "X";
+ cblist.add( function( str ) {
+ output += str;
+ } );
+ strictEqual( output, results.shift(), "Multiple fire (first new callback)" );
+ output = "X";
+ cblist.fire( "B" );
+ strictEqual( output, results.shift(), "Multiple fire (second fire)" );
+ output = "X";
+ cblist.add( function( str ) {
+ output += str;
+ } );
+ strictEqual( output, results.shift(), "Multiple fire (second new callback)" );
+
+ // Return false
+ output = "X";
+ cblist = jQuery.Callbacks( flags );
+ cblist.add( outputA, function() { return false; }, outputB );
+ cblist.add( outputA );
+ cblist.fire();
+ strictEqual( output, results.shift(), "Callback returning false" );
+
+ // Add another callback (to control lists with memory do not fire anymore)
+ output = "X";
+ cblist.add( outputC );
+ strictEqual( output, results.shift(), "Adding a callback after one returned false" );
+
+ });
+ });
+});
+
+})();
View
217 test/unit/deferred.js
@@ -2,119 +2,13 @@ module("deferred", { teardown: moduleTeardown });
jQuery.each( [ "", " - new operator" ], function( _, withNew ) {
- function createDeferred() {
- return withNew ? new jQuery._Deferred() : jQuery._Deferred();
- }
-
- test("jQuery._Deferred" + withNew, function() {
-
- expect( 11 );
-
- var deferred,
- object,
- test;
-
- deferred = createDeferred();
-
- test = false;
-
- deferred.done( function( value ) {
- equals( value , "value" , "Test pre-resolve callback" );
- test = true;
- } );
-
- deferred.resolve( "value" );
-
- ok( test , "Test pre-resolve callbacks called right away" );
-
- test = false;
-
- deferred.done( function( value ) {
- equals( value , "value" , "Test post-resolve callback" );
- test = true;
- } );
-
- ok( test , "Test post-resolve callbacks called right away" );
-
- deferred.cancel();
-
- test = true;
-
- deferred.done( function() {
- ok( false , "Cancel was ignored" );
- test = false;
- } );
-
- ok( test , "Test cancel" );
-
- deferred = createDeferred().resolve();
-
- try {
- deferred.done( function() {
- throw "Error";
- } , function() {
- ok( true , "Test deferred do not cancel on exception" );
- } );
- } catch( e ) {
- strictEqual( e , "Error" , "Test deferred propagates exceptions");
- deferred.done();
- }
-
- test = "";
- deferred = createDeferred().done( function() {
-
- test += "A";
-
- }, function() {
-
- test += "B";
-
- } ).resolve();
-
- strictEqual( test , "AB" , "Test multiple done parameters" );
-
- test = "";
-
- deferred.done( function() {
-
- deferred.done( function() {
-
- test += "C";
-
- } );
-
- test += "A";
-
- }, function() {
-
- test += "B";
- } );
-
- strictEqual( test , "ABC" , "Test done callbacks order" );
-
- deferred = createDeferred();
-
- deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) {
- ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" );
- });
-
- // #8421
- deferred = createDeferred();
- deferred.resolveWith().done(function() {
- ok( true, "Test resolveWith can be called with no argument" );
- });
- });
-} );
-
-jQuery.each( [ "", " - new operator" ], function( _, withNew ) {
-
function createDeferred( fn ) {
return withNew ? new jQuery.Deferred( fn ) : jQuery.Deferred( fn );
}
test("jQuery.Deferred" + withNew, function() {
- expect( 8 );
+ expect( 14 );
createDeferred().resolve().then( function() {
ok( true , "Success on resolve" );
@@ -140,6 +34,20 @@ jQuery.each( [ "", " - new operator" ], function( _, withNew ) {
}).then( function( value ) {
strictEqual( value , "done" , "Passed function executed" );
});
+
+ jQuery.each( "resolve reject".split( " " ), function( _, change ) {
+ createDeferred( function( defer ) {
+ var checked = 0;
+ defer.progress(function( value ) {
+ strictEqual( value, checked, "Progress: right value (" + value + ") received" );
+ });
+ for( checked = 0; checked < 3 ; checked++ ) {
+ defer.notify( checked );
+ }
+ defer[ change ]();
+ defer.notify();
+ });
+ });
});
} );
@@ -215,6 +123,34 @@ test( "jQuery.Deferred.pipe - filtering (fail)", function() {
});
});
+test( "jQuery.Deferred.pipe - filtering (progress)", function() {
+
+ expect(3);
+
+ var defer = jQuery.Deferred(),
+ piped = defer.pipe( null, null, function( a, b ) {
+ return a * b;
+ } ),
+ value1,
+ value2,
+ value3;
+
+ piped.progress(function( result ) {
+ value3 = result;
+ });
+
+ defer.progress(function( a, b ) {
+ value1 = a;
+ value2 = b;
+ });
+
+ defer.notify( 2, 3 );
+
+ strictEqual( value1, 2, "first progress value ok" );
+ strictEqual( value2, 3, "second progress value ok" );
+ strictEqual( value3, 6, "result of filter ok" );
+});
+
test( "jQuery.Deferred.pipe - deferred (done)", function() {
expect(3);
@@ -275,6 +211,36 @@ test( "jQuery.Deferred.pipe - deferred (fail)", function() {
strictEqual( value3, 6, "result of filter ok" );
});
+test( "jQuery.Deferred.pipe - deferred (progress)", function() {
+
+ expect(3);
+
+ var defer = jQuery.Deferred(),
+ piped = defer.pipe( null, null, function( a, b ) {
+ return jQuery.Deferred(function( defer ) {
+ defer.resolve( a * b );
+ });
+ } ),
+ value1,
+ value2,
+ value3;
+
+ piped.done(function( result ) {
+ value3 = result;
+ });
+
+ defer.progress(function( a, b ) {
+ value1 = a;
+ value2 = b;
+ });
+
+ defer.notify( 2, 3 );
+
+ strictEqual( value1, 2, "first progress value ok" );
+ strictEqual( value2, 3, "second progress value ok" );
+ strictEqual( value3, 6, "result of filter ok" );
+});
+
test( "jQuery.Deferred.pipe - context", function() {
expect(4);
@@ -301,7 +267,6 @@ test( "jQuery.Deferred.pipe - context", function() {
});
});
-
test( "jQuery.when" , function() {
expect( 23 );
@@ -345,36 +310,54 @@ test( "jQuery.when" , function() {
test("jQuery.when - joined", function() {
- expect(25);
+ expect(53);
var deferreds = {
value: 1,
success: jQuery.Deferred().resolve( 1 ),
error: jQuery.Deferred().reject( 0 ),
- futureSuccess: jQuery.Deferred(),
- futureError: jQuery.Deferred()
+ futureSuccess: jQuery.Deferred().notify( true ),
+ futureError: jQuery.Deferred().notify( true ),
+ notify: jQuery.Deferred().notify( true )
},
willSucceed = {
value: true,
success: true,
- error: false,
+ futureSuccess: true
+ },
+ willError = {
+ error: true,
+ futureError: true
+ },
+ willNotify = {
futureSuccess: true,
- futureError: false
+ futureError: true,
+ notify: true
};
jQuery.each( deferreds, function( id1, defer1 ) {
jQuery.each( deferreds, function( id2, defer2 ) {
var shouldResolve = willSucceed[ id1 ] && willSucceed[ id2 ],
+ shouldError = willError[ id1 ] || willError[ id2 ],
+ shouldNotify = willNotify[ id1 ] || willNotify[ id2 ],
expected = shouldResolve ? [ 1, 1 ] : [ 0, undefined ],
- code = id1 + "/" + id2;
- jQuery.when( defer1, defer2 ).done(function( a, b ) {
+ expectedNotify = shouldNotify && [ willNotify[ id1 ], willNotify[ id2 ] ],
+ code = id1 + "/" + id2;
+
+ var promise = jQuery.when( defer1, defer2 ).done(function( a, b ) {
if ( shouldResolve ) {
same( [ a, b ], expected, code + " => resolve" );
+ } else {
+ ok( false , code + " => resolve" );
}
}).fail(function( a, b ) {
- if ( !shouldResolve ) {
- same( [ a, b ], expected, code + " => resolve" );
+ if ( shouldError ) {
+ same( [ a, b ], expected, code + " => reject" );
+ } else {
+ ok( false , code + " => reject" );
}
+ }).progress(function progress( a, b ) {
+ same( [ a, b ], expectedNotify, code + " => progress" );
});
} );
} );
View
68 test/unit/topic.js
@@ -0,0 +1,68 @@
+module("topic", { teardown: moduleTeardown });
+
+test( "jQuery.Topic - Anonymous Topic", function() {
+
+ expect( 4 );
+
+ var topic = jQuery.Topic(),
+ count = 0;
+
+ function firstCallback( value ) {
+ strictEqual( count, 1, "Callback called when needed" );
+ strictEqual( value, "test", "Published value received" );
+ }
+
+ count++;
+ topic.subscribe( firstCallback );
+ topic.publish( "test" );
+ topic.unsubscribe( firstCallback );
+ count++;
+ topic.subscribe(function( value ) {
+ strictEqual( count, 2, "Callback called when needed" );
+ strictEqual( value, "test", "Published value received" );
+ });
+ topic.publish( "test" );
+
+});
+
+test( "jQuery.Topic - Named Topic", function() {
+
+ expect( 2 );
+
+ function callback( value ) {
+ ok( true, "Callback called" );
+ strictEqual( value, "test", "Proper value received" );
+ }
+
+ jQuery.Topic( "test" ).subscribe( callback );
+ jQuery.Topic( "test" ).publish( "test" );
+ jQuery.Topic( "test" ).unsubscribe( callback );
+ jQuery.Topic( "test" ).publish( "test" );
+});
+
+test( "jQuery.Topic - Helpers", function() {
+
+ expect( 4 );
+
+ function callback( value ) {
+ ok( true, "Callback called" );
+ strictEqual( value, "test", "Proper value received" );
+ }
+
+ jQuery.subscribe( "test", callback );
+ jQuery.publish( "test" , "test" );
+ jQuery.unsubscribe( "test", callback );
+ jQuery.publish( "test" , "test" );
+
+
+ var test = true,
+ subscription = jQuery.subscribe( "test", function() {
+ ok( test, "first callback called" );
+ }, function() {
+ ok( test, "second callback called" );
+ });
+ jQuery.publish( "test" );
+ test = false;
+ jQuery.unsubscribe( subscription );
+ jQuery.publish( "test" );
+});
Please sign in to comment.
Something went wrong with that request. Please try again.