Ensures a list with memory will not called further callbacks before the next fire/fireWith is in stopOnFalse mode and a callback returned false. Unit tests added.

This commit is contained in:
jaubourg 2011-05-09 00:40:45 +02:00
parent 8dcf7ec1ce
commit ebb39c2774
2 changed files with 36 additions and 28 deletions

View file

@ -113,8 +113,9 @@ jQuery.Callbacks = function( flags, filter ) {
firingLength = list.length; firingLength = list.length;
} }
// With memory, if we're not firing then // With memory, if we're not firing then
// we should call right away // we should call right away, unless previous
} else if ( flags.memory && memory ) { // firing was halted (stopOnFalse)
} else if ( memory && memory !== true ) {
var tmp = memory; var tmp = memory;
memory = undefined; memory = undefined;
firingStart = length; firingStart = length;
@ -179,7 +180,7 @@ jQuery.Callbacks = function( flags, filter ) {
// Lock the list in its current state // Lock the list in its current state
lock: function() { lock: function() {
stack = undefined; stack = undefined;
if ( !memory ) { if ( !memory || memory === true ) {
object.disable(); object.disable();
} }
return this; return this;
@ -197,13 +198,14 @@ jQuery.Callbacks = function( flags, filter ) {
} }
} else if ( !( flags.once && memory ) ) { } else if ( !( flags.once && memory ) ) {
args = args || []; args = args || [];
memory = [ context, args ]; memory = !flags.memory || [ context, args ];
firing = true; firing = true;
firingIndex = firingStart || 0; firingIndex = firingStart || 0;
firingStart = 0; firingStart = 0;
firingLength = list.length; firingLength = list.length;
for ( ; list && firingIndex < firingLength; firingIndex++ ) { for ( ; list && firingIndex < firingLength; firingIndex++ ) {
if ( list[ firingIndex ][ 1 ].apply( context, args ) === false && flags.stopOnFalse ) { if ( list[ firingIndex ][ 1 ].apply( context, args ) === false && flags.stopOnFalse ) {
memory = true; // Mark as halted
break; break;
} }
} }
@ -214,7 +216,7 @@ jQuery.Callbacks = function( flags, filter ) {
memory = stack.shift(); memory = stack.shift();
object.fireWith( memory[ 0 ], memory[ 1 ] ); object.fireWith( memory[ 0 ], memory[ 1 ] );
} }
} else if ( !flags.memory ) { } else if ( memory === true ) {
object.disable(); object.disable();
} else { } else {
list = []; list = [];

View file

@ -12,28 +12,28 @@ var output,
outputB = addToOutput( "B" ), outputB = addToOutput( "B" ),
outputC = addToOutput( "C" ), outputC = addToOutput( "C" ),
tests = { tests = {
"": "XABC X XABCABCC X XBB X XABA", "": "XABC X XABCABCC X XBB X XABA X",
"once": "XABC X X X X X XABA", "once": "XABC X X X X X XABA X",
"memory": "XABC XABC XABCABCCC XA XBB XB XABA", "memory": "XABC XABC XABCABCCC XA XBB XB XABA XC",
"unique": "XABC X XABCA X XBB X XAB", "unique": "XABC X XABCA X XBB X XAB X",
"relocate": "XABC X XAABC X XBB X XBA", "relocate": "XABC X XAABC X XBB X XBA X",
"stopOnFalse": "XABC X XABCABCC X XBB X XA", "stopOnFalse": "XABC X XABCABCC X XBB X XA X",
"addAfterFire": "XAB X XABCAB X XBB X XABA", "addAfterFire": "XAB X XABCAB X XBB X XABA X",
"once memory": "XABC XABC X XA X XA XABA", "once memory": "XABC XABC X XA X XA XABA XC",
"once unique": "XABC X X X X X XAB", "once unique": "XABC X X X X X XAB X",
"once relocate": "XABC X X X X X XBA", "once relocate": "XABC X X X X X XBA X",
"once stopOnFalse": "XABC X X X X X XA", "once stopOnFalse": "XABC X X X X X XA X",
"once addAfterFire": "XAB X X X X X XABA", "once addAfterFire": "XAB X X X X X XABA X",
"memory unique": "XABC XA XABCA XA XBB XB XAB", "memory unique": "XABC XA XABCA XA XBB XB XAB XC",
"memory relocate": "XABC XB XAABC XA XBB XB XBA", "memory relocate": "XABC XB XAABC XA XBB XB XBA XC",
"memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA", "memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA X",
"memory addAfterFire": "XAB XAB XABCABC XA XBB XB XABA", "memory addAfterFire": "XAB XAB XABCABC XA XBB XB XABA XC",
"unique relocate": "XABC X XAABC X XBB X XBA", "unique relocate": "XABC X XAABC X XBB X XBA X",
"unique stopOnFalse": "XABC X XABCA X XBB X XA", "unique stopOnFalse": "XABC X XABCA X XBB X XA X",
"unique addAfterFire": "XAB X XABCA X XBB X XAB", "unique addAfterFire": "XAB X XABCA X XBB X XAB X",
"relocate stopOnFalse": "XABC X XAABC X XBB X X", "relocate stopOnFalse": "XABC X XAABC X XBB X X X",
"relocate addAfterFire": "XAB X XAA X XBB X XBA", "relocate addAfterFire": "XAB X XAA X XBB X XBA X",
"stopOnFalse addAfterFire": "XAB X XABCAB X XBB X XA" "stopOnFalse addAfterFire": "XAB X XABCAB X XBB X XA X"
}, },
filters = { filters = {
"no filter": undefined, "no filter": undefined,
@ -50,7 +50,7 @@ jQuery.each( tests, function( flags, resultString ) {
test( "jQuery.Callbacks( \"" + flags + "\" ) - " + filterLabel, function() { test( "jQuery.Callbacks( \"" + flags + "\" ) - " + filterLabel, function() {
expect( 18 ); expect( 19 );
// Give qunit a little breathing room // Give qunit a little breathing room
stop(); stop();
@ -182,6 +182,12 @@ jQuery.each( tests, function( flags, resultString ) {
cblist.add( outputA ); cblist.add( outputA );
cblist.fire(); cblist.fire();
strictEqual( output, results.shift(), "Callback returning false" ); strictEqual( output, results.shift(), "Callback returning false" );
// Add another callback (to control lists with memory do not fire anymore)
output = "X";
cblist.add( outputC );
strictEqual( output, results.shift(), "Adding a callback after one returned false" );
}); });
}); });
}); });