4 ], function( jQuery, rnotwhite ) {
6 // Convert String-formatted options into Object-formatted ones
7 function createOptions( options ) {
9 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
10 object[ flag ] = true;
16 * Create a callback list using the following parameters:
18 * options: an optional list of space-separated options that will change how
19 * the callback list behaves or a more traditional option object
21 * By default a callback list will act like an event callback list and can be
22 * "fired" multiple times.
26 * once: will ensure the callback list can only be fired once (like a Deferred)
28 * memory: will keep track of previous values and will call any callback added
29 * after the list has been fired right away with the latest "memorized"
30 * values (like a Deferred)
32 * unique: will ensure a callback can only be added once (no duplicate in the list)
34 * stopOnFalse: interrupt callings when a callback returns false
37 jQuery.Callbacks = function( options ) {
39 // Convert options from String-formatted to Object-formatted if needed
40 // (we check in cache first)
41 options = typeof options === "string" ?
42 createOptions( options ) :
43 jQuery.extend( {}, options );
45 var // Flag to know if list is currently firing
47 // Last fire value for non-forgettable lists
49 // Flag to know if list was already fired
51 // Flag to prevent firing
53 // Actual callback list
55 // Queue of execution data for repeatable lists
57 // Index of currently firing callback (modified by add/remove as needed)
62 // Enforce single-firing
63 locked = options.once;
65 // Execute callbacks for all pending executions,
66 // respecting firingIndex overrides and runtime changes
67 fired = firing = true;
68 for ( ; queue.length; firingIndex = -1 ) {
69 memory = queue.shift();
70 while ( ++firingIndex < list.length ) {
72 // Run callback and check for early termination
73 if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
74 options.stopOnFalse ) {
76 // Jump to end and forget the data so .add doesn't re-fire
77 firingIndex = list.length;
83 // Forget the data if we're done with it
84 if ( !options.memory ) {
90 // Clean up if we're done firing for good
93 // Keep an empty list if we have data for future add calls
97 // Otherwise, this object is spent
104 // Actual Callbacks object
107 // Add a callback or a collection of callbacks to the list
111 // If we have memory from a past run, we should fire after adding
112 if ( memory && !firing ) {
113 firingIndex = list.length - 1;
114 queue.push( memory );
117 (function add( args ) {
118 jQuery.each( args, function( _, arg ) {
119 if ( jQuery.isFunction( arg ) ) {
120 if ( !options.unique || !self.has( arg ) ) {
123 } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
124 // Inspect recursively
130 if ( memory && !firing ) {
137 // Remove a callback from the list
139 jQuery.each( arguments, function( _, arg ) {
141 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
142 list.splice( index, 1 );
144 // Handle firing indexes
145 if ( index <= firingIndex ) {
153 // Check if a given callback is in the list.
154 // If no argument is given, return whether or not list has callbacks attached.
155 has: function( fn ) {
157 jQuery.inArray( fn, list ) > -1 :
161 // Remove all callbacks from the list
169 // Disable .fire and .add
170 // Abort any current/pending executions
171 // Clear all callbacks and values
172 disable: function() {
177 disabled: function() {
182 // Also disable .add unless we have memory (since it would have no effect)
183 // Abort any pending executions
186 if ( !memory && !firing ) {
195 // Call all callbacks with the given context and arguments
196 fireWith: function( context, args ) {
199 args = [ context, args.slice ? args.slice() : args ];
208 // Call all the callbacks with the given arguments
210 self.fireWith( this, arguments );
214 // To know if the callbacks have already been called at least once