0
# Callback Management
1
2
Flexible callback list management for event handling and plugin development. The Callbacks system provides a powerful way to manage lists of callbacks with configurable behavior patterns.
3
4
## Capabilities
5
6
### Callback List Creation
7
8
Create callback lists with configurable options to control firing behavior.
9
10
```javascript { .api }
11
/**
12
* Create a callback list with configurable options
13
* @param options - Configuration string (space-separated flags)
14
* @returns Callbacks object for managing callback lists
15
*/
16
$.Callbacks(options);
17
```
18
19
**Configuration Options:**
20
- `once` - Callbacks can only be fired once
21
- `memory` - Remember previous fire arguments for new callbacks
22
- `unique` - Prevent duplicate callbacks from being added
23
- `stopOnFalse` - Stop firing when a callback returns false
24
25
### Callback Management Methods
26
27
Methods for adding, removing, and controlling callbacks.
28
29
```javascript { .api }
30
/**
31
* Add callback function(s) to the list
32
* @param callbacks - One or more callback functions
33
* @returns Callbacks object for chaining
34
*/
35
$.fn.add(...callbacks);
36
37
/**
38
* Remove callback function(s) from the list
39
* @param callbacks - One or more callback functions to remove
40
* @returns Callbacks object for chaining
41
*/
42
$.fn.remove(...callbacks);
43
44
/**
45
* Check if callback function exists in the list
46
* @param callback - Optional specific callback to check for
47
* @returns Boolean indicating presence of callback(s)
48
*/
49
$.fn.has(callback);
50
51
/**
52
* Remove all callbacks from the list
53
* @returns Callbacks object for chaining
54
*/
55
$.fn.empty();
56
```
57
58
### Callback Firing Methods
59
60
Methods for executing callbacks with different contexts and arguments.
61
62
```javascript { .api }
63
/**
64
* Fire all callbacks with given arguments
65
* @param args - Arguments to pass to callbacks
66
* @returns Callbacks object for chaining
67
*/
68
$.fn.fire(...args);
69
70
/**
71
* Fire all callbacks with specific context and arguments
72
* @param context - Context (this) for callback execution
73
* @param args - Arguments array to pass to callbacks
74
* @returns Callbacks object for chaining
75
*/
76
$.fn.fireWith(context, args);
77
78
/**
79
* Check if callbacks have been fired at least once
80
* @returns Boolean indicating if fire() has been called
81
*/
82
$.fn.fired();
83
```
84
85
### State Control Methods
86
87
Methods for controlling the state and behavior of the callback list.
88
89
```javascript { .api }
90
/**
91
* Disable the callback list (no more firing)
92
* @returns Callbacks object for chaining
93
*/
94
$.fn.disable();
95
96
/**
97
* Check if the callback list is disabled
98
* @returns Boolean indicating disabled state
99
*/
100
$.fn.disabled();
101
102
/**
103
* Lock the callback list (no more callbacks can be added)
104
* @returns Callbacks object for chaining
105
*/
106
$.fn.lock();
107
108
/**
109
* Check if the callback list is locked
110
* @returns Boolean indicating locked state
111
*/
112
$.fn.locked();
113
```
114
115
## Usage Examples
116
117
### Basic Callback Management
118
119
```javascript
120
// Create a basic callback list
121
const callbacks = $.Callbacks();
122
123
// Define some callback functions
124
function logMessage(message) {
125
console.log('Log:', message);
126
}
127
128
function alertMessage(message) {
129
alert('Alert: ' + message);
130
}
131
132
function processMessage(message) {
133
return message.toUpperCase();
134
}
135
136
// Add callbacks to the list
137
callbacks.add(logMessage, alertMessage);
138
139
// Fire all callbacks
140
callbacks.fire('Hello World');
141
// Output: "Log: Hello World" and alert dialog
142
143
// Add more callbacks
144
callbacks.add(processMessage);
145
146
// Fire again
147
callbacks.fire('Another message');
148
// All three callbacks execute
149
```
150
151
### Memory Option
152
153
```javascript
154
// Create callback list with memory
155
const memoryCallbacks = $.Callbacks('memory');
156
157
// Add initial callback and fire
158
memoryCallbacks.add((msg) => console.log('First:', msg));
159
memoryCallbacks.fire('Initial message');
160
161
// Add callback later - it immediately receives the last fired arguments
162
memoryCallbacks.add((msg) => console.log('Second:', msg));
163
// Immediately outputs: "Second: Initial message"
164
165
// Fire again - both callbacks execute
166
memoryCallbacks.fire('New message');
167
// Outputs: "First: New message" and "Second: New message"
168
```
169
170
### Once Option
171
172
```javascript
173
// Create callback list that fires only once
174
const onceCallbacks = $.Callbacks('once');
175
176
onceCallbacks.add(
177
() => console.log('First execution'),
178
() => console.log('Also first execution')
179
);
180
181
onceCallbacks.fire();
182
// Outputs both messages
183
184
onceCallbacks.fire();
185
// No output - callbacks already fired once
186
187
// Adding new callbacks after firing has no effect with 'once'
188
onceCallbacks.add(() => console.log('Will not execute'));
189
onceCallbacks.fire(); // Still no output
190
```
191
192
### Unique Option
193
194
```javascript
195
// Create callback list that prevents duplicates
196
const uniqueCallbacks = $.Callbacks('unique');
197
198
function duplicateCallback() {
199
console.log('This will only be added once');
200
}
201
202
uniqueCallbacks.add(duplicateCallback);
203
uniqueCallbacks.add(duplicateCallback); // Ignored due to 'unique'
204
uniqueCallbacks.add(duplicateCallback); // Also ignored
205
206
uniqueCallbacks.fire();
207
// Only executes once despite multiple add() calls
208
```
209
210
### StopOnFalse Option
211
212
```javascript
213
// Create callback list that stops when a callback returns false
214
const stoppableCallbacks = $.Callbacks('stopOnFalse');
215
216
stoppableCallbacks.add(
217
() => { console.log('First callback'); return true; },
218
() => { console.log('Second callback'); return false; },
219
() => { console.log('Third callback - will not execute'); return true; }
220
);
221
222
stoppableCallbacks.fire();
223
// Outputs: "First callback" and "Second callback"
224
// Third callback doesn't execute because second returned false
225
```
226
227
### Combined Options
228
229
```javascript
230
// Combine multiple options
231
const advancedCallbacks = $.Callbacks('once memory unique stopOnFalse');
232
233
function validator1(data) {
234
console.log('Validating format...');
235
return data && data.length > 0;
236
}
237
238
function validator2(data) {
239
console.log('Validating content...');
240
return data && !data.includes('invalid');
241
}
242
243
function validator3(data) {
244
console.log('This runs only if previous validators pass');
245
return true;
246
}
247
248
// Add validators (unique prevents duplicates)
249
advancedCallbacks.add(validator1, validator2, validator3);
250
advancedCallbacks.add(validator1); // Ignored due to 'unique'
251
252
// Fire validation (once + memory + stopOnFalse)
253
const result = advancedCallbacks.fire('valid data');
254
console.log('All validators passed');
255
256
// Later callbacks added will receive memory of last fire
257
advancedCallbacks.add((data) => {
258
console.log('Late validator received:', data);
259
});
260
```
261
262
### Context and Arguments
263
264
```javascript
265
// Using fireWith for specific context
266
const contextCallbacks = $.Callbacks();
267
268
function contextualCallback(message) {
269
console.log(`${this.name} says: ${message}`);
270
}
271
272
contextCallbacks.add(contextualCallback);
273
274
// Fire with specific context
275
const speaker1 = { name: 'Alice' };
276
const speaker2 = { name: 'Bob' };
277
278
contextCallbacks.fireWith(speaker1, ['Hello from Alice']);
279
// Output: "Alice says: Hello from Alice"
280
281
contextCallbacks.fireWith(speaker2, ['Hello from Bob']);
282
// Output: "Bob says: Hello from Bob"
283
```
284
285
### State Management
286
287
```javascript
288
const stateCallbacks = $.Callbacks();
289
290
// Add callbacks
291
stateCallbacks.add(() => console.log('Callback 1'));
292
stateCallbacks.add(() => console.log('Callback 2'));
293
294
console.log('Has callbacks:', stateCallbacks.has()); // true
295
console.log('Fired:', stateCallbacks.fired()); // false
296
console.log('Disabled:', stateCallbacks.disabled()); // false
297
console.log('Locked:', stateCallbacks.locked()); // false
298
299
// Fire callbacks
300
stateCallbacks.fire();
301
console.log('Fired after fire():', stateCallbacks.fired()); // true
302
303
// Lock the list (no more adding)
304
stateCallbacks.lock();
305
console.log('Locked after lock():', stateCallbacks.locked()); // true
306
307
stateCallbacks.add(() => console.log('Will not be added')); // Ignored
308
stateCallbacks.fire(); // Still works
309
310
// Disable the list (no more firing)
311
stateCallbacks.disable();
312
console.log('Disabled after disable():', stateCallbacks.disabled()); // true
313
314
stateCallbacks.fire(); // Ignored - list is disabled
315
```
316
317
### Practical Use Cases
318
319
#### Event System Implementation
320
321
```javascript
322
// Simple event system using callbacks
323
function EventEmitter() {
324
this.events = {};
325
}
326
327
EventEmitter.prototype.on = function(event, callback) {
328
if (!this.events[event]) {
329
this.events[event] = $.Callbacks('memory unique');
330
}
331
this.events[event].add(callback);
332
return this;
333
};
334
335
EventEmitter.prototype.off = function(event, callback) {
336
if (this.events[event]) {
337
this.events[event].remove(callback);
338
}
339
return this;
340
};
341
342
EventEmitter.prototype.emit = function(event, ...args) {
343
if (this.events[event]) {
344
this.events[event].fire(...args);
345
}
346
return this;
347
};
348
349
// Usage
350
const emitter = new EventEmitter();
351
emitter.on('data', (data) => console.log('Received:', data));
352
emitter.emit('data', { value: 123 });
353
```
354
355
#### Plugin Hook System
356
357
```javascript
358
// Plugin system with hooks
359
const PluginSystem = {
360
hooks: {},
361
362
addHook(hookName, callback, options = '') {
363
if (!this.hooks[hookName]) {
364
this.hooks[hookName] = $.Callbacks(options);
365
}
366
this.hooks[hookName].add(callback);
367
},
368
369
runHook(hookName, ...args) {
370
if (this.hooks[hookName]) {
371
return this.hooks[hookName].fire(...args);
372
}
373
},
374
375
removeHook(hookName, callback) {
376
if (this.hooks[hookName]) {
377
this.hooks[hookName].remove(callback);
378
}
379
}
380
};
381
382
// Plugins can register hooks
383
PluginSystem.addHook('beforeSave', (data) => {
384
console.log('Validating data before save');
385
return data.isValid;
386
}, 'stopOnFalse');
387
388
PluginSystem.addHook('afterSave', (result) => {
389
console.log('Data saved successfully');
390
});
391
392
// Application uses hooks
393
function saveData(data) {
394
// Run pre-save hooks
395
const canSave = PluginSystem.runHook('beforeSave', data);
396
397
if (canSave) {
398
// Simulate save
399
const result = { success: true, id: Date.now() };
400
401
// Run post-save hooks
402
PluginSystem.runHook('afterSave', result);
403
404
return result;
405
}
406
}
407
```