0
|
1 define( [
|
|
2 "./core",
|
|
3 "./core/toType",
|
|
4 "./var/isFunction",
|
|
5 "./var/rnothtmlwhite"
|
|
6 ], function( jQuery, toType, isFunction, rnothtmlwhite ) {
|
|
7
|
|
8 "use strict";
|
|
9
|
|
10 // Convert String-formatted options into Object-formatted ones
|
|
11 function createOptions( options ) {
|
|
12 var object = {};
|
|
13 jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
|
|
14 object[ flag ] = true;
|
|
15 } );
|
|
16 return object;
|
|
17 }
|
|
18
|
|
19 /*
|
|
20 * Create a callback list using the following parameters:
|
|
21 *
|
|
22 * options: an optional list of space-separated options that will change how
|
|
23 * the callback list behaves or a more traditional option object
|
|
24 *
|
|
25 * By default a callback list will act like an event callback list and can be
|
|
26 * "fired" multiple times.
|
|
27 *
|
|
28 * Possible options:
|
|
29 *
|
|
30 * once: will ensure the callback list can only be fired once (like a Deferred)
|
|
31 *
|
|
32 * memory: will keep track of previous values and will call any callback added
|
|
33 * after the list has been fired right away with the latest "memorized"
|
|
34 * values (like a Deferred)
|
|
35 *
|
|
36 * unique: will ensure a callback can only be added once (no duplicate in the list)
|
|
37 *
|
|
38 * stopOnFalse: interrupt callings when a callback returns false
|
|
39 *
|
|
40 */
|
|
41 jQuery.Callbacks = function( options ) {
|
|
42
|
|
43 // Convert options from String-formatted to Object-formatted if needed
|
|
44 // (we check in cache first)
|
|
45 options = typeof options === "string" ?
|
|
46 createOptions( options ) :
|
|
47 jQuery.extend( {}, options );
|
|
48
|
|
49 var // Flag to know if list is currently firing
|
|
50 firing,
|
|
51
|
|
52 // Last fire value for non-forgettable lists
|
|
53 memory,
|
|
54
|
|
55 // Flag to know if list was already fired
|
|
56 fired,
|
|
57
|
|
58 // Flag to prevent firing
|
|
59 locked,
|
|
60
|
|
61 // Actual callback list
|
|
62 list = [],
|
|
63
|
|
64 // Queue of execution data for repeatable lists
|
|
65 queue = [],
|
|
66
|
|
67 // Index of currently firing callback (modified by add/remove as needed)
|
|
68 firingIndex = -1,
|
|
69
|
|
70 // Fire callbacks
|
|
71 fire = function() {
|
|
72
|
|
73 // Enforce single-firing
|
|
74 locked = locked || options.once;
|
|
75
|
|
76 // Execute callbacks for all pending executions,
|
|
77 // respecting firingIndex overrides and runtime changes
|
|
78 fired = firing = true;
|
|
79 for ( ; queue.length; firingIndex = -1 ) {
|
|
80 memory = queue.shift();
|
|
81 while ( ++firingIndex < list.length ) {
|
|
82
|
|
83 // Run callback and check for early termination
|
|
84 if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
|
|
85 options.stopOnFalse ) {
|
|
86
|
|
87 // Jump to end and forget the data so .add doesn't re-fire
|
|
88 firingIndex = list.length;
|
|
89 memory = false;
|
|
90 }
|
|
91 }
|
|
92 }
|
|
93
|
|
94 // Forget the data if we're done with it
|
|
95 if ( !options.memory ) {
|
|
96 memory = false;
|
|
97 }
|
|
98
|
|
99 firing = false;
|
|
100
|
|
101 // Clean up if we're done firing for good
|
|
102 if ( locked ) {
|
|
103
|
|
104 // Keep an empty list if we have data for future add calls
|
|
105 if ( memory ) {
|
|
106 list = [];
|
|
107
|
|
108 // Otherwise, this object is spent
|
|
109 } else {
|
|
110 list = "";
|
|
111 }
|
|
112 }
|
|
113 },
|
|
114
|
|
115 // Actual Callbacks object
|
|
116 self = {
|
|
117
|
|
118 // Add a callback or a collection of callbacks to the list
|
|
119 add: function() {
|
|
120 if ( list ) {
|
|
121
|
|
122 // If we have memory from a past run, we should fire after adding
|
|
123 if ( memory && !firing ) {
|
|
124 firingIndex = list.length - 1;
|
|
125 queue.push( memory );
|
|
126 }
|
|
127
|
|
128 ( function add( args ) {
|
|
129 jQuery.each( args, function( _, arg ) {
|
|
130 if ( isFunction( arg ) ) {
|
|
131 if ( !options.unique || !self.has( arg ) ) {
|
|
132 list.push( arg );
|
|
133 }
|
|
134 } else if ( arg && arg.length && toType( arg ) !== "string" ) {
|
|
135
|
|
136 // Inspect recursively
|
|
137 add( arg );
|
|
138 }
|
|
139 } );
|
|
140 } )( arguments );
|
|
141
|
|
142 if ( memory && !firing ) {
|
|
143 fire();
|
|
144 }
|
|
145 }
|
|
146 return this;
|
|
147 },
|
|
148
|
|
149 // Remove a callback from the list
|
|
150 remove: function() {
|
|
151 jQuery.each( arguments, function( _, arg ) {
|
|
152 var index;
|
|
153 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
|
|
154 list.splice( index, 1 );
|
|
155
|
|
156 // Handle firing indexes
|
|
157 if ( index <= firingIndex ) {
|
|
158 firingIndex--;
|
|
159 }
|
|
160 }
|
|
161 } );
|
|
162 return this;
|
|
163 },
|
|
164
|
|
165 // Check if a given callback is in the list.
|
|
166 // If no argument is given, return whether or not list has callbacks attached.
|
|
167 has: function( fn ) {
|
|
168 return fn ?
|
|
169 jQuery.inArray( fn, list ) > -1 :
|
|
170 list.length > 0;
|
|
171 },
|
|
172
|
|
173 // Remove all callbacks from the list
|
|
174 empty: function() {
|
|
175 if ( list ) {
|
|
176 list = [];
|
|
177 }
|
|
178 return this;
|
|
179 },
|
|
180
|
|
181 // Disable .fire and .add
|
|
182 // Abort any current/pending executions
|
|
183 // Clear all callbacks and values
|
|
184 disable: function() {
|
|
185 locked = queue = [];
|
|
186 list = memory = "";
|
|
187 return this;
|
|
188 },
|
|
189 disabled: function() {
|
|
190 return !list;
|
|
191 },
|
|
192
|
|
193 // Disable .fire
|
|
194 // Also disable .add unless we have memory (since it would have no effect)
|
|
195 // Abort any pending executions
|
|
196 lock: function() {
|
|
197 locked = queue = [];
|
|
198 if ( !memory && !firing ) {
|
|
199 list = memory = "";
|
|
200 }
|
|
201 return this;
|
|
202 },
|
|
203 locked: function() {
|
|
204 return !!locked;
|
|
205 },
|
|
206
|
|
207 // Call all callbacks with the given context and arguments
|
|
208 fireWith: function( context, args ) {
|
|
209 if ( !locked ) {
|
|
210 args = args || [];
|
|
211 args = [ context, args.slice ? args.slice() : args ];
|
|
212 queue.push( args );
|
|
213 if ( !firing ) {
|
|
214 fire();
|
|
215 }
|
|
216 }
|
|
217 return this;
|
|
218 },
|
|
219
|
|
220 // Call all the callbacks with the given arguments
|
|
221 fire: function() {
|
|
222 self.fireWith( this, arguments );
|
|
223 return this;
|
|
224 },
|
|
225
|
|
226 // To know if the callbacks have already been called at least once
|
|
227 fired: function() {
|
|
228 return !!fired;
|
|
229 }
|
|
230 };
|
|
231
|
|
232 return self;
|
|
233 };
|
|
234
|
|
235 return jQuery;
|
|
236 } );
|