Project

General

Profile

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

    
6
// String to Object options format cache
7
var optionsCache = {};
8

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

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

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

    
48
	var // Last fire value (for non-forgettable lists)
49
		memory,
50
		// Flag to know if list was already fired
51
		fired,
52
		// Flag to know if list is currently firing
53
		firing,
54
		// First callback to fire (used internally by add and fireWith)
55
		firingStart,
56
		// End of the loop when firing
57
		firingLength,
58
		// Index of currently firing callback (modified by remove if needed)
59
		firingIndex,
60
		// Actual callback list
61
		list = [],
62
		// Stack of fire calls for repeatable lists
63
		stack = !options.once && [],
64
		// Fire callbacks
65
		fire = function( data ) {
66
			memory = options.memory && data;
67
			fired = true;
68
			firingIndex = firingStart || 0;
69
			firingStart = 0;
70
			firingLength = list.length;
71
			firing = true;
72
			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
73
				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
74
					memory = false; // To prevent further calls using add
75
					break;
76
				}
77
			}
78
			firing = false;
79
			if ( list ) {
80
				if ( stack ) {
81
					if ( stack.length ) {
82
						fire( stack.shift() );
83
					}
84
				} else if ( memory ) {
85
					list = [];
86
				} else {
87
					self.disable();
88
				}
89
			}
90
		},
91
		// Actual Callbacks object
92
		self = {
93
			// Add a callback or a collection of callbacks to the list
94
			add: function() {
95
				if ( list ) {
96
					// First, we save the current length
97
					var start = list.length;
98
					(function add( args ) {
99
						jQuery.each( args, function( _, arg ) {
100
							var type = jQuery.type( arg );
101
							if ( type === "function" ) {
102
								if ( !options.unique || !self.has( arg ) ) {
103
									list.push( arg );
104
								}
105
							} else if ( arg && arg.length && type !== "string" ) {
106
								// Inspect recursively
107
								add( arg );
108
							}
109
						});
110
					})( arguments );
111
					// Do we need to add the callbacks to the
112
					// current firing batch?
113
					if ( firing ) {
114
						firingLength = list.length;
115
					// With memory, if we're not firing then
116
					// we should call right away
117
					} else if ( memory ) {
118
						firingStart = start;
119
						fire( memory );
120
					}
121
				}
122
				return this;
123
			},
124
			// Remove a callback from the list
125
			remove: function() {
126
				if ( list ) {
127
					jQuery.each( arguments, function( _, arg ) {
128
						var index;
129
						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
130
							list.splice( index, 1 );
131
							// Handle firing indexes
132
							if ( firing ) {
133
								if ( index <= firingLength ) {
134
									firingLength--;
135
								}
136
								if ( index <= firingIndex ) {
137
									firingIndex--;
138
								}
139
							}
140
						}
141
					});
142
				}
143
				return this;
144
			},
145
			// Check if a given callback is in the list.
146
			// If no argument is given, return whether or not list has callbacks attached.
147
			has: function( fn ) {
148
				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
149
			},
150
			// Remove all callbacks from the list
151
			empty: function() {
152
				list = [];
153
				firingLength = 0;
154
				return this;
155
			},
156
			// Have the list do nothing anymore
157
			disable: function() {
158
				list = stack = memory = undefined;
159
				return this;
160
			},
161
			// Is it disabled?
162
			disabled: function() {
163
				return !list;
164
			},
165
			// Lock the list in its current state
166
			lock: function() {
167
				stack = undefined;
168
				if ( !memory ) {
169
					self.disable();
170
				}
171
				return this;
172
			},
173
			// Is it locked?
174
			locked: function() {
175
				return !stack;
176
			},
177
			// Call all callbacks with the given context and arguments
178
			fireWith: function( context, args ) {
179
				if ( list && ( !fired || stack ) ) {
180
					args = args || [];
181
					args = [ context, args.slice ? args.slice() : args ];
182
					if ( firing ) {
183
						stack.push( args );
184
					} else {
185
						fire( args );
186
					}
187
				}
188
				return this;
189
			},
190
			// Call all the callbacks with the given arguments
191
			fire: function() {
192
				self.fireWith( this, arguments );
193
				return this;
194
			},
195
			// To know if the callbacks have already been called at least once
196
			fired: function() {
197
				return !!fired;
198
			}
199
		};
200

    
201
	return self;
202
};
203

    
204
return jQuery;
205
});
(3-3/23)