Project

General

Profile

1
define( [
2
	"./core",
3
	"./var/rnothtmlwhite"
4
], function( jQuery, rnothtmlwhite ) {
5

    
6
"use strict";
7

    
8
// Convert String-formatted options into Object-formatted ones
9
function createOptions( options ) {
10
	var object = {};
11
	jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
12
		object[ flag ] = true;
13
	} );
14
	return object;
15
}
16

    
17
/*
18
 * Create a callback list using the following parameters:
19
 *
20
 *	options: an optional list of space-separated options that will change how
21
 *			the callback list behaves or a more traditional option object
22
 *
23
 * By default a callback list will act like an event callback list and can be
24
 * "fired" multiple times.
25
 *
26
 * Possible options:
27
 *
28
 *	once:			will ensure the callback list can only be fired once (like a Deferred)
29
 *
30
 *	memory:			will keep track of previous values and will call any callback added
31
 *					after the list has been fired right away with the latest "memorized"
32
 *					values (like a Deferred)
33
 *
34
 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
35
 *
36
 *	stopOnFalse:	interrupt callings when a callback returns false
37
 *
38
 */
39
jQuery.Callbacks = function( options ) {
40

    
41
	// Convert options from String-formatted to Object-formatted if needed
42
	// (we check in cache first)
43
	options = typeof options === "string" ?
44
		createOptions( options ) :
45
		jQuery.extend( {}, options );
46

    
47
	var // Flag to know if list is currently firing
48
		firing,
49

    
50
		// Last fire value for non-forgettable lists
51
		memory,
52

    
53
		// Flag to know if list was already fired
54
		fired,
55

    
56
		// Flag to prevent firing
57
		locked,
58

    
59
		// Actual callback list
60
		list = [],
61

    
62
		// Queue of execution data for repeatable lists
63
		queue = [],
64

    
65
		// Index of currently firing callback (modified by add/remove as needed)
66
		firingIndex = -1,
67

    
68
		// Fire callbacks
69
		fire = function() {
70

    
71
			// Enforce single-firing
72
			locked = locked || options.once;
73

    
74
			// Execute callbacks for all pending executions,
75
			// respecting firingIndex overrides and runtime changes
76
			fired = firing = true;
77
			for ( ; queue.length; firingIndex = -1 ) {
78
				memory = queue.shift();
79
				while ( ++firingIndex < list.length ) {
80

    
81
					// Run callback and check for early termination
82
					if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
83
						options.stopOnFalse ) {
84

    
85
						// Jump to end and forget the data so .add doesn't re-fire
86
						firingIndex = list.length;
87
						memory = false;
88
					}
89
				}
90
			}
91

    
92
			// Forget the data if we're done with it
93
			if ( !options.memory ) {
94
				memory = false;
95
			}
96

    
97
			firing = false;
98

    
99
			// Clean up if we're done firing for good
100
			if ( locked ) {
101

    
102
				// Keep an empty list if we have data for future add calls
103
				if ( memory ) {
104
					list = [];
105

    
106
				// Otherwise, this object is spent
107
				} else {
108
					list = "";
109
				}
110
			}
111
		},
112

    
113
		// Actual Callbacks object
114
		self = {
115

    
116
			// Add a callback or a collection of callbacks to the list
117
			add: function() {
118
				if ( list ) {
119

    
120
					// If we have memory from a past run, we should fire after adding
121
					if ( memory && !firing ) {
122
						firingIndex = list.length - 1;
123
						queue.push( memory );
124
					}
125

    
126
					( function add( args ) {
127
						jQuery.each( args, function( _, arg ) {
128
							if ( jQuery.isFunction( arg ) ) {
129
								if ( !options.unique || !self.has( arg ) ) {
130
									list.push( arg );
131
								}
132
							} else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
133

    
134
								// Inspect recursively
135
								add( arg );
136
							}
137
						} );
138
					} )( arguments );
139

    
140
					if ( memory && !firing ) {
141
						fire();
142
					}
143
				}
144
				return this;
145
			},
146

    
147
			// Remove a callback from the list
148
			remove: function() {
149
				jQuery.each( arguments, function( _, arg ) {
150
					var index;
151
					while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
152
						list.splice( index, 1 );
153

    
154
						// Handle firing indexes
155
						if ( index <= firingIndex ) {
156
							firingIndex--;
157
						}
158
					}
159
				} );
160
				return this;
161
			},
162

    
163
			// Check if a given callback is in the list.
164
			// If no argument is given, return whether or not list has callbacks attached.
165
			has: function( fn ) {
166
				return fn ?
167
					jQuery.inArray( fn, list ) > -1 :
168
					list.length > 0;
169
			},
170

    
171
			// Remove all callbacks from the list
172
			empty: function() {
173
				if ( list ) {
174
					list = [];
175
				}
176
				return this;
177
			},
178

    
179
			// Disable .fire and .add
180
			// Abort any current/pending executions
181
			// Clear all callbacks and values
182
			disable: function() {
183
				locked = queue = [];
184
				list = memory = "";
185
				return this;
186
			},
187
			disabled: function() {
188
				return !list;
189
			},
190

    
191
			// Disable .fire
192
			// Also disable .add unless we have memory (since it would have no effect)
193
			// Abort any pending executions
194
			lock: function() {
195
				locked = queue = [];
196
				if ( !memory && !firing ) {
197
					list = memory = "";
198
				}
199
				return this;
200
			},
201
			locked: function() {
202
				return !!locked;
203
			},
204

    
205
			// Call all callbacks with the given context and arguments
206
			fireWith: function( context, args ) {
207
				if ( !locked ) {
208
					args = args || [];
209
					args = [ context, args.slice ? args.slice() : args ];
210
					queue.push( args );
211
					if ( !firing ) {
212
						fire();
213
					}
214
				}
215
				return this;
216
			},
217

    
218
			// Call all the callbacks with the given arguments
219
			fire: function() {
220
				self.fireWith( this, arguments );
221
				return this;
222
			},
223

    
224
			// To know if the callbacks have already been called at least once
225
			fired: function() {
226
				return !!fired;
227
			}
228
		};
229

    
230
	return self;
231
};
232

    
233
return jQuery;
234
} );
(4-4/22)