Skip to content

Commit 8dcf7ec

Browse files
committed
Adds addAfterFire flag. Unit tests updated with addAfterFire cases and also for when a callback returns false.
1 parent 946a920 commit 8dcf7ec

File tree

2 files changed

+53
-23
lines changed

2 files changed

+53
-23
lines changed

src/callbacks.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ function createFlags( flags ) {
4040
*
4141
* stopOnFalse: interrupt callings when a callback returns false
4242
*
43+
* addAfterFire: if callbacks are added while firing, then they are not executed until after
44+
* the next call to fire/fireWith
45+
*
4346
*/
4447
jQuery.Callbacks = function( flags, filter ) {
4548

@@ -63,6 +66,8 @@ jQuery.Callbacks = function( flags, filter ) {
6366
firing,
6467
// First callback to fire (used internally by add and fireWith)
6568
firingStart,
69+
// End of the loop when firing
70+
firingLength,
6671
// Index of currently firing callback (modified by remove if needed)
6772
firingIndex,
6873
// Add a list of callbacks to the list
@@ -101,9 +106,15 @@ jQuery.Callbacks = function( flags, filter ) {
101106
if ( list ) {
102107
var length = list.length;
103108
add( arguments );
109+
// Do we need to add the callbacks to the
110+
// current firing batch?
111+
if ( firing ) {
112+
if ( !flags.addAfterFire ) {
113+
firingLength = list.length;
114+
}
104115
// With memory, if we're not firing then
105116
// we should call right away
106-
if ( !firing && flags.memory && memory ) {
117+
} else if ( flags.memory && memory ) {
107118
var tmp = memory;
108119
memory = undefined;
109120
firingStart = length;
@@ -117,9 +128,14 @@ jQuery.Callbacks = function( flags, filter ) {
117128
if ( list ) {
118129
for ( var i = 0; i < list.length; i++ ) {
119130
if ( fn === list[ i ][ 0 ] ) {
120-
// Handle firingIndex
121-
if ( firing && i <= firingIndex ) {
122-
firingIndex--;
131+
// Handle firingIndex and firingLength
132+
if ( firing ) {
133+
if ( i <= firingLength ) {
134+
firingLength--;
135+
if ( i <= firingIndex ) {
136+
firingIndex--;
137+
}
138+
}
123139
}
124140
// Remove the element
125141
list.splice( i--, 1 );
@@ -185,7 +201,8 @@ jQuery.Callbacks = function( flags, filter ) {
185201
firing = true;
186202
firingIndex = firingStart || 0;
187203
firingStart = 0;
188-
for ( ; list && firingIndex < list.length; firingIndex++ ) {
204+
firingLength = list.length;
205+
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
189206
if ( list[ firingIndex ][ 1 ].apply( context, args ) === false && flags.stopOnFalse ) {
190207
break;
191208
}

test/unit/callbacks.js

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,28 @@ var output,
1212
outputB = addToOutput( "B" ),
1313
outputC = addToOutput( "C" ),
1414
tests = {
15-
"": "X XABCABCC X XBB X",
16-
"once": "X X X X X",
17-
"memory": "XABC XABCABCCC XA XBB XB",
18-
"unique": "X XABCA X XBB X",
19-
"relocate": "X XAABC X XBB X",
20-
"stopOnFalse": "X XABCABCC X XBB X",
21-
"once memory": "XABC X XA X XA",
22-
"once unique": "X X X X X",
23-
"once relocate": "X X X X X",
24-
"once stopOnFalse": "X X X X X",
25-
"memory unique": "XA XABCA XA XBB XB",
26-
"memory relocate": "XB XAABC XA XBB XB",
27-
"memory stopOnFalse": "XABC XABCABCCC XA XBB XB",
28-
"unique relocate": "X XAABC X XBB X",
29-
"unique stopOnFalse": "X XABCA X XBB X",
30-
"relocate stopOnFalse": "X XAABC X XBB X"
15+
"": "XABC X XABCABCC X XBB X XABA",
16+
"once": "XABC X X X X X XABA",
17+
"memory": "XABC XABC XABCABCCC XA XBB XB XABA",
18+
"unique": "XABC X XABCA X XBB X XAB",
19+
"relocate": "XABC X XAABC X XBB X XBA",
20+
"stopOnFalse": "XABC X XABCABCC X XBB X XA",
21+
"addAfterFire": "XAB X XABCAB X XBB X XABA",
22+
"once memory": "XABC XABC X XA X XA XABA",
23+
"once unique": "XABC X X X X X XAB",
24+
"once relocate": "XABC X X X X X XBA",
25+
"once stopOnFalse": "XABC X X X X X XA",
26+
"once addAfterFire": "XAB X X X X X XABA",
27+
"memory unique": "XABC XA XABCA XA XBB XB XAB",
28+
"memory relocate": "XABC XB XAABC XA XBB XB XBA",
29+
"memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA",
30+
"memory addAfterFire": "XAB XAB XABCABC XA XBB XB XABA",
31+
"unique relocate": "XABC X XAABC X XBB X XBA",
32+
"unique stopOnFalse": "XABC X XABCA X XBB X XA",
33+
"unique addAfterFire": "XAB X XABCA X XBB X XAB",
34+
"relocate stopOnFalse": "XABC X XAABC X XBB X X",
35+
"relocate addAfterFire": "XAB X XAA X XBB X XBA",
36+
"stopOnFalse addAfterFire": "XAB X XABCAB X XBB X XA"
3137
},
3238
filters = {
3339
"no filter": undefined,
@@ -44,7 +50,7 @@ jQuery.each( tests, function( flags, resultString ) {
4450

4551
test( "jQuery.Callbacks( \"" + flags + "\" ) - " + filterLabel, function() {
4652

47-
expect( 17 );
53+
expect( 18 );
4854

4955
// Give qunit a little breathing room
5056
stop();
@@ -133,7 +139,7 @@ jQuery.each( tests, function( flags, resultString ) {
133139
outputA();
134140
}, outputB );
135141
cblist.fire();
136-
strictEqual( output, "XABC", "Proper ordering" );
142+
strictEqual( output, results.shift(), "Proper ordering" );
137143

138144
// Add and fire again
139145
output = "X";
@@ -169,6 +175,13 @@ jQuery.each( tests, function( flags, resultString ) {
169175
} );
170176
strictEqual( output, results.shift(), "Multiple fire (second new callback)" );
171177

178+
// Return false
179+
output = "X";
180+
cblist = jQuery.Callbacks( flags );
181+
cblist.add( outputA, function() { return false; }, outputB );
182+
cblist.add( outputA );
183+
cblist.fire();
184+
strictEqual( output, results.shift(), "Callback returning false" );
172185
});
173186
});
174187
});

0 commit comments

Comments
 (0)